我试图内联IV,以便可以解密消息而无需知道初始IV(仅密钥)。
我生成我的密钥。
我用SecureRandom生成IV
我随机插入IV字节数组。
(我用iv + message创建一条消息)
最后,我使用唯一的IV加密消息。
如预期的那样,如果在接收端删除IV,则可以解密该消息。
但是,生成的密文始终是相同的。
我不知道为什么会这样,现在还没有在线找到解决方案。
下面是我的代码和输出。
谁能帮我理解为什么会这样吗?
enter code
String mssg = "Hello hellow hello";
byte[] key = "kljhn1234512345abcde123451234512".getBytes();
SecretKeySpec spec = new SecretKeySpec(key, "AES");
SecureRandom rand = new SecureRandom();
for (int i = 0; i < 5; i++) {
//
//initialzize empty byte array for random IV
byte[] iv = new byte[16];
System.out.println("IV pre rand: " + Arrays.toString(iv));
rand.nextBytes(iv); //RANDOMIZE
System.out.println("IV POST rand: " + Arrays.toString(iv));
//CONCATENTATE IV TO FRONT OF MESSAGE TO ENCRYPT
//CONCATENATE MESSAGE TO END OF IV
ByteArrayOutputStream bout = new ByteArrayOutputStream();
try {
bout.write(iv);
bout.write(mssg.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
byte[] message = bout.toByteArray();
try {
//ENCRYPT USING RANDIMIZED IV.. THIS SHOULD RESULT IN NON EQUAL CIPHER TEXT FOR SAME MESSAGE.
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, spec, new IvParameterSpec(iv));
byte[] ct = cipher.doFinal(message);
System.out.println("CIPHER TEXT: " + Arrays.toString(ct));
//DECRYPT. AND USING A WRONG IV.
cipher.init(Cipher.DECRYPT_MODE, spec, new IvParameterSpec(new byte[16]));
System.out.println("DECRYPTED: " + new String(cipher.doFinal(ct)));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
}
这里
并输出:
迭代1
IV前置位:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
IV POST兰特:[13、68、83、113、86、48、50,-71,-75,-25、56、100,-25、34,-27,-23]
密文:[-102,-52,-21,-92,-85、119,-10,-18,-52、0,-39,-19、11 -83、70、44、101,- 92,-93,-60,4,73,-17,73,-58,119,81,66,-114,54,-107,-83,11,42,-92,121,-15,- 61、92、83、24、10、89,-21、110、100、116、119]
解密:������������������������
迭代2:
IV前置位:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
IV POST兰特:[90、115、91、124、27,-80,-32,-46,-66,-50,-85、43、34,-18,-74,-3
密文:[-102,-52,-21,-92,-85、119,-10,-18,-52、0,-39,-19、11 -83、70、44、101,- 92,-93,-60,4,73,-17,73,-58,119,81,66,-114,54,-107,-83,11,42,-92,121,-15,- 61、92、83、24、10、89,-21、110、100、116、119]
解密:����������������������������������
迭代3
IV前置位:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
IV POST兰特:[113、112、9、47,-125,-4、80、10,-97、44、42、90,-58,-44,-46、17]
密文:[-102,-52,-21,-92,-85、119,-10,-18,-52、0,-39,-19、11 -83、70、44、101,- 92,-93,-60,4,73,-17,73,-58,119,81,66,-114,54,-107,-83,11,42,-92,121,-15,- 61、92、83、24、10、89,-21、110、100、116、119]
解密:������������������������
最佳答案
如果查看the nice picture in Wikipedia of how CBC works,您会看到将IV放在CBC的纯文本开头,实际上您正在取消IV并破坏了它打算提供的语义安全性。具体来说,使用CBC加密可以:
将IV与第一个纯文本块进行XOR并将其加密为第一个密文块。由于您将第一个明文块复制为IV,因此始终加密零块并每次产生相同的结果。
将第一个密文块与第二个明文块(在拧紧它之前是实际的明文)进行异或运算,然后将其加密到第二个密文块。由于您将第一个密文块设为固定值,并且在测试中实际的明文相同,因此每次生成的结果也相同。
等等等
做您应该做的事情:
用(秘密)密钥和(随机)IV加密实际的明文,然后将IV与密文结合起来进行传输;串联是一种简单方法,但不是唯一方法
在接收时,将IV与密文分开或分开,并使用(秘密)密钥和(随机但可见)IV对密文进行解密