Hiding Secret Messages in Images using C# Program

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 the best C# Book you can find : C# School by Faraz Rasheed.

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.

11 thoughts on “Hiding Secret Messages in Images using C# Program”

  1. 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.

  2. 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??

  3. 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

Comments are closed.