SecretKey key = keyFactory.generateSecret(keySpec);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] ciphertext = cipher.doFinal(cleartext);
return bytes2String(ciphertext);
我收到了java.security.InvalidKeyException,即当cipher.init(Cipher.DECRYPT_MODE,key)中的一个预期错误没有设置IV时.cleartext是字符串base64解码的字节数组。我在这里缺少什么?
答案 0 :(得分:4)
我不是这方面的专家,但是,您指定的CBC mode需要初始化向量(IV),对于AES,这是一个16字节的参数。
private final static byte[] iv = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
private static final IvParameterSpec ivspec = new IvParameterSpec(iv);
然后在加密和解密时调用init()
方法提供IV。
cipher.init(Cipher.ENCRYPT_MODE, key, ivspec);
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivspec);
您永远不应该使用上述方法,让Java为您生成随机IV或提供SecureRandom实现。
使用随机,IV的要点是确保相同的纯文本不加密以生成相同的密文两次。这是IV的唯一目的。
将IV存储在加密文本的开头,在解密时,您知道起始的n位是IV。
当不提供IV时,它将默认生成随机IV。 Source
如果此密码(包括其底层反馈或填充方案)需要任何随机字节(例如,用于参数生成),它将使用最高优先级安装提供程序的SecureRandom实现作为随机源。 (如果没有安装的提供程序提供SecureRandom的实现,则将使用系统提供的随机源。)
答案 1 :(得分:0)
使用
private final static byte[] iv = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
和
private static final IvParameterSpec ivspec = new IvParameterSpec(iv);
为我导致了“ 填充块损坏错误 ”。我通过修改init()
步骤来解决以下问题:
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));
不使用static final
参数。