PLAINTEXT STEGANOGRAPHY ON THE WEB

Image steganography is a well known technique for hiding messages in plain sight by manipulating some of the image pixels to encode an embedded message. The pixel modifications are so slight that the viewer can’t tell they are seeing a modified image.

original image (source: wikipedia)

The above image contains modified pixels that when extracted compose a second image:

hidden image (source: wikipedia)

Plaintext steganography can be achieved using non-printing whitespace characters from the Unicode character set. As long as the viewport will render the Unicode characters correctly, you can embed hidden messages in plain sight.

To start, what are zero-width or non-printing whitespace characters? These are various formatting directives such as “Zero-Width Non-Joiner” and others that give the viewport directives on how to break up a word across line breaks for instance, but unlike tabs and spaces, they take up no width. They are rendered as invisible in the viewport.

Here is a list of several and what they do:

zero-width characters

We can take a few of these and encode a plaintext message with them by encoding the binary representations of the UTF-16 decimal values of the message to hide. For binary encoding we’ll need three characters, one each for 0, 1, and a boundary separator.

Using these, let’s take the message “I know something you don’t know”, and embed the message “I am not left-handed” inside it.

The UTF-16 decimal values for “I am not left-handed” are as follows:

The binary representation of the Unicode values are as follows:

Now, we represent all the binary values by replacing 1 and 0 with our zero width characters

Remember, the 8203 and 8204 represent the Unicode UTF-16 numbers for a single character and those characters are invisible (zero-width). We’re showing the number representations so you can see them. We concatenate those characters and separate the groups with another invisible character, 8205. Once we do that, here’s our message (again, showing the number value of the characters and separating characters with “,” for readability):

8204,8203,8203,8204,8203,8203,8204,8205,8204,8203,8203,8203,8203,8203,8205,8204,8204,8203,8203,8203,8203,8204,8205,8204,8204,8203,8204,8204,8203,8204,8205,8204,8203,8203,8203,8203,8203,8205,8204,8204,8203,8204,8204,8204,8203,8205,8204,8204,8203,8204,8204,8204,8204,8205,8204,8204,8204,8203,8204,8203,8203,8205,8204,8203,8203,8203,8203,8203,8205,8204,8204,8203,8204,8204,8203,8203,8205,8204,8204,8203,8203,8204,8203,8204,8205,8204,8204,8203,8203,8204,8204,8203,8205,8204,8204,8204,8203,8204,8203,8203,8205,8204,8203,8204,8204,8203,8204,8205,8204,8204,8203,8204,8203,8203,8203,8205,8204,8204,8203,8203,8203,8203,8204,8205,8204,8204,8203,8204,8204,8204,8203,8205,8204,8204,8203,8203,8204,8203,8203,8205,8204,8204,8203,8203,8204,8203,8204,8205,8204,8204,8203,8203,8204,8203,8203,8205

Now let’s embed that in our stegotext.

I know some‍‍‌‌​​​‌‍‌​​‌​​‌‍‌​​​​​‍‌‌​​​​‌‍‌‌​‌‌​‌‍‌​​​​​‍‌‌​‌‌‌​‍‌‌​‌‌‌‌‍‌‌‌​‌​​‍‌​​​​​‍‌‌​‌‌​​‍‌‌​​‌​‌‍‌‌​​‌‌​‍‌‌‌​‌​​‍‌​‌‌​‌‍‌‌​‌​​​‍‌‌​​​​‌‍‌‌​‌‌‌​‍‌‌​​‌​​‍‌‌​​‌​‌‍‌‌​​‌​​‍‍‍thing you don't know!

Well this is hard to do by hand. How about a nice javascript utility for implementing this algorithm easily?

Here you go. Seecret.js is open-source under the MIT license so use it however you like.

How about a nice web form for just making and viewing these plaintext steganography messages? Here you go. Try copying the “I know something you don’t know” stegotext above and reveal the message using the demo form.

Ok, that’s it for now. Have fun!