Java encryption and decryption instance

  java

Order

This article mainly summarizes AES and RSA encryption and decryption in java.

AES


AES encryption requires several parameters:

  • Key Size

Under AES algorithm, there are three key lengths: 128, 192 and 256 bits. Due to historical reasons, JDK only supports keys not larger than 128 bits by default, while 128 bits of keys can already meet commercial security requirements.

  • Cipher Mode

The block cipher algorithm can only encrypt packets of fixed length, but the length of plaintext that we need to encrypt may exceed the block length of the block cipher, so we need to iterate the block cipher algorithm in order to encrypt all the long plaintext. The iterative method is called the block cipher mode.
AES belongs to Block Cipher. There are CBC, ECB, CTR, OFB, CFB and other working modes in block cipher.

  • ECB is too simple and unsafe (Because the encryption of each block of data is independent, the encryption and decryption can be calculated in parallel in ECB mode. The biggest disadvantage of ECB mode is that the same plaintext block will be encrypted into the same ciphertext block. This method cannot provide strict data confidentiality in some circumstances);
  • CFB can be subjected to replay attacks;
  • OFB and CTR can both be reversed by active attackers, causing the corresponding bits in the decrypted plaintext to change. CTR is more capable of supporting concurrent computation than OFB. In addition, CTR is a stream cipher.
  • Although CBC does not support parallel computing, it is the safest of these modes.

This article uses CBC mode.

CBC mode will XOR with the ciphertext of the previous cipher block before encrypting each cipher block to be encrypted, and then encrypt with an encryptor. The first plaintext block XOR with a data block called initialization vector. CBC mode has higher confidentialit y than ECB, but encryption cannot be parallel because the encryption of each data block depends on the encryption of the previous data block. Like ECB, data needs to be filled before encryption, which is not very suitable for encrypting stream data.

  • Padding

Because block encryption can only encrypt data blocks of a specific length, CBC and ECB modes need to fill in data before encrypting the last data block.
JDK provides PKCS5Padding.

  • Initial vector

Using encryption modes other than ECB requires an initial vector to be passed in with the same size as Block Size (Block Size of AES is 128 bits)

Generate AES KEY

public static String genKeyAES() throws Exception {
        KeyGenerator kenGen = KeyGenerator.getInstance(AES);
        kenGen.init(KEY_SIZE);
        SecretKey key = kenGen.generateKey();
        String base64 = Base64.getEncoder().encodeToString(key.getEncoded());
        return base64;
    }

KEY_SIZE here uses 128
Later, byte[] will be converted into a character string by base64, which is convenient for display and investigation.

Encryption and decryption

public static byte[] aesEncryptBytes(byte[] contentBytes, byte[] keyBytes) throws Exception {
        return cipherOperation(contentBytes, keyBytes, Cipher.ENCRYPT_MODE);
    }

    public static byte[] aesDecryptBytes(byte[] contentBytes, byte[] keyBytes) throws Exception {
        return cipherOperation(contentBytes, keyBytes, Cipher.DECRYPT_MODE);
    }

    private static byte[] cipherOperation(byte[] contentBytes, byte[] keyBytes, int mode) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(keyBytes,AES);

        byte[] initParam = SIXTEEN_CHAR_INIT_VECTOR.getBytes(CHARSET);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);

        Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5_PADDING);
        cipher.init(mode, secretKey, ivParameterSpec);

        return cipher.doFinal(contentBytes);
    }

AES_CBC_PKCS5_PADDING is AES/CBC/PKCS5Padding, which is the default value for AES using shorthand

RSA

Generate key pair

public static KeyPair getKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);
        keyPairGenerator.initialize(KEY_SIZE);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return keyPair;
    }

    public static String getPublicKey(KeyPair keyPair){
        PublicKey publicKey = keyPair.getPublic();
        byte[] bytes = publicKey.getEncoded();
        return Base64.getEncoder().encodeToString(bytes);
    }

    public static String getPrivateKey(KeyPair keyPair){
        PrivateKey privateKey = keyPair.getPrivate();
        byte[] bytes = privateKey.getEncoded();
        return Base64.getEncoder().encodeToString(bytes);
    }

Here, KEY_SIZE uses 1024,RSA256, RSA512, RSA1024 and RSA2048. n after RSA represents the number of bits (how many bits). the larger the number of bits, the greater the encryption strength, and the longer it takes to crack it.

At present, the length of mainstream keys is at least 1024bits, and keys below 1024 bits are not recommended (security issues). So where is the upper limit? There is no upper limit; you can use it up to any size. Therefore, the mainstream modulus value is 1024 bits

Encryption and decryption

public static byte[] publicEncrypt(byte[] content,PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance(RSA);
        cipher.init(Cipher.ENCRYPT_MODE,publicKey);
        byte[] bytes = cipher.doFinal(content);
        return bytes;
    }

    public static byte[] privateDecrypt(byte[] content,PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance(RSA);
        cipher.init(Cipher.DECRYPT_MODE,privateKey);
        byte[] bytes = cipher.doFinal(content);
        return bytes;
    }

RSA is “RSA” here, and the default is RSA/ECB/PKCS1Padding.

AES combined with RSA

  • RSA is more difficult to crack than AES, because it does not need to worry about the key leaking in the process of transmission, only there is one possibility of violent crack.
  • The advantage of AES is that the encryption and decryption speed is very fast, generally speaking, AES is hundreds of times faster than RSA

In practical applications, we will mix AES and RSA:

  • 1 Generates a one-time random key. The algorithm uses AES’s CBC mode aes-128-cbc (encryption packet is 128 bits) to encrypt the file.
  • After the encryption is completed, in order to safely transfer this one-time random key, we use the RSA public key of the receiver to encrypt it and send the encrypted file together.
  • 3 The receiver decrypts with RSA private key to obtain the original AES key and decrypts the file with AES

This makes full use of the advantages of both.

public void testHyperCodec(){
        KeyPair keyPair = RSAUtil.getKeyPair();
        String pubKey = RSAUtil.getPublicKey(keyPair);
        String priKey = RSAUtil.getPrivateKey(keyPair);


        String password = "1234567890";

        String aesRawKey = AESUtil.genKeyAES();
        System.out.println("aes raw key:"+aesRawKey);

        String rsaEntryptAesKey = RSAUtil.publicEncryptString(aesRawKey,pubKey);
        System.out.println(rsaEntryptAesKey);
        String aesEntryptContent = AESUtil.aesEncryptStringByBase64Key(password,aesRawKey);
        System.out.println(aesEntryptContent);

        //decode
        String decodedAesKey = RSAUtil.privateDecryptString(rsaEntryptAesKey,priKey);
        String decodedPwd = AESUtil.aesDecryptStringByBase64Key(aesEntryptContent,decodedAesKey);

        System.out.println("aes key decoded:"+decodedAesKey);
        System.out.println(decodedPwd);
}

doc