Steganography- The real layman way!
What is Steganography?
Well, that's a technique of hiding secret data within an ordinary file. Too vague? This picture below has a hidden message in it.
Image 2, has a hidden message in it. Interesting, right?
“The key to steganography is to hide the data in such a way that nobody can easily tell that you have altered the original image.”
Well as a part of one of the programming courses on Coursera, I found this interesting topic so I thought to write it down. And here it goes :)
Steganography is the hiding of data in an image or other digital artifact.
I’ll explain with an example of hiding one image inside another image. Like the one image message is hidden in Usain Bolt’s image. If the blog doesn’t get too long we’ll also go on extracting information out of an image that contains a hidden message.
We know that a pixel in an image has a red, blue and green component which numerically represents the color.
Is there much difference between red value: 240 and red value: 255? Numerically- yes. Visually- No. That’s the basic alteration that happens inside.
The fact that you can’t easily tell the difference in images when you change the numerical color value of pixel slightly is the key to hiding data in an image.
We can store the hidden data in the least significant digit of the color value and not seeing much change.
We can hide data in ones and tens places of the pixel value like we can hide value 15 in 240 and show it 255(Max pixel value) and that won’t make any significant difference.
For the implementation, we’ll do a bit of basic maths- multiplication, division, add and subtract. We just have to put them together, the right way.
To understand how to do this math, we ll understand with Base 10 numbers system we use every day, then learn about Binary (Base 2) that computer uses to store numbers. All the principals in Base 2 would be the same as in Base 10, just that we’ll use powers of 2 instead of powers of 10.
To see this idea in the familiar base 10, suppose the values used for red, blue and green vary from 0–9999 instead of 0–255. This gives each component of color 4 decimal digits.
Now, suppose we want to hide this red pixel with RGB values as shown inside this blue pixel with RGB values shown.
For the result, we take the two most significant digits of the pixel of the image we want to hide in, which is the blue pixel. And use them as the most significant two digits of the result. Then we take 2- most significant digits of the pixel we want to hide(the red pixel) and use them as the least significant digits of the resultant pixel. For simplicity, here is the pictorial way.
This alteration leads us to the final result as shown below.
If we look at the resultant pixel, it pretty hard to tell the difference between it and the original blue pixel. But as we see we have hidden a Red pixel inside it. Notice that 3582 in “Result” is pretty similar to 3568 in “In This”. They look almost the same, but we have changed it slightly so it stores the secret information in its least significant digits.
Now that the information is hidden, how would we extract the secret? We know that we want to extract the 2 least significant digits of the “Result” pixel to be the most significant 2 digits of the hidden and soon to be extracted pixel Red.
But what about the least significant digits of the secret message? Well, that doesn’t really matter much so we’ll pick 0s.
Similarly, we do for the remaining colors of the hidden pixel and get the hidden pixel as “Extracted”, with the least significant digits put to 0.
The shade of red that we got back is quite similar to what we hidden, though there is a slight difference in its values. Even though we don't get the exact pixel back out, but as a whole, we get the final image indistinguishable from the original image. We ll see that happening soon.
Now we got the basic maths involved in it, taking digits from each number and combining them. However, to implement this in code we’ll need to know about Binary(The Base 2 number system) that the Computer works in, which is why the values of colors go from 0–255 instead of 0–9999 that we just worked with.
8149=8*(1000)+1*(100)+4*(10)+9 : The Base 10 Number system. 10111=1*(16)+0*(8)+1*(4)+1*(2)+1: The Binary Number system.
The RGB components of pixels range from 0–255 because they are stored in a computer with 8 binary digits called “bits” where ‘b’-binary and “its”-Digits.
00000000(Binary)=0(Decimal) & 11111111(Binary)=255(Decimal)
Now that we know that each color is an 8-bit binary number, let's revisit the Steganography problem. We want to hide an 8-bit number on the left inside an 8-bit number on the right. We’ll follow the same maths as we did in the Decimal number system(Left picture) to find results in the Binary number system(Right picture.)
To extract the hidden message back from the image. Similarly, we do the modulus with 16 of the result in the above Binary calculation to get the 4-most significant bits of the secret image. And what about the rest 4- least significant digits? Well as they don’t matter much, we put them 0s here again.
Now that we know the big picture of Steganography that is all about the basics of binary maths. Now is the time to put all of that together to hide the message inside an image. Here goes the task!
We are already well versed in how it works for one pixel.
We need to do the same for each pixel in the image. An image that is 2048 pixels in width and 1536 pixels in height has a total of 2048×1536 = 3,145,728 pixels or 3.1 megapixels. We’ll need computation to access each pixel and do the binary maths.
I’ll code in JavaScript by breaking down the problem into functions to do several tasks involved. We’ll using DukeLearnToProgramming’s “SimpleImage” JavaScript Library which makes it easy to work with pixels. Documentation for same can be referred from : http://www.dukelearntoprogram.com/course1/doc/#simpleimage
You can run the below code in DLTP IDE at (http://www.dukelearntoprogram.com/course1/example/index.php)to see Steganography in action.
- Function tochop() extracts 4 most significant bits from “Galaxy” image’s pixels and puts rest pixels to 0 and returns the image like (XYZY0000).
function tochop(image){ for(px of image.values()){ px.setRed(Math.floor(px.getRed()/16)*16); px.setGreen(Math.floor(px.getGreen()/16)*16); px.setBlue(Math.floor(px.getBlue()/16)*16); } return image;
}
- Function toshift() moves 4- most significant bits of “secret message” in place of 4-least significant bits and thus 4- most significant bits are set to 0s. The returned image is like (0000ABCD).
function toshift(image){ for(px of image.values()){ px.setRed((px.getRed()/16)); px.setGreen((px.getGreen()/16)); px.setBlue((px.getBlue()/16)); } return image;
}
- As we can observe we are on the track to make XYZW0000(Galaxy Image)+0000ABCD(Secret Image)=XYZWABCD(Image containing secret message).
- Finally, the function combine() does the task mentioned in the above point and we get the galaxy image as XYZWABCD that contains a secret message image.
function combine(show,hide){ var out=new SimpleImage(show.getWidth(),show.getHeight()); for(px of out.values()){ var x=px.getX(); var y=px.getY(); var showPx=show.getPixel(x,y); var hidePx=hide.getPixel(x,y); px.setRed(showPx.getRed()+hidePx.getRed()); px.setGreen(showPx.getGreen()+hidePx.getGreen()); px.setBlue(showPx.getBlue()+hidePx.getBlue()); } return out;
}
- The flow of execution of the above functions to do the task go as follows:
var toshow=new SimpleImage("Galaxy.png");var tohide=new SimpleImage("secret-message.png");var chopped=tochop(toshow);var shifted=toshift(tohide);var out=combine(chopped,shifted);print(out); //The resultant image that has the secret message.**for this solution to work, the images has to be of same sizes.**so you may have to write(implement) crop function in order to make the imgaes of same size.
So we have the final galaxy image which looks basically the same as the original Galaxy image but has a hidden message inside. Ya, so its that simple to hide a secret message inside an image. The secret message image can be extracted back in the way I explained above. Since the blog already got too long, I m leaving that part for readers :)
Thanks for reading the first blog of my life XD.