We are rapidly approaching the end of the semester. Next week you are going to have to take the final exam. On that exam you will need to be able to describe the encodings of Sound and Picture files to me. This lab should help you review these concepts, and fortunately we can do this within the context of the textfiles that we have been working with lately.
On the very first day of the semester, while introducing this class, I mentioned the concept of Steganography.
Wikipedia defines :
"Steganography is the art and science of writing hidden messages in such a way that no one apart from the sender and intended recipient even realizes there is a hidden message. By contrast, cryptography obscures the meaning of a message, but it does not conceal the fact that there is a message. Today, the term steganography includes the concealment of digital information within computer files."
Today you will consider three ways to hide text messages inside of picture and sound files.
The easiest way to hide a secret message into a picture file is to process each letter in your secret message, find the ordinal value of that letter, and put this value into the color data for it's "corresponding" pixel in the picture. There are even two ways to do this. The EASIEST way to do this is to replace the value of one color channel (say, the red channel) with the ordinal values of the characters being encoded.
For example, if I wanted to hide the message "Hi Dr. Schafer" in a picture I would change the red channel of the first pixel to 72 (the ordinal value of "H", change the red channel of the second pixel to 105 (the ordinal value of "i" and so on. In this example I would change the red channel of the first 14 pixels in the picture (the length of my input string).
Thus, if the original pixel color was 123,52,17 and we are trying to hide the letter 'j' (value 106) the new color would be 106,52,17.
At this point I would need to signal the person "reading" the secret message from the picture that I was done (otherwise they would keep reading the red channel of the pixels which would produce a bunch of garbage). In the simpleEncode() we could write a red channel value of zero (ASCII for NULL) to signal the EOF (end of file) [Other options would be a value of 3 or 4 which are ASCII for "end of text" and "end of transmission" respectively]
I have already hidden a message in a picture using this technique.
Download:
Write a method called redDecode(picture,filename). This method should:
To test your method use the picture above. If everything is working properly you should be able to read one of my favorite short-stories in the output file that you selected.
The problem with the previous technique for hiding the secret message is that it has the potential to significantly change the color of the picture which contains the secret message. To illustrate this point, the example I gave above about setting a pixel to contain the letter j produced a color difference of 15 between the original color (123,52,17) and the new color (106,52,17). And these colors weren't even THAT far apart because my original red value was pretty close.
Think about this - typical ASCII values are from 65 to 122. This is a fairly limited set of the values that might be in a red channel (which range from 0-255). Even values that were close to begin with can look "wrong."
If you look at the original picture that I gave you in Activity A it is fairly obvious that something is going on. This is because the red channel of the background in that picture tends to be about 110-125 (which are the ranges of lower case letters), yet lower capital letters are in the 65-90 range, and a space (common in a text file) is a 32 which is quite a bit lower (the cyan spots you see in that image are almost all caused by spaces).
A slightly more complex encode attempts to minimize the difference between the original color of a pixel and it's new color by distributing the ordinal value of each letter across all three channels - not JUST the red channel. In this technique the person hiding the secret message split the ord() value of each char into its 100s part, its 10s part, and its 1s part and then uses these single digits as the last digit in the red, green, and blue channel respectively.
Thus, the letter 'j', whose ordinal value is 106, would get split into 1, 0, and 6. The encoder then modifies the ones value of each rgb channel to equal these three values respectively. Thus, if a pixel with color 0,0,0 was trying to hide the letter j, it would change to 1,0,6. If a pixel with color 123,52,17 was trying to hide the letter j, it would change to 121,50,16.
Notice that the color difference between the original color (123,52,17) and the new color (121,50,16) is only 2.24 - much smaller than the color difference of 15 we observed in Activity A.
Download:
Write a method called fullColorDecode(picture,filename). This method should:
To test your method use the picture above. If everything is working properly you should be able to read the study guide for the final exam.
Ok the title for this section may have you confused. You mean you can hide a picture in a picture? Well, yes, if you know what you are doing and the picture you want to hide isn't too complicated.
To complete this activity download the following image of a recent graduation at UNI:
There is actually a second picture hidden in the encoding of this picture. To see what this second picture is you should write a method called twoBitDecode() that:
The technique used in Activity C, part 1can be adapted to hide text as well. It's actually a little bit complex at first, but once you figure out some math, it produces REALLY nice results that are hard to notice by looking at the source picture because the color shifts are so minor.
The technique we used in Activity A takes the information about a single letter of the secret message and hides it in one color channel of a single pixel. This produces a worst case color shift with a distance of 255 and an "average" distance of ~77.
The technique we used in Activity B takes the information about a single letter of the secret message and hides it in all three color channels of a single pixel. This produces a worst case color shift with a distance of ~15 and an "average" distance of ~7.
The final technique we will study takes the information about a single letter of the secret message and hides it in the red channel of seven pixels. While this takes seven times as many pixels as the previous two techniques, it produces a worst case color shift with a distance of 1 and and "average" distance of 0.5.
As we have been discussing, the letter 'j' has a an ASCII value of 106. We have talked about the fact that all ASCII values exist between 0 and 127. Recall that we can encode the values from 0 to 127 with 7 bits of data:
0 = 0000000 1 = 0000001 ... 106 = 1101010 ... 126 = 1111110 127 = 1111111
These represent bits with values of 64, 32, 16, 8, 4, 2, and 1 (which collectively sum to 127)
A j, whose value is 106 would be encoded as 1101010 = 64 + 32 + 8 + 2 = 106
To encode the letter j in a picture we would consider 7 pixels - one each for the 7 bits of information needed to convert the j to ASCII. For each pixel we begin by looking at the red channel of the pixel. If the red channel currently has an even value, we leave it alone. If the red channel currently has an odd value we subtract 1 to make it an even number. Next, we look at the first of the seven pixels and the "first" (highest order) bit. In this case, the 1 stored in the bit which encodes the value 64. We would add this to the value of the red channel. We then look at the next pixel and the value of the next bit (the 32 bit). Since this is a 1 we would add 1 to the red channel. We then look at the next pixel and the next bit (the 16 bit). Since this is a 0 we would add nothing to the red channel. We would continue this process through the seventh pixel and the lowest (the 1) bit.
Notice that there are a total of four possibilities for each pixel
Half the time, the color shifts by a total of 1 and half the time the color doesn't shift at all.
COOL!
Download:
Write a method called sevenBitDecode(picture,filename). This method should:
To test your method use the picture above. If everything is working properly you should be able to read a special message from me to you.
Write a method called
simpleSoundEncode(sound,filename)
This method should:
You may use any technique you like that largely preserves the original sound. Thus, if I encode hamlet into the Dr. Guzdial reading the preamble, I should be able to hear him reading the preamble the whole way through and I don't want to hear a static hiss garbling the first 8+ seconds of the sound. (How many samples would be used up if you did a STRAIGHT replace one character per sound sample).