Image of the glider from the Game of Life by John Conway
Skip to content

ECB vs CBC Encryption

This is something you can do on your computer fairly easily, provided you have OpenSSL installed, which I would be willing to bet you do. Take a bitmap image (any image will work fine, I'm just going to use bitmap headers in this example), such as the Ubuntu logo, and encrypt it with AES in ECB mode. Then encrypt the same image with AES in CBC mode. Apply the 54-byte bitmap header to the encrypted files, and open up in an image viewer. Here are the commands I ran:

$ openssl enc -aes-256-ecb -in ubuntu.bmp -out ubuntu-ecb.bmp
$ openssl enc -aes-256-cbc -in ubuntu.bmp -out ubuntu-cbc.bmp
$ dd if=ubuntu.bmp of=ubuntu-ecb.bmp bs=1 count=54 conv=notrunc
$ dd if=ubuntu.bmp of=ubuntu-cbc.bmp bs=1 count=54 conv=notrunc

Now, open all three files, ubuntu.bmp, ubuntu-ecb.bmp and ubuntu-cbc.bmpp, and see what you get. Here are my results with the password "chi0eeMieng7Ohe8ookeaxae6ieph1":

Plaintext ECB Encrypted CBC Encrypted

Feel free to play with different passwords, and notice the colors change. Or use a different block cipher such as "bf-ecb", "des-ecb", or "rc2-ecb" with OpenSSL, and notice details change.

What's going on here? Why can I clearly make out the image when encrypted with EBC? Well, EBC, or electronic codeblock, is a block cipher that operates on individual blocks at a time. ECB does not use an initialization vector to kickstart the encryption. So, each block is encrypted with the same algorithm. If any underlying block is the same as another, then the encrypted output is exactly the same. Thus, all "#000000" hexadecimal colors in our image, for example, will have the same encrypted output, per block (thus, why you see stripes).

Compare this to CBC, or cipher-block chaining. An initialization vector must be used before the encryption can begin. The password in our case is our initialization vector. It is hashed to provide a 256-bit output, then AES encrypts the hash, plus the first block to provide a 512-bit output, 256-bits for the next vector, and 256-bits encrypted output. That vector is then used to encrypt the next 256-bits. This chaining algorithm continues to the end of the file. This ensures that every "#000000" hexadecimal color will have a different output, thus causing the file to appear as random (I have an attacking algorithm to still leak information out of a CBC-encrypted file, but that will be for another post).

Hopefully, this simple illustration convinces you to use CBC, or at least to not use ECB, when encrypting data that might be public.

{ 17 } Comments

  1. Lonnie Olson using Google Chrome 19.0.1041.0 on GNU/Linux 64 bits | February 17, 2012 at 7:58 pm | Permalink

    Fascinating, I previously understood that CBC was much better, but didn't understand how much so. This visualization of the differences was awesome. Thanks.

  2. Nathan MacInnes using Safari 533.1 on Android | February 17, 2012 at 10:11 pm | Permalink

    The images aren't showing up for me.

  3. Aaron Toponce using Debian IceWeasel 10.0.1 on GNU/Linux 64 bits | February 17, 2012 at 11:54 pm | Permalink

    Lonnie Olson- Yeah, that's why I blogged it. I'm hoping to show some illustrations with other attacks on weak algs, so it's easy to understand the "why".

    Nathan Macinnes- Works fine here. Don't know what to tell you.

  4. anonymous using Google Chrome 17.0.963.46 on GNU/Linux 64 bits | February 18, 2012 at 3:45 pm | Permalink

    Thanks for this illustration. That's why some time ago i changed for IRC encryption from FiSH to mircryption which supports CBC

  5. Ross using Google Chrome 17.0.963.56 on Windows 7 | February 21, 2012 at 9:16 pm | Permalink

    Very clever! Thanks for posting.

  6. shalombi using Google Chrome 17.0.963.56 on Mac OS | February 22, 2012 at 12:56 am | Permalink

    ECB does preserve block structure which in the case of images reveals part of the information encrypted.
    However this isn't so much an issue with other types of data where the value lies in the data rather than the structure.

    As explained CBC solves this by chaining the encryption but this comes with a performance hit.
    So IMHO CBC isn't a blanket solution but must be chosen carefully in regard with the task at hand.

    http://www.cse.wustl.edu/~jain/cse567-06/ftp/encryption_perf/index.html#6

  7. Aaron Toponce using Debian IceWeasel 10.0.2 on GNU/Linux 64 bits | February 22, 2012 at 5:12 am | Permalink

    shalombi- Yes, this isn't a one-size-fits-all solution. And ECB definitely performs better than CBC in most cases. However, it is important to understand that patterns will emerge from the underlying data if you use ECB. It's simple enough to do this same exercise on binary executables or text files, and see patterns emerge.

    Regardless, the illustration with images is to help you understand what is happening with the different block modes.

  8. Tiao using WebKit 533.1 on Unknown O.S. | February 22, 2012 at 6:11 pm | Permalink

    I cannot see the images in my bada phone.

  9. Aaron Toponce using Debian IceWeasel 10.0.2 on GNU/Linux 64 bits | February 22, 2012 at 7:15 pm | Permalink

    Tiao- You need a browser that supports viewing bitmaps.

  10. Jim using Firefox 10.0.1 on GNU/Linux | February 26, 2012 at 11:13 am | Permalink

    Fascinating. ECB looks like a terrible idea that should never be used to encrypt anything, as it makes no proper attempt to encrypt "whitespace", or repeated runs of the same data in the input. The BMP clearly shows the effect, but other datasets (documents, audio, whatever) would be affected too.

  11. Martins Mozeiko using Google Chrome 19.0.1084.52 on Windows 7 | June 3, 2012 at 5:32 pm | Permalink

    AES-256 doesn't operate on 256-bit blocks at time. AES-128, 192 and 256 all operate on 128-bit blocks at time.
    Only difference is in key size. That means expanded key size will be bigger and AES will use more rounds for AES-192/256 than for AES-128. 128 has 10 rounds, 192 has 12 rounds and 256 has 14 rounds

  12. Aaron Toponce using Debian IceWeasel 10.0.4 on GNU/Linux 64 bits | June 4, 2012 at 3:54 pm | Permalink

    Yes. You're absolutely correct. I'll update the post. Thanks!

  13. Bryan using Firefox 12.0 on Ubuntu | July 8, 2012 at 8:57 pm | Permalink

    This is a great demonstration, but I wonder if it might be made more accurate if the first 54 bytes of ubuntu.bmp were not included in the encryption. In the given example, the first 54 bytes are used in encryption, but then thrown away for visualization. It might be better to dd ubuntu.bmp to ubuntu-sans-header.bmp with bs=1 and skip=54. Perform encryption on ubuntu-sans-header.bmp and then append the 54 bytes from ubuntu.bmp as per the current example.

  14. Marcus Klaas using Firefox 15.0.1 on Ubuntu 64 bits | September 8, 2012 at 10:11 am | Permalink

    Great post that explained EBC vs CBC really well. Thanks :-)

  15. Shailja using Firefox 16.0 on Ubuntu | October 28, 2012 at 3:46 am | Permalink

    Can you tell me how to decrypt this image , because I tried but it shows some bad magic no
    Please reply asap with the command

    Thanks

  16. Aaron Toponce using Google Chrome 21.0.1180.89 on GNU/Linux 64 bits | October 28, 2012 at 8:43 am | Permalink

    Well, first all the commands are already in the post. You just need to reverse them. Second, because I took a bitmap header (54 bytes worth), and placed it on the encrypted data to create the image, there is irreversible data corruption on the encrypted data. For ECB, this won't be a problem. For CBC, it will.

  17. Peter G. using Safari 536.26.17 on Mac OS | February 21, 2013 at 4:39 am | Permalink

    Is it possible to get a visual feedback from a DES / T-DES OR DESX encryption as well?

{ 1 } Trackback

  1. [...] blog post is in continuation of the previous post, where I showed why you should not use ECB when encrypting your data. Well, when putting down an [...]

Post a Comment

Your email is never published nor shared.

Switch to our mobile site