我正在尝试在Java中实现AES,这是我使用的代码:
byte[] sessionKey = {00000000000000000000000000000000};
byte[] iv = {00000000000000000000000000000000};
byte[] plaintext = "6a84867cd77e12ad07ea1be895c53fa3".getBytes();
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sessionKey, "AES"), new IvParameterSpec(iv));
byte[] ciphertext = cipher.doFinal(plaintext);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(sessionKey, "AES"), new IvParameterSpec(iv));
byte[] deciphertext = cipher.doFinal(ciphertext);
我需要这个固定密钥和IV用于测试目的,但我得到以下异常:
Exception in thread "main"
java.security.InvalidAlgorithmParameterException:
Wrong IV length: must be 16 bytes long at
com.sun.crypto.provider.SunJCE_h.a(DashoA12275) at
com.sun.crypto.provider.AESCipher.engineInit(DashoA12275) at
javax.crypto.Cipher.a(DashoA12275) at
javax.crypto.Cipher.a(DashoA12275) at
javax.crypto.Cipher.init(DashoA12275) at
javax.crypto.Cipher.init(DashoA12275)
如何在此AES实施中使用此固定IV?有什么办法吗?
答案 0 :(得分:38)
首先,
byte[] iv = {00000000000000000000000000000000};
创建一个大小为1的字节数组,而不是一个大小为32的字节数组(如果这是你的意图)。
其次,AES的IV大小应为16字节或128位(这是AES-128的块大小)。如果使用AES-256,则IV大小应为128位大,因为AES标准仅允许128位块大小。原始的Rijndael算法允许其他块大小,包括256位长的块大小。
第三,如果您打算使用AES-256,这不是开箱即用的。您需要下载并安装JCE Unlimited Strength Jurisdiction Policy Files(滚动到页面底部);我还建议阅读随附的许可证。
这会导致对您的代码进行以下更改:
byte[] iv = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
最后,初始化向量意味着唯一且不可预测。 16字节的序列,每个字节由值0表示,不适合IV。如果这是生产代码,请考虑获取帮助。
答案 1 :(得分:14)
来自Advanced Encryption Standard:
该标准包括三个分组密码,AES-128,AES-192和AES-256,采用最初发布为Rijndael的大型系列。 这些密码中的每一个都具有128位块大小,密钥大小分别为128,192和256位
(强调补充)
对于分组密码操作模式,IV通常与密码的块大小一样大
将这两个因素结合在一起,您可以得到AES,对于AES,总是128位,与密钥大小无关。
答案 2 :(得分:2)
这里的AES可能是AES-128而不是AES-256。如果要启用AES-256,则必须包含额外的jar,因为有适当的出口控制策略。所以先检查一下。在大多数情况下,AES-128就足够了。
当它是AES-128时,你的IV不能超过128位,即16字节。所以改变初始化向量长度。
那必须奏效。另请阅读此http://en.wikipedia.org/wiki/Initialization_vector
警告:固定IV不是一个好习惯。它必须是随机的或伪随机的才能提供更好的安全性。
答案 3 :(得分:2)
为什么不使用类似的东西而不是使用"魔术数字":
SecureRandom random = new SecureRandom();
byte[] iv = random.generateSeed(16);
所以你的iv会得到16个随机字节。
答案 4 :(得分:0)
出现此问题的原因是因为我将IV作为字符串读取,然后以错误的方式将其转换为字节数组。
正确的方法:
Hex.decodeHex(initializationVector.toCharArray()
使用org.apache.commons.codec.binary.Hex
错误的方式:
initializationVector.getBytes()
这是错误的原因,是因为当您调用 时,它只获取表示字符串的所有位并将其切成字节。因此,getBytes()
0
最终被写入了Unicode表中构成0
索引的位,该位不是0,而是30,将被写在2个字节上。
相反,实际上,您想要的是将0
表示为字节00000000
。