带有内联安全随机IV的Java AES CBC - 生成相同的密文?

Jos*_*ree 0 java encryption aes

我试图内联我的IV,以便我可以解密我的消息而不知道最初的IV,只是秘密密钥.

我生成了我的钥匙.我使用SecureRandom生成我的IV我对IV字节数组进行了randominze.(我使用iv +消息创建一条消息)最后,我用唯一的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();
            }


        }
Run Code Online (Sandbox Code Playgroud)

这里

并输出:

ITERATION 1 IV pre rand:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

IV POST rand:[13,68,83,113,86,48,50,-71,-75,-25,56,100,-25,34,-27,-23]

CIPHER TEXT:[ - 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]

解密: 你好hello你好

ITERATION 2:IV pre rand:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

IV POST rand:[90,115,91,124,27,-80,-32,-46,-66,-50,-85,43,34,-18,-74,-3]

CIPHER TEXT:[ - 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]

解密: 你好hello你好

ITERATION 3

IV pre rand:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

IV POST rand:[113,112,9,47,-125,-4,80,10,-97,44,42,90,-58,-44,-46,17]

CIPHER TEXT:[ - 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]

解密: 你好hello你好

dav*_*085 5

如果你看一下维基百科中有关CBC如何工作的精彩图片,你会看到通过将IV置于CBC明文的开头,你实际上取消了IV并破坏了它旨在提供的语义安全性.具体来说,使用CBC加密可以:

  • 使用第一个明文块对IV进行异或,并将其加密到第一个密文块.由于您将第一个明文块作为IV的副本,因此它始终会对零块进行加密,并且每次都会产生相同的结果.

  • 将第一个密文块与第二个明文块进行异或(这里是你搞砸之前的实际明文)并将其加密到第二个密文块.由于您将第一个密文块设为固定值,并且在测试中实际明文是相同的,因此每次都会产生相同的结果.

  • 等等

做你应该做的事:

  • 用(秘密)密钥和(随机)IV 加密实际明文,然后将IV与密文结合起来进行传输 ; 连接是一种简单的方法,但不是唯一的方法

  • 在接收中将IV与密文分开或分开,并用(秘密)密钥和(随机但可见)IV解密密文