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?
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.
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:
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:
Another Pikachu, from Ye Olde Pokemon Red/Green:
Not so immediately obvious, but the overall shape is clearly visible.
One last one, a photo of my beloved Princess Bubblegum:
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:
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!