Stego my Ego: Hiding Secrets in Digital Images

Brent Heeringa and Thomas P. Murtagh
Williams College

Summary A final programming project exploring steganography (hiding information in other information), data representation, and image manipluation.
Array processing, binary arithmetic, data representation, and character encodings.
Appropriate for the end of CS 1 or beginning of CS 2.
Moderate to challenging. We developed this as our final programming project. The students had two weeks to work on it.
The students directly explore and manipulate data representations of images, integers, and characters in a motivating context: steganographic protocols.
The project depends on SImage, a non-standard class for representing images. It also depends on a second non-standard class for GUI event handling, but this dependence could easily be eliminated. Both of these classes are part of the Squint library developed to support introductory courses using Java.
This is a final project so it requires knowledge of basic control structures, class and method definitions, and the construction of simple Swing GUI interfaces. We also assume knowledge of 2D-arrays, integer division, and strings.
Steganography is not limited to hiding text in images. One could hide other images in images, songs in images, video in images, or vice-versa.


The Wikipedia entry for steganography provides the following:

Steganography is the art and science of writing hidden messages in such a way that no one apart from the intended recipient knows of the existence of the message; this is in contrast to cryptography, where the existence of the message itself is not disguised, but the content is obscured. . .

Generally, a steganographic message will appear to be something else: a picture, an article, a shopping list, or some other message. This apparent message is the covertext. For instance, a message may be hidden by using invisible ink between the visible lines of innocuous documents.

The advantage of steganography over cryptography alone is that messages do not attract attention to themselves, to messengers, or to recipients. An unhidden coded message, no matter how unbreakable it is, will arouse suspicion and may in itself be incriminating, as in countries where encryption is illegal.

As an example, while we all know that a picture is worth a thousand words, the lovely picture of our college campus shown below is worth quite a few more.

Hidden in this picture is the text of an entire short story , Roald Dahl's "Beware of the Dog." This story is over five thousand words long.

For this assignment, students construct a very basic steganographic system by implementing two two pairs of data transformations. The first two transformations provide the means to hide and later extract an approximation of a secret image in a cover image. The second pair of transformations make it possible to represent segments of text in the form of a black and white images that can be steganographically hidden in cover images using the first pair of transformations.

Hiding Images in Images

A sample of the interface provided by the program the student's construct is shown below.

The window is divided into three sections --- the leftmost sub-window is used to hold a cover image, the middle sub-window is used to hold a secret image, and the rightmost sub-window is used to display the steganographic image the program produces by combining the two.

Below each sub-window there are buttons that can be used to load an image into the sub-window. When these buttons are pressed, the program displays a dialog that can be used to select the desired image file. For example, by first pressing the leftmost "Load" button and then the middle "Load" button, we could access two image files as shown below:

The image on the left is a beautiful landscape from Mynamar we will use as a cover image. The image in the middle is an appropriate cartoon to use as our secret image.

Once the cover and secret images are loaded, we can produce an image in which the secret image is hidden within the cover image by pressing the "Encrypt" button. The resulting image is displayed on the right side of the program's window as shown below:

This image can be saved in a file by pressing the "Save" button.

The process of hiding a secret image within a cover image is accomplished by encoding approximations of the brightness values of the secret image in the low order bits of the brightness values of the cover image. In particular, the students write code to replace the lowest bit in each of the three color brightness values describing the color of each pixel in the cover image with the high bit of the corresponding brightness value from the corresponding pixel of the secret image. Since only the low order bits of the cover image brightness values are changed, the resulting image will be indistinguishable from the original cover image.

The students also implement the reverse transformation. To exercise this feature, one would first load an image containing a secret into the rightmost sub-window as shown below:

Once an image is loaded in this way, pressing the "Decrypt" button instructs the program to extract the hidden image and display it in the center of the program's window as shown below:

Since only one bit of each of the secret image's brightness values can be extracted in this way, only an approximation of the original secret image can be retrieved. If the program was used to hide a grayscale image, the extracted image will be reduced to black and white. If you hide a color image, only 8 shades of color will be preserved by the extraction process. If the secret image is black and white to start with, the black pixels will remain black and the white pixels will become light gray. While this is a limitation when the program is actually used to hide images, it is perfect for its true purpose, hiding text in cover images.

Hiding Text in Images

The second pair of transformations the students implement provides the means to generate a black and white image that encodes a block of text and to extract text from suitable black and white images. When the first of these transformations is used to encode text as an image, each pixel of the image produced will correspond to one bit from the ASCII representation of the String being encoded. If the bit is a 1, then the pixel will be bright. If the bit is a 0, then the pixel will be black.

You may have noticed that the middle sub-window of the program's interface is just a bit different from the left and right sub-windows. There is a text area at the top of the sub-window where one can place text to be hidden within an image. The image below illustrates how this is done. First we load a cover image into the left sub-window and paste some text into the middle sub-window. In this case, the text we have chosen is the contents of this web page.

Next, by pressing the "Encode" button we tell the program to create an image in which the pixels are painted black and white corresponding to where 0's and 1's appear in the ASCII encoding of the text we entered. The pattern of 1s and 0s used to encode a piece of text can be pretty random. That's why the encoded image shown below looks like the Matrix (take the red pill and stay in wonderland).

Finally, by pressing the "Encrypt" button, the program hides this random-looking secret image under the cover image provided as shown below.

Of course, the reverse transformation is also supported. One can load an image containing hidden text in the right sub-window, and then press the "Decrypt" button followed by the "Decode" button to reveal the hidden message as shown below.

In fact, we have hidden some interesting secret text in one of the images included in this web page. Those of you intested in seeing a sample solution to this program just have to figure out which image it is!


Extra info about this assignment: