我试图内联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对密文进行解密

10-06 05:50
查看更多