Java mainstream symmetric / asymmetric encryption Daquan

1 Introduction

Encryption method is divided into symmetric encryption and asymmetric encryption, symmetric encryption except that only one key, asymmetrical encryption has two keys

  • Symmetric encryption and decryption: enccrypt (plain text, key) = ciphertext, the decrypt (ciphertext, key) = plaintext
  • Asymmetric encryption: encrypt (plaintext, public key) = ciphertext, the decrypt (ciphertext, private key) = plaintext

2. Key

2.1. Key Format

2.1.1.the

.der key, a key to be read as a stream of binary coded in JAVA. Here is an example to obtain the public key:

     /**
     * der公钥解密,密文Base64输出
       */
       public static PublicKey getPublicKeyByDer(InputStream is) throws Exception {
       try {
           if (certificatefactory == null) {
               certificatefactory = CertificateFactory.getInstance("X.509");
           }
           Certificate cert = certificatefactory.generateCertificate(is);
           return cert.getPublicKey();
       }finally {
           if (is != null) {
               is.close();
           }
       }
       }

2.1.2.pem

.pem to "----- BEGIN ..." at the beginning, "----- END ..." at the end, content is BASE64 encoding. Here is an example to obtain the public key:

 public static PublicKey getPublicKeyByPem(String publicKey) throws Exception {
       KeyFactory keyFactory = KeyFactory.getInstance("RSA");
       X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey));
       return keyFactory.generatePublic(keySpec);
   }

2.1.3.PKCS12

.p12PKCS # 12 certificate, simply put, it contains the certificate and private key, and allows password protection. Here is an example to obtain the private key:

     public static Key getP12Key() throws Exception{
       try (InputStream is = new FileInputStream( "xx.p12")) {
           if (certificatefactory == null) {
               certificatefactory = CertificateFactory.getInstance("X.509");
           }
           KeyStore keystore = KeyStore.getInstance("PKCS12");
           keystore.load(is, "p12证书的密码".toCharArray());
           Key key = keystore.getKey("p12证书的别名", "p12证书的密码".toCharArray());
           key.getAlgorithm();//密钥对应的加密算法,可以用在 Cipher.getInstance(key.getAlgorithm())
           return key;
       }
   }

2.1.4. Pure string

Key may be a string or a hexadecimal coding Base64 encoded, or even directly to a string, the key is to find ways to convert byte [] can generate the key.

RSA keys can be obtained in this manner:

 public static PublicKey getRSAPublicKey(byte[] publicKey) throws Exception {
       KeyFactory keyFactory = KeyFactory.getInstance("RSA");
       X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
       return keyFactory.generatePublic(keySpec);
   }

AES key can be obtained in this manner:

 public static Key getKey(byte[] key) throws Exception {
       return new SecretKeySpec(key, "AES");
   }

2.2. Type

  • X509EncodedKey

  • PKCS8EncodedKey

  • RSAPublicKey

  • RSAPrivateKey

  • DSAPublicKey

  • DSAPrivateKey

2.3. Length

  • 128bit
  • 256bit JAVA key length of the AES has a limit, a maximum of 128bit, i.e. 16-bit string. If the key is 256bit, i.e. 32-bit string of encryption and decryption can be modified by using the JRE or a document of CryptoJS AES method.

2.4. Key Encryption

  • PBKDF2WithHmacSHA1PBKDF2 (Password-Based Key Derivation Function) is a function used to derive the key, commonly employed to form encrypted password. Its basic principle is a pseudo-random function (e.g. HMAC function), and a salt value plaintext as an input parameter, operation is then repeated, and finally generate the key. If the number of repetitions is large enough to break the cost becomes high. And to add salt value will increase the difficulty of "rainbow table" attack.

The following is a JAVA realize PBKDF2WithHmacSHA1

   private static final String DEFAULT_ALGORITHM = "PBKDF2WithHmacSHA1";
   private static final int DEFAULT_ITERATIONS = 10000;
   private static final int DEFAULT_HASH_SIZE = 128;
   private static final byte[] DEFAULT_SALT = new byte[]{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
   
   public static byte[] hash(String key) throws Exception {
       char[] password = key.toCharArray();
       return hash(password, DEFAULT_ALGORITHM, DEFAULT_ITERATIONS, DEFAULT_HASH_SIZE, DEFAULT_SALT);
   }
 
   /**
     * @param password 密钥
     * @param algorithm 运算算法
     * @param iteration 进行重复计算的次数
     * @param hashSize 期望得到的密钥的长度
     * @param salt     盐值
     * @return 最后生成的密钥
     * @throws Exception 各种异常
     */
   public static byte[] hash(char[] password, String algorithm, int iteration, int hashSize, byte[] salt) throws Exception {
           SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
           PBEKeySpec spec = new PBEKeySpec(password, salt, iteration, hashSize);
           return skf.generateSecret(spec).getEncoded();
   }

3. Encryption Algorithm

3.1 Symmetric

3.1.1.DES

DES is a symmetric encryption inside a common one kind, called the Data Encryption Standard, i.e., Data Encryption Standard, a block key encryption algorithm. Key length is 64-bit (bit), exceeds the length of the key is ignored. The so-called symmetric encryption, the same encryption and decryption keys. Symmetric encryption generally a fixed length, the character string to be encrypted into blocks. Lack of a single piece or just the last special padding characters. Cross-language often do DES encryption and decryption, often problems occur. Often filled with the wrong way, or is inconsistent coding, or the selection result (ECB, CBC, CTR, OFB, CFB, NCFB, NOFB) no corresponding encryption and decryption mode. Filled with a common pattern: 'pkcs5', 'pkcs7', 'iso10126', 'ansix923', 'zero' types, including DES-ECB, DES-CBC, DES-CTR, DES-OFB, DES-CFB

 public static byte[] desEncrypt(byte[] data, byte[] key) throws Exception {
       Cipher cipher = Cipher.getInstance("DES");
       SecretKeySpec secretKeySpec = new SecretKeySpec(key, "DES");
       cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
       return cipher.doFinal(data);
   }

3.1.2.3DES

3DES (also known as Triple DES) is a generic term Triple Data Encryption Algorithm (TDEA, Triple Data Encryption Algorithm) block cipher. It corresponds to the triple DES encryption algorithm is applied to each data block. Key length is 128 bits, 192 ( 'bit), if the password is less than the number of bits is equal to 64, the same DES encryption result. Original easy to crack DES, 3DES emergence of new, increased encryption security, avoid brute force. It is also a symmetric encryption, the same encryption involves encoding, and filling mode. Comprising 3DES-ECB, 3DES-CBC, 3DES-CTR, 3DES-OFB, 3DES-CFB

 public static byte[] desedeEncrypt(byte[] data, byte[] key) throws Exception {
       Cipher cipher = Cipher.getInstance("DESede");
       SecretKeySpec secretKeySpec = new SecretKeySpec(key, "DESede");
       cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
       return cipher.doFinal(data);
   }

3.1.3. AES

AES, Advanced Encryption Standard (English: Advanced Encryption Standard, abbreviation: AES), in cryptography, also known as Rijndael encryption method, is a block encryption standard adopted by the US federal government. This standard is used to replace the original DES, it has been widely analyzed and multi- used around the world. Strictly speaking, AES Rijndael encryption method, and not exactly the same (although the two may be used interchangeably in practical applications), since the Rijndael encryption method and key blocks can support a wider range of length: fixed block length of AES 128 bits, the key length may be 128, 192 or 256 bits; Rijndael block length and the key and may be used in an integer multiple of 32, to 128 as a lower limit to an upper limit of 256 bits. Including AES-ECB, AES-CBC, AES-CTR, AES-OFB, AES-CFB

 public static byte[] aesEncrypt(byte[] data, byte[] key) throws Exception {
       Cipher cipher = Cipher.getInstance("AES");
       SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
       cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
       return cipher.doFinal(data);
   }

AES algorithm mode and padding There are several options, ECB and CBC offset need not be offset. NoPadding is not filled, this time manually encrypt or decrypt content to ensure the number of bytes is a multiple of 16; and PKCS7Padding PKCS5Padding are almost the same, can be generic, filled with stuffing bytes content length sequence, for example if the byte array length 15, only one needs to be filled up to 16, then filled with 0x1, if the length of 1 byte array, it is necessary to fill 15 0xf; ZeroPadding to be filled with 0x0.

Cipher.getInstance("AES/CBC/NoPadding");
Cipher.getInstance("AES/CBC/PKCS5Padding");
Cipher.getInstance("AES/CBC/PKCS7Padding");
Cipher.getInstance("AES/CBC/ZeroBytePadding");
Cipher.getInstance("AES/ECB/NoPadding");
Cipher.getInstance("AES/ECB/PKCS5Padding");
Cipher.getInstance("AES/ECB/PKCS7Padding");
Cipher.getInstance("AES/ECB/ZeroBytePadding");

Further, the key length of the AES are 128byte, 192byte, 256byte, respectively corresponding to the length of the string 16, 24, 32. When the key is greater than 128Byte, i.e. 16-bit string length, the code will be thrown java.security.InvalidKeyException: Illegal key size or default parameters. Illegal key size or default parameters refer to the key length is limited, java runtime environment read is restricted policy file. File is located in $ {java_home} / jre / lib / security, this limitation is because the United States controls the export of software. There are two solutions

- 替换${java_home}/jre/lib/security/ 下面的local_policy.jar和US_export_policy.jar。
- 使用CryptoJs,这是谷歌开源的用Js实现的AES加解密库,速度和原生JDK相差无几,除了第一次载入Js文件需要额外耗时。

3.1.4.RC4

RC4 encryption algorithm is RSA trio of top man in Ron Rivest key length of 1987 design variable stream encryption algorithm clusters. The speed of the algorithm can reach 10 times the DES encryption, and having a very high level of non-linear. In September 1994, its algorithm was posted on the Internet. Since the encryption algorithm RC4 xor is used, so that once the subkey repeated sequence occurs, the ciphertext is likely to be cracked. As an old RC4 authentication and encryption algorithms vulnerable to hacker attacks, it is now increasingly is not recommended for use.

 public static byte[] rc4Encrypt(byte[] data, byte[] key) throws Exception {
       Cipher cipher = Cipher.getInstance("RC4");
       SecretKeySpec secretKeySpec = new SecretKeySpec(key, "ARCFOUR");
       cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
       return cipher.doFinal(data);
   }

3.2. Asymmetric

3.2.1. RSA

Encryption and decryption keys are different, the private key is not generally disclosed, using the public key encryption and private key to decrypt, using a private key encryption, the public key can decrypt. And AES different, each encryption out of the result is not the same. And the need to perform packet encrypt, RSA-encrypt each group up to 117 byte length, each group of up to 128 decrypts byte length.

public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
       Cipher cipher = Cipher.getInstance("RSA");
       KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
       X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
       PublicKey key = keyFactory.generatePublic(keySpec);
       cipher.init(Cipher.ENCRYPT_MODE, key);
       //执行分组加密操作,RSA加密每一组最多117位长度
       int segment = 117;
       int inputLen = data.length;
       try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
           int offSet = 0;
           byte[] cache;
           int i = 0;
           // 对数据分段加密
           while (inputLen - offSet > 0) {
               if (inputLen - offSet > segment) {
                   cache = cipher.doFinal(data, offSet, segment);
               } else {
                   cache = cipher.doFinal(data, offSet, inputLen - offSet);
               }
               out.write(cache, 0, cache.length);
               i++;
               offSet = i * segment;
           }
           return out.toByteArray();
       }
   }
 
 public static byte[] encryptByPrivateKey(byte[] data, byte[] publicKey) throws Exception {
       Cipher cipher = Cipher.getInstance("RSA");
       KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
       X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
       PrivateKey key = keyFactory.generatePrivate(keySpec);
       cipher.init(Cipher.ENCRYPT_MODE, key);
       //执行分组加密操作,RSA加密每一组最多117位长度
       int segment = 117;
       int inputLen = data.length;
       try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
           int offSet = 0;
           byte[] cache;
           int i = 0;
           // 对数据分段加密
           while (inputLen - offSet > 0) {
               if (inputLen - offSet > segment) {
                   cache = cipher.doFinal(data, offSet, segment);
               } else {
                   cache = cipher.doFinal(data, offSet, inputLen - offSet);
               }
               out.write(cache, 0, cache.length);
               i++;
               offSet = i * segment;
           }
           return out.toByteArray();
       }
   }

3.3 Supplementary additional algorithm

Add rely BouncyCastle, and called once at program initialization

 Security.addProvider(new BouncyCastleProvider());

You can get more encryption algorithms Cipher.getInstance ( "") method.

4. Signature

4.1. Algorithms

4.1.1.SHA1withRSA

   /**
     * RSA签名
     *
     * @param content   待签名数据
     * @param privateKey 商户私钥
     * @param encode     字符集编码
     * @return 使用Base64编码的签名值
     */
   public static String sign(String content, String privateKey, String encode) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, UnsupportedEncodingException, SignatureException {
       PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decode(privateKey));
 
       KeyFactory keyFactory = KeyFactory.getInstance("RSA");
       PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
 
       java.security.Signature signature = java.security.Signature.getInstance("SHA256withRSA");
 
       signature.initSign(priKey);
       signature.update(content.getBytes());
 
       byte[] signed = signature.sign();
       return Base64.encode(signed);
   }

4.1.2. The remaining common private key signature

/**
     * 私钥签名底层操作
     *
     * @param algorithm NONEwithRSA
     *                   MD2withRSA,MD5withRSA
     *                   SHA1withRSA,SHA256withRSA ,SHA384withRSA ,SHA512withRSA
     *                   NONEwithDSA
     *                   SHA1withDSA
     *                   NONEwithECDSA ,SHA1withECDSA ,SHA256withECDSA ,SHA384withECDSA ,SHA512withECDSA
     * @param data       byte[]
     * @param privateKey PrivateKey
     * @return byte[]
     */
   public static byte[] sign(String algorithm, byte[] data, PrivateKey privateKey) throws Exception {
       Signature signature = Signature.getInstance(algorithm);
       signature.initSign(privateKey);
       signature.update(data);
       return signature.sign();
   }

5. Hash

  • SHA1
  • SHA256
  • SHA384
  • SHA512
  • MD2
  • MD5

apache-commons-codec is DigestUtils have fully achieved.

Reference material

https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html document various encryption algorithms implemented in the name of the official Java

https://www.example-code.com/java/rsa.asp RSA examples

https://www.programcreek.com/java-api-examples/ find a variety of algorithms and key demo

http://tool.chacuo.net/cryptaes check the correctness of the encryption algorithm Website

Guess you like

Origin www.cnblogs.com/datartvinci/p/10985577.html