AES 256 bit encryption - java.security.InvalidAlgo

2020-05-29 07:00发布

Below is my encryption logic. Although my IV is 16bytes long, I still get an error with invalid IV length. Would appreciate any help

@Override
public String encrypt(String dataToEncrypt, String IV) throws Exception{
    if(encryptionKey.length() < 10){
        encryptionKey = generateEncryptionKey().toString();
    }
    System.out.println("number of IV bytes is "+IV.length()+" "+IV);
    Cipher cipher = Cipher.getInstance(encrpytionAlgo);
    SecretKey key = new SecretKeySpec(encryptionKey.getBytes(Charset.forName("UTF-8")), "AES");
    cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes(Charset.forName("UTF-8"))));
    byte[] encryptedTextBytes = cipher.doFinal(dataToEncrypt.getBytes(Charset.forName("UTF-8")));
    return new Base64().encodeAsString(encryptedTextBytes);
}

IV and Key generation logic

 @Override
public String generateRandomIV(){
        Random random = new SecureRandom();
        byte[] iv = new byte[16];
        random.nextBytes(iv);
        System.out.println("IV is "+Base64.encodeBase64(iv)+" "+ com.sun.jersey.core.util.Base64.base64Decode(new String(Base64.encodeBase64(iv)))+ " number of bytes is "+iv.length);
        return new String(Base64.encodeBase64(iv));
}

@Override
public SecretKey generateEncryptionKey(){
    KeyGenerator aesKey = null;
    try {
        aesKey = KeyGenerator.getInstance("AES");
    } catch (NoSuchAlgorithmException e) {
          e.printStackTrace();
    }
    aesKey.init(256);
    SecretKey secretKey = aesKey.generateKey();
    System.out.println("Encryption key is "+ new Base64().encode(secretKey.getEncoded()));
    return secretKey;
}

Below is the stacktrace for the exception Exception is at line :
cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes(Charset.forName("UTF-8"))));

java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long
at com.sun.crypto.provider.SunJCE_f.a(DashoA13*..)
at com.sun.crypto.provider.AESCipher.engineInit(DashoA13*..)
at javax.crypto.Cipher.a(DashoA13*..)
at javax.crypto.Cipher.a(DashoA13*..)
at javax.crypto.Cipher.init(DashoA13*..)
at javax.crypto.Cipher.init(DashoA13*..)
at com.intuit.platform.publiccloudaccess.core.services.EncryptionServiceImpl.encrypt(EncryptionServiceImpl.java:47)

2条回答
ゆ 、 Hurt°
2楼-- · 2020-05-29 07:14

Following the Rob's comment,

System.out.println("number of IV bytes is "+IV.length()+" "+IV);

Here you get the length of the IV in terms of String. However

cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes(Charset.forName("UTF-8"))));    

here you are providing the IV as byte array and making the length of the IV as 16 in therms of String does not guarantee that its byte representation is also 16 bytes. So as Rob suggested it would be better for you to keep the IV in the byte array and use it as the byte array.

查看更多
地球回转人心会变
3楼-- · 2020-05-29 07:37

You encoded your IV as Base64 before returning it from generateRandomIV. You have to decode it before using it for encryption and decryption.

cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(java.util.Base64.Decoder.decode(IV.getBytes("UTF-8"))));

Java 8 provides the java.util.Base64 class for getting different Base 64 encoders and decoders.

查看更多
登录 后发表回答