Encrypting Images with Electronic CodeBook

I recently started a series on Encryption with JavaScript. In my latest entry I mentioned I'd follow up with Modes of Operations.

Before we dive into that last piece of the series, I wanted to have a little fun and showcase encryption of images with the most primitive (and insecure) mode of operation, Electronic CodeBook (ECB for short).

For this I built a simple NodeJS application that encrypts all images with a random encryption key. The key itself is irrelevant, as I'm only trying to provide a visual example of why we should never use ECB.

Let's start with a simple one. Can you guess what this is?

Click or touch anywhere on the image to reveal the unencrypted version.

Yep, that's a young Goku. My wife guessed it on the third or fourth attempt, after "some kind of elf" and "yoda".

Let's see another Goku, this time taken from a high quality frame of the anime.

Click or touch anywhere on the image to reveal the unencrypted version.

In this case, since there are more different pixels, it's way harder to see a pattern. We only get to recognize his hair and shoes, which are plain black. I suspect Goku is digitally drawn here, and overlaid over an original background, probably watercolor.

Let's look at another frame from the show, but this time with TV quality:

Click or touch anywhere on the image to reveal the unencrypted version.

This one is mostly noise. Again we get to see a pattern for the hair, but it's less noticeable due to black pixels not being the exact same RGB value.

There are a few more fun examples. This digitally-drawn Pikachu is clear as day:

Click or touch anywhere on the image to reveal the unencrypted version.

Another Pikachu, from Ye Olde Pokemon Red/Green:

Click or touch anywhere on the image to reveal the unencrypted version.

Not so immediately obvious, but the overall shape is clearly visible.

One last one, a photo of my beloved Princess Bubblegum:

Click or touch anywhere on the image to reveal the unencrypted version.

This last one, due to the high resolution and quality of the picture, looks like random noise after encryption. This doesn't mean it would be safe to encrypt this with ECB, but it's not immediately obvious.

We can still see a bit of a pattern in it. If we start by assuming all the pixels of the pattern are black, which is a reasonable guess, we could probably get some data of the image, maybe an outline, and take it from there.

Finally, we have our good old Tux:

Click or touch anywhere on the image to reveal the unencrypted version.

I created these images with tux-ecb, a quick project I built for the occasion using NodeJS.

The code only works on .bmp files and does not encrypt the bitmap header to avoid breaking the file entirely. In real life, the header would be encrypted, but bitmap headers are pretty standard and it wouldn't take effort for an attacker to guess the values by trial and error.

JPEG files won't work as easily due to compression, but I bet knowledge of the protocol would lead to decryption.

This also works with plain text, to an extent. Going with trial and error, we can start by assuming the text is in English. The most common letter in English is e. There are well studied probabilities of English letters showing up in texts. Just starting with that would probably show us some patterns, and then we could quickly take it from there to full decryption by looking for word lengths, etc.

Alphabets have way fewer possible values than RGB images, so it should be relatively easy to solve, specially if using ASCII. This is not as straight-forward as it sounds, though, since characters are not always a single byte, and AES and other block cyphers don't encrypt byte-by-byte.

I made a small experiment comparing the frequency of appearance of letters of the English language on average vs. an extract from Dune, showing e is a clear winner in both, but they then deviate due to the small sample. Check out the gist for more details and source code.

Anyway, that's it for today. Thank you for reading and see you in the next one!

A newsletter for programmers

Yo! This is Taro. I've been doing JavaScript for years and TypeScript for years. I have experience with many programming languages, libraries, frameworks; both backend and frontend, and in a few company roles/positions.

I learned a few things over the years. Some took more effort than I wish they had. My goal with this blog and newsletter is to help frontend and backend developers by sharing what I learned in a friendlier, more accessible and thorough manner.

I write about cool and new JavaScript, TypeScript and CSS features, architecture, the human side of working in IT, my experience and software-related things I enjoy in general.

Subscribe to my newsletter to receive notifications when I publish new articles, as well as some newsletter-exclusive content.

No spam. Unsubscribe at any time. I'll never share your details with anyone. 1 email a week at most.

Success!
You have subscribed to Taro's newsletter
Shoot!
The server blew up. I'll go get my fire extinguisher — please check back in 5.