AES 256位加密 – java.security.InvalidAlgorithmParameterException:错误的IV长度:必须是16个字节长

以下是我的加密逻辑。 虽然我的IV是16字节长,但我仍然会收到无效IV长度的错误。 非常感谢任何帮助

@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和密钥生成逻辑

  @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; } 

下面是exception的堆栈跟踪exception是在行:
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) 

在从generateRandomIV返回之前,您将IV编码为Base64。 在将其用于加密和解密之前,您必须对其进行解码。

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

Java 8提供了java.util.Base64类,用于获取不同的Base 64编码器和解码器。

继Rob的评论之后,

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

在这里,您可以根据字符串获得IV的长度。 然而

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

在这里,您将IV作为字节数组提供,并且将字符串的长度设置为16的字符串并不保证其字节表示也是16字节。 因此,Rob建议将IV保留在字节数组中并将其用作字节数组会更好。