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.
What is Steganography?
As Wikipedia puts it
Steganography is the practice of concealing a file, message, image, or video within another file, message, image, or video. The word steganography combines the Greek words steganos (στεγανός), meaning “covered, concealed, or protected”, and graphein (γράφειν) meaning “writing”.
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.
How to Do Steganography in C#?
This example encodes a message in an image. An image is composed of pixels. For each bit in our secret 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.
C# Project
First, Let us show how actually this program uses Steganography to store messages in images in reality.
Steganography Source Code in C#
Here is the Steganography.CSharpens class code. For the complete working application, godown.
using System; using System.Drawing; namespace Stegnography.CSharpens { class Stegnography { public enum State { Hiding, Filling_With_Zeros }; public static Bitmap embedText(string text, Bitmap bmp) { // initially, we'll be hiding characters in the image State state = State.Hiding; // holds the index of the character that is being hidden int charIndex = 0; // holds the value of the character converted to integer int charValue = 0; // holds the index of the color element (R or G or B) that is currently being processed long pixelElementIndex = 0; // holds the number of trailing zeros that have been added when finishing the process int zeros = 0; // hold pixel elements int R = 0, G = 0, B = 0; // pass through the rows for (int i = 0; i < bmp.Height; i++) { // pass through each row for (int j = 0; j < bmp.Width; j++) { // holds the pixel that is currently being processed Color pixel = bmp.GetPixel(j, i); // now, clear the least significant bit (LSB) from each pixel element R = pixel.R - pixel.R % 2; G = pixel.G - pixel.G % 2; B = pixel.B - pixel.B % 2; // for each pixel, pass through its elements (RGB) for (int n = 0; n < 3; n++) { // check if new 8 bits has been processed if (pixelElementIndex % 8 == 0) { // check if the whole process has finished // we can say that it's finished when 8 zeros are added if (state == State.Filling_With_Zeros && zeros == 8) { // apply the last pixel on the image // even if only a part of its elements have been affected if ((pixelElementIndex - 1) % 3 < 2) { bmp.SetPixel(j, i, Color.FromArgb(R, G, B)); } // return the bitmap with the text hidden in return bmp; } // check if all characters has been hidden if (charIndex >= text.Length) { // start adding zeros to mark the end of the text state = State.Filling_With_Zeros; } else { // move to the next character and process again charValue = text[charIndex++]; } } // check which pixel element has the turn to hide a bit in its LSB switch (pixelElementIndex % 3) { case 0: { if (state == State.Hiding) { // the rightmost bit in the character will be (charValue % 2) // to put this value instead of the LSB of the pixel element // just add it to it // recall that the LSB of the pixel element had been cleared // before this operation R += charValue % 2; // removes the added rightmost bit of the character // such that next time we can reach the next one charValue /= 2; } } break; case 1: { if (state == State.Hiding) { G += charValue % 2; charValue /= 2; } } break; case 2: { if (state == State.Hiding) { B += charValue % 2; charValue /= 2; } bmp.SetPixel(j, i, Color.FromArgb(R, G, B)); } break; } pixelElementIndex++; if (state == State.Filling_With_Zeros) { // increment the value of zeros until it is 8 zeros++; } } } } return bmp; } public static string extractText(Bitmap bmp) { int colorUnitIndex = 0; int charValue = 0; // holds the text that will be extracted from the image string extractedText = String.Empty; // pass through the rows for (int i = 0; i < bmp.Height; i++) { // pass through each row for (int j = 0; j < bmp.Width; j++) { Color pixel = bmp.GetPixel(j, i); // for each pixel, pass through its elements (RGB) for (int n = 0; n < 3; n++) { switch (colorUnitIndex % 3) { case 0: { // get the LSB from the pixel element (will be pixel.R % 2) // then add one bit to the right of the current character // this can be done by (charValue = charValue * 2) // replace the added bit (which value is by default 0) with // the LSB of the pixel element, simply by addition charValue = charValue * 2 + pixel.R % 2; } break; case 1: { charValue = charValue * 2 + pixel.G % 2; } break; case 2: { charValue = charValue * 2 + pixel.B % 2; } break; } colorUnitIndex++; // if 8 bits has been added, then add the current character to the result text if (colorUnitIndex % 8 == 0) { // reverse? of course, since each time the process happens on the right (for simplicity) charValue = reverseBits(charValue); // can only be 0 if it is the stop character (the 8 zeros) if (charValue == 0) { return extractedText; } // convert the character value from int to char char c = (char)charValue; // add the current character to the result text extractedText += c.ToString(); } } } } return extractedText; } public static int reverseBits(int n) { int result = 0; for (int i = 0; i < 8; i++) { result = result * 2 + n % 2; n /= 2; } return result; } } }
Download
You can also download the working app from below. This application is developed in Visual Studio 2012. You might need to upgrade or downgrade it if you use any other version of Visual Studio. File size in 97KB
You can ask any questions related to this or any other programming issue in our C# Group on Facebook.
Sajjad, Is there anyway we can use this steganography to hide messages in plain text? Like for example in Arabic words? We can use Kasheeda to encrypt messages in words. I would like if you address this topic.
I did tried to develop a program to do steganography in arabic text but i have not shared it on the site. You can easily find some research papers on this topic.
Hi Sajjad I have just begun my journey in programming some two months ago or so(even though am studying geo-engineering, and am more of numerical modeler), I can say am hooked. I hooked by tech and software capabilities. But so far i went so many websites and blogs but truly yours is clear and gives good insight brother, well done and i love it at all. When a man does good work he must be praised as due. I wanted to ask if you have a source code on creating a web application for your online cv type of style ??can you give me references or how much you charge for that??
Can this project be Submitted for Final Year University Project
Ahmed! I think you need to add multiple other factors & features to it if you want to make it your FYP.
can the code be in the windows form design and not in added windows form? and remove the public enum
need helps..
can u build with steganography end of file method?
thx
hey i was unable to download this project i am getting Error 404
Hi, i have tried to download source code of above mentioned example, but unable to download because of 404 error. Kindly make this link working so it can be downloaded. Thanks
is there a difference between steganography and digital watermarking?
Hello brother , i can’t download this file . please check this download file.