# Can you change an AES encrypted message if you control the IV?

Let's say that an attacker has the plaintext, the ciphertext and the IV of a specific message. If the attacker can control the ciphertext and the IV, could he forge valid plaintext? Let's say that the message is shorter than the block size, just a few bytes. Could the attacker change the value of the plaintext by changing the IV?

• This is more than hint!. Yes Bit Flipping Attack on CBC Mode, 64 bit clock cipher with CFB mode. One-byte defected from the ciphertext. What is the number of bits defected from plaintext, and same for others, too. – kelalaka Oct 24 '20 at 19:59
• With AES-CBC, you can make the first block of plaintext anything you want, upon decryption, if you can alter the IV without being detected. Knowing the original plaintext is not necessary, and altering the ciphertext is not necessary. – mti2935 Oct 24 '20 at 20:25
• @mti2935 how are you able to get any plaintext you want without knowledge of the original plaintext (or the key) ?? Otherwise I agree, plaintext + malleable IV with AES-CBC and no integrity check → you can produce any content on fhe first block – Ángel Oct 24 '20 at 21:53
• @Ángel I'll show you. Encrypt some plaintext using openssl aes-256-cbc like so: echo -n 'ET Phone Home' | openssl aes-256-cbc -e -K 7ac01f50605b8fcebd1c82ea6a6aacd6b112e8c9675b84cd77054b2f49668301 -iv f822ee7b8c0a8ba40daa773b01d9485a | xxd -p. Change the plaintext to something else (<16 bytes in length so that the ciphertext is one block long), and change the key and the iv. Then, post the ciphertext produced by the command and the iv that you used, and I'll show you to make it decrypt to some other plaintext. – mti2935 Oct 24 '20 at 22:22
• @Ángel OK. Use the following command to decrypt your ciphertext: echo -n '300541c5f2081fc47ea43c9f2fd47ade' | xxd -p -r | openssl aes-256-cbc -d -K yourkey -iv e37fc62e2f2ebf4569c6451c58a3d949. This should produce your original plaintext. Now, change the IV in the above command to: 9b1feb87b206f7ee650e1da2565682b6. The plaintext produced should be: Hello World!!!!! Is that what you get? If so, I'll write an answer explaining how it is done. – mti2935 Oct 24 '20 at 22:59

Consider the case where you encrypt the plaintext message attack at noon!! using AES-CBC-256, with the key 7ac01f50605b8fcebd1c82ea6a6aacd6b112e8c9675b84cd77054b2f49668301 and the iv f822ee7b8c0a8ba40daa773b01d9485a:

echo -n 'attack at noon!!' | openssl aes-256-cbc -e -nopad -K 7ac01f50605b8fcebd1c82ea6a6aacd6b112e8c9675b84cd77054b2f49668301 -iv f822ee7b8c0a8ba40daa773b01d9485a | xxd -p


The plaintext message is one block in length (16 bytes), and no padding is used, so this produces one block of cipher text:

8b2f9ede941cb6f3958d809510f579a5


Naturally, if you decrypt the ciphertext above using the same key and iv, you get the original plaintext:

echo -n '8b2f9ede941cb6f3958d809510f579a5' | xxd -p -r |  openssl aes-256-cbc -d -nopad -K 7ac01f50605b8fcebd1c82ea6a6aacd6b112e8c9675b84cd77054b2f49668301 -iv f822ee7b8c0a8ba40daa773b01d9485a


produces:

attack at noon!!


Now, an attacker who knows the original plaintext (attack at noon!!), the ciphertext, and the iv wishes to modify the iv, so that upon decryption, the plaintext produced is attack at dawn!!.

To see how this is done, refer to the diagram below (copied from https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation):

Consider point labeled E. E is the AES decryption of the first block (in the case, the only block) of ciphertext, using the key. We don't know the key, so we can't compute E...

Or, can we? Looking further, the first block of ciphertext is E XOR IV. The XOR function is unique in that: if A XOR B = C, then you can re-arrange A, B, and C in any order, and the expression still holds true - i.e. A XOR C = B, and B XOR C = A. So:

Plaintext = E XOR IV
E = Plaintext XOR IV
IV = E XOR Plaintext


So, knowing the original plaintext (attack at noon!!) and the IV (f822ee7b8c0a8ba40daa773b01d9485a), we can compute E. To do this, we use E = Plaintext XOR IV (above). First, use the following command to get the hex representation of the underlying ascii-decoded bytes of the plaintext:

echo -n 'attack at noon!!' | xxd -p


This produces:

61747461636b206174206e6f6f6e2121


Now, XOR the plaintext and the IV to get E like so:

python3 -c "print (hex(0x61747461636b206174206e6f6f6e2121 ^ 0xf822ee7b8c0a8ba40daa773b01d9485a))"


This produces:

0x99569a1aef61abc5798a19546eb7697b


So, E is 99569a1aef61abc5798a19546eb7697b.

Now, we can compute what the IV should be, so that when the ciphertext is decrypted by AES-CBC with our specially crafted IV, and E gets XOR'd with this IV, the plaintext produced will be our wanted plaintext 'attack at dawn!!'. To do this, we use IV = E XOR Plaintext (above). First, get the hex representation of the underlying ascii-decoded bytes of the wanted plaintext, like we did before:

echo -n 'attack at dawn!!' | xxd -p


this produces:

61747461636b206174206461776e2121


Now, XOR the the wanted plaintext with E to get the IV that we need, like so:

python3 -c "print (hex(0x61747461636b206174206461776e2121 ^ 0x99569a1aef61abc5798a19546eb7697b))"


This produces:

0xf822ee7b8c0a8ba40daa7d3519d9485a


Let's see if it worked. Let's use the decryption command above to decypt the ciphertext, using iv f822ee7b8c0a8ba40daa7d3519d9485a in place of f822ee7b8c0a8ba40daa773b01d9485a:

echo -n '8b2f9ede941cb6f3958d809510f579a5' | xxd -p -r |  openssl aes-256-cbc -d -nopad -K 7ac01f50605b8fcebd1c82ea6a6aacd6b112e8c9675b84cd77054b2f49668301 -iv f822ee7b8c0a8ba40daa7d3519d9485a


Sure enough, the plaintext produced is:

attack at dawn!!


***Special thanks to Ángel for helping me work through this in the comments under the question.

• How would this work if the messages are shorter than 16 bytes, say 4 bytes. Would it work the same by XORing them together. – 241020 Oct 25 '20 at 14:03
• @241020 In this case, PKCS#5 (or PKCS#7) padding would be applied to the plaintext block, to pad its length to 16 bytes, when the message is encrypted. So, you would simply do the same when applying the procedure above. – mti2935 Oct 25 '20 at 14:08
• The PKCS#5 is designed for 8-bytes, PKCS#7 is well defined if the block size is less than 256 see in rfc5652 – kelalaka Oct 25 '20 at 16:19