While developing some code that uses the .NET AesManaged algorithm, I made some mistakes but was surprised at the results.

My encryption was correct. I was generating a random IV block and writing it to the file (without encrypting the IV). Then I was encrypting the plaintext and writing it.

The decryption was wrong though... instead of reading the first block from the file an using it as an IV, it was just using a random IV and decrypting everything. The first block came out gibberish but the 2nd (and subsequent) ones were decrypted properly! Why would this be?

And even weirder... when I tried to fix it by encrypting the IV in the encryption code (instead of writing the IV unchanged) the decryption result was the same! (gibberish then correctly decrypted blocks).

Although I eventually fixed my code, how do these results make sense?

  • $\begingroup$ What mode of encryption were you using? $\endgroup$ – mikeazo Jun 11 '12 at 17:15
  • $\begingroup$ I used CBC...... $\endgroup$ – JoelFan Jun 11 '12 at 17:18
  • $\begingroup$ You found a feature of CBC :-) $\endgroup$ – Paŭlo Ebermann Jun 11 '12 at 19:33

In the correct use of CBC mode, you should see the following:
$c_1=E_k(IV\oplus p_1), c_2=E_k(c_1\oplus p_2)$, etc
and decryption is:
$p_1=D_k(c_1)\oplus IV, p_2=D_k(c_2)\oplus c_1$, etc

From what you are saying, it sounds like you have stored in the file (for case 1):
$IV||c_1||c_2||\cdots$ (where $||$ is concatenation).

So, what will decryption do? It will read $IV$ and try to decrypt it (sounds like the code thinks the first block read is the first block of ciphertext). Since it doesn't have an IV to use, it probably uses whatever happened to be at that memory location (since it is an uninitialized variable). So it does $D_k(IV)\oplus R$ (where $R$ is the random value that happened to be at that memory location). This is the block of random gibberish you saw. Then, it reads $c_1$ and uses $IV$ as the previous cipher block and correctly computes $p_1=D_k(c_1)\oplus IV$.

For the second case, from your description it is unclear exactly how you are encrypting $IV$. What IV do you use to encrypt the IV? That point aside, something very similar is happening in this case too. I'll let you work out the details.

  • $\begingroup$ Second case... it is encrypting IV using a random value as the IV. $\endgroup$ – JoelFan Jun 11 '12 at 18:18
  • $\begingroup$ I still don't understand how it would decrypt the 2nd block correctly no matter whether the IV is encrypted or not... it seems that my 'Case 1' or 'Case 2' should work... but not both! $\endgroup$ – JoelFan Jun 11 '12 at 18:22
  • $\begingroup$ @JoelFan, then the second case is pretty similar. It is probably using a different IV to decrypt the encrypted IV, which is why you don't get the IV back. But the first block of plaintext is using the previous block of ciphertext as it's IV, which is why decryption is correct. $\endgroup$ – mikeazo Jun 11 '12 at 18:22
  • $\begingroup$ @JoelFan, do you see from my explanation why case 1 works? If so, I can expand to include case 2. If not I can clarify. $\endgroup$ – mikeazo Jun 11 '12 at 18:23
  • $\begingroup$ Oh I get it... it doesn't really matter what IV was put into the first block, because whatever it is... either R or E(R)... the same IV will be used in decrypting block 2 that was used in encrypting block 2... so the decryption should work in either case... right? $\endgroup$ – JoelFan Jun 11 '12 at 18:27

This is what ciphertext block chaining is about - each plaintext block is XORed ("chained") with the previous ciphertext block before encrypting (and after decrypting).

The initialization vector then takes the place of the ciphertext block before the first block (since there is none).

So, mistaking the initialization vector as a ciphertext block does nothing wrong for decryption (other than that you'll get an additional garbage block of plaintext).

You did observe (part of) the malleability property of CBC: One can change the start of the ciphertext (including the IV), even prepend/remove blocks, and the result is still a valid ciphertext, and the plaintext block after the changed one will be changed in a predictable way.

This is used for some attacks on protocols using CBC, when they allow a chosen-ciphertext attack - search for the padding oracle attack, for example. For this reason, you always (not only for CBC) should use authentication together with your encryption, for example in form of a MAC around your ciphertext (including the IV).


Can't you just put random text in the first 16 bytes of your plain text, encrypt using a random IV, then during decryption use any IV and just throw away the first 16 bytes of the result?

  • 2
    $\begingroup$ Perhaps this should be a separate question instead of an answer. $\endgroup$ – mikeazo Jul 7 '12 at 18:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.