1

I am trying to inline my IV, so that I can decrypt my message without knowing the initial IV, just the secret key.

I generate my key. I generate my IV with SecureRandom I randominze the IV byte array. (I create a message with the iv+message) And finally, I encrypt the message with the unique IV.

As expected, I can decrypt the message if I remove the IV on the receiving end. However, the generated cipher text is always the same.

I am at a loss as to why this is and have yet to find a solution online.

Below is my code and output.

Can anyone help me understand why this is?

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();
            }


        }

here

And the output:

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]

DECRYPTED: ��������������������������������Hello hellow hello

ITERATION 2: IV pre rand: [0, 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]

DECRYPTED: ��������������������������������Hello hellow hello

ITERATION 3

IV pre rand: [0, 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]

DECRYPTED: ��������������������������������Hello hellow hello

Coder
  • 2,153
  • 1
  • 16
  • 21
JoshuaTree
  • 1,211
  • 14
  • 19
  • You seem to be at loss what to do with the security related exceptions, you might want to take a look [here](http://stackoverflow.com/q/15709421/589259). Also take a look at GCM mode, CBC is getting old - authenticated encryption is the way to go 99% of the time. – Maarten Bodewes Oct 14 '16 at 22:40
  • Thank you for the pointer in a good direction. :) – JoshuaTree Oct 15 '16 at 10:15

1 Answers1

6

If you look at the nice picture in Wikipedia of how CBC works you will see that by putting the IV at the beginning of the plaintext for CBC you are in fact cancelling out the IV and destroying the semantic security it is intended to provide. Specifically, encryption with CBC does:

  • XOR the IV with the first plaintext block and encrypt that to the first ciphertext block. Since you made the first plaintext block a copy of the IV, this always encrypts the zero block and produces the same result every time.

  • XOR the first ciphertext block with the second plaintext block (which here is the actual plaintext before you screwed it up) and encrypt that to the second ciphertext block. Since you made the first ciphertext block a fixed value, and in your test the actual plaintext is the same, this also produces the same result every time.

  • etc etc.

Do what you are supposed to do:

  • encrypt the actual plaintext with the (secret) key and (random) IV, and then combine the IV with the ciphertext for transmission; concatenation is a simple way but not the only way

  • on reception split or separate the IV from the ciphertext, and decrypt the ciphertext with the (secret) key and the (random but visible) IV

dave_thompson_085
  • 34,712
  • 6
  • 50
  • 70
  • Thanks for this comment. What you said makes sense. However, I think where I went wrong, was by thinking that the IV needs to be kept secret during transmission for some reason. – JoshuaTree Oct 15 '16 at 10:12
  • Does the IV not need to be kept secret? – JoshuaTree Oct 15 '16 at 10:13
  • @Enjoy87 No; as the same Wikipedia article says, **IV does not need to be secret**, only unique (all modes) and unpredictable (some modes including CBC). You can't transmit it encrypted, because you need the IV before you decrypt but you would need to decrypt before you get the IV, which is impossible. There are schemes that use an unpredictable but untransmitted value, such as secretly-keyed hash of a synchronized counter (which some transmission schemes need anyway, thus saving a little space) but they are rare. – dave_thompson_085 Oct 15 '16 at 22:49