Steganography is the science of hiding information within other information. For example, a watermark “hides” an image on a piece of paper. If you look at most paper currency at a low angle or if you hold it up to a bright light, you can see a ghostly image inside the paper. When you look at the currency straight on in normal light, you cannot see the image. Because this example is so easy to understand, steganography is sometimes called “watermarking.”
Another example is a correspondence where the last letter in each word spells out a secret message. Composing this sort of message can be fun. The more constraints you place on the correspondence, the more challenging it is to write something that satisfies the constraints and still contains the hidden message. For example, try writing a poem where the last letter of each word spells out the message. Or try writing a sonnet, which has particular rules for the poem’s meter and rhyme.
Today steganography is often used to hide copyright information in an image, movie, or audio file. The information is carefully encrypted and hidden so you cannot easily find it. Later, if I think you have stolen my movie file, I can pull the hidden copyright information out of it to prove it is mine not yours.
This example encodes a message in an image. For each bit in the message, the program selects a pseudo-random pixel and color component (red, green, or blue). It then sets the least significant bit of the color component on that pixel to the message bit.
For example, suppose the chosen pixel is green so its red, green, and blue components in binary are 0000, 1111, and 0000 respectively. Now suppose the program wants to hide the bit value 1 in this pixel’s red component. The new pixel value has components 0001, 1111, 0000. That’s so close to the original value that you won’t notice the difference when you look at the image.
For another example, suppose the program wants to store the bit value 0 in the same pixel’s blue component. The least significant bit in that component is already 0 so there is no change to the color.
These changes are so small they are almost impossible to detect. In a photographic image, you won’t be able to tell the difference just by looking.
This program handles a lot of little details. For example, before it stores its message it stores the length of the message. That allows the program to know how many characters are encoded when it tries to decode them.
The program uses a password to initialize a random number generator from the Random class. When you decode the message, the program initializes the random number generator using the same password so the Random object produces the same series of pseudo-random numbers. That lets the program determine which pixels and color components to use when decoding the message.
If you replace C#’s Random class with a cryptographically secure pseudo-random generator, you will get a much more secure system. If you encrypt your message before you embed it in the image, it will be even harder to break.
The program also needs to ensure that each message bit maps to a different pixel color component. If two message bits mapped to the same component, the second would hide the value of the first. This program uses a HashSet to keep track of the pixel/component values that it has already used so it doesn’t use one twice. See Perform set operations in C# for information on the HashSet class that this program uses to keep track of the used pixels and components.
Use the program’s radio buttons to display the original image, the image with a message encoded in it (switch back and forth to compare the two), or a “marked” image that shows the encoding pixels in red.
Download the example program and look at the code for additional details.