This question was also asked on StackOverflow, but with no answers, and I thought this may be a better exchange, since I have the same question.


Using AESCryptoServiceProvider, I noticed that before I had implemented any logic to pass the IV from the encrypting party to the decrypting party, my large zip file decrypted successfully (as far as I could tell). So I wrote a little test to see why this worked, as I didn't expect it to.

Using the encrypt... and decrypt... functions found on: http://msdn.microsoft.com/en-us/library/system.security.cryptography.aescryptoserviceprovider.aspx

And the following test:

static void TestIV()
    string plainText = "abcdefghijklmnopqrstuvwxyz0123456789asdfqwerfdsareqw";
    byte[] key;

    string roundTrip = "";
    byte[] encrypted = null;

    using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider())
        key = aes.Key;
        Console.WriteLine("encryption Key = " + System.Convert.ToBase64String(aes.Key));
        Console.WriteLine("encryption IV = " + System.Convert.ToBase64String(aes.IV));
        encrypted = EncryptStringToBytes_Aes(plainText, aes.Key, aes.IV);

        Console.WriteLine("cipherText = " + System.Convert.ToBase64String(encrypted));

    using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider())
        aes.Key = key;
        Console.WriteLine("decryption Key = " + System.Convert.ToBase64String(aes.Key));
        Console.WriteLine("decryption IV = " + System.Convert.ToBase64String(aes.IV));
        roundTrip = DecryptStringFromBytes_Aes(encrypted, aes.Key, aes.IV);

    Console.WriteLine("Original: " + plainText);
    Console.WriteLine("Round Trip: " + roundTrip);

This was my output:

encryption Key = 0Fnvwk0qzbn6sQ+qUbGDyz0MmpBt5e3vkA+7YCUYTzc=
encryption IV = 7E5iw+226INZNzA6y7wWjQ==
cipherText = YVj3ZsSx9nbOKor6ZGqzyGFxdnaR6KM+qSeQj322+2QyhU9Iu1G3d4xPnj7n0X/wpObvjpFBlHf+9rRFWtPodA==
decryption Key = 0Fnvwk0qzbn6sQ+qUbGDyz0MmpBt5e3vkA+7YCUYTzc=
decryption IV = o//BGrMnXatF5po9dUEnug==
Original: abcdefghijklmnopqrstuvwxyz0123456789asdfqwerfdsareqw
Round Trip: .???;??@u??k?^Gqrstuvwxyz0123456789asdfqwerfdsareqw

Turns out the first block of my zip file was probably mangled, but it unzipped successfully anyway, and the files I looked at must not have been part of the first block.

Running this multiple times I get the following cipherTexts:

cipherText = ZsvLpvVucn0ekx393Fmk5R/UrzzPmzH4dY32EqVlpHJvAKGRERIUY7LLPGHIuyPikHcGKUWL/mt8eP6RI/Qqcw==
cipherText = 0i5tZ1vQvmU5zMimCBIqCWsQzze8PDEOuOxVYekq8T/IGKu4VuHuZWJ6H4aPjRqmSBQYRDbWff6o3Odjl8Qg8A==
cipherText = En/I32AeAASiq10j7ChNPzclWdj8uc6hdBUk/sp8S9G7ly6QBCPAzJFJCR1c9TWjb1gUbzrCEghUgCoRnlJbGA==

So it appears that the IV is successfully creating a different cipherText for the same text as expected. So when decrypting with an incorrect IV, is it expected that only the first block will be mangled?

Note that AesCryptoServiceProvider uses CBC mode by default, but I saw this same behavior using CFB, and when using ECB, the plaintext was completely the same (first block not mangled).


I want to clear a couple of things first:

  1. What you're seeing is the intended and correct behaviour.

  2. ECB doesn't use chaining and it applies the block cipher to the plaintext block by block separately, so there's no point to discuss IV and ECB because the two don't really work with each others.

Let's start with CBC encryption. It's quite simple; take the first plaintext block and XOR it with the IV, apply the block cipher on it, take the resulting ciphertext and XOR it with the second plaintext, apply the block cipher, XOR the result with the third plaintext block, and so on.

CBC encyption

Now let's look at the decryption. Take the first ciphertext block, apply the block cipher on it, and then XOR it with the IV, (pay attention here) then move to the next ciphertext block and apply the block cipher on it and then XOR it with the previous ciphertext block, and so on.

CBC decryption

Now, can you see it? The IV is only used when working on the first block, and that's why using the wrong IV for decryption will only give the wrong first block with all of the next blocks decrypting just fine.

The same logic can be used for CFB decryption

CFB decryption]

For the sake of simplicity, you can think of it this way: The IV of the first block is the actual IV, while the "IV" for the next block is the first block's ciphertext, and the "IV" for third block is the second block's ciphertext and so on. Guess what? When trying to decrypt without the correct IV, you already have the ciphertext, so you already have the "IVs" for all the blocks except for the first one.


It is not a matter of C# -- it is intrinsic to CBC mode. In CBC, upon encryption, each block is first XORed with the previous encrypted block (with the IV for the first block), and then the XOR result is processed with the block cipher. This implies that, for decryption, you process a block with the block cipher, then XOR it with the previous encrypted block. So, the decryption process of block n only depends on encrypted blocks n and n-1 ("block n-1" being the IV when "block n" is the first block). The schematic on the Wikipedia page makes it clear: CBC decryption (from Wikipedia page on block cipher modes of operation)

Remember that CBC mode was never meant to produce all-file mangling or anything like that. Its role is merely to avoid leaking information about which source blocks were identical to each other.

As for the successful Zip decompression, this is because in the Zip file format, the "central directory" (which references the files within the archive) is located at the end of the file, not at the start. Mangling the first 16 bytes will damage the header of only one file (the one which happens to be at the start of the file). The other files shall be unscathed.

  • Appreciate the information about the zip file, I had never looked into this before. I accepted Adnan's answer as it explained the decryption process in more detail and mentioned clearly that what I am seeing is the expected behavior. – BrightLight Oct 25 '13 at 20:44

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.