Write hidden messages to image file c#

2020-08-04 02:42发布

问题:

I was looking for a tutorial where is described how to write/read hidden text into image file using C#, but unfortunately I din;t find any good posts about this, so I decided to ask here about this small trick.

Suppose I have an image file called test.jpg , is there any way to write an hidden text like "Hello word " to this file ? I have read about image metadata , and I suppose that I should try to write somehow to this metadata , but I din;t find how. If anybody know how to do it , please help me to understand how to it. Thanks.

回答1:

The correct term for this is "Steganography".

The following article state's the definition of Steganography:

Steganography is the art and science of hiding information by embedding messages within others. Steganography works by replacing bits of useless or unused data in regular computer files with bits of different, invisible information. This hidden information can be plain text, cipher text, or even images

Step by step explanation on how Steganography works:

  • Loop through the pixels of the image. In each iteration, get the RGB values separated each in a separate integer.
  • For each of R, G, and B, make the LSB equals to 0. These bits will be used in hiding characters.
  • Get the current character and convert it to integer. Then hide its 8 bits in R1, G1, B1, R2, G2, B2, R3, G3, where the numbers refer to the numbers of the pixels. In each LSB of these elements (from R1 to G3), hide the bits of the character consecutively.
  • When the 8 bits of the character are processed, jump to the next character, and repeat the process until the whole text is processed.
  • The text can be hidden in a small part of the image according to the length of that text. So, there must be something to indicate that here we reached the end of the text. The indicator is simply 8 consecutive zeros. This will be needed when extracting the text from the image.

It's more simple than hiding. Just pass through the pixels of the image until you find 8 consecutive zeros. As you are passing, pick the LSB from each pixel element (R, G, B) and attach it into an empty value. When the 8 bits of this value are done, convert it back to character, then add that character to the result text you are seeking.

An example source code would be::

class SteganographyHelper
{
    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 occurs
                        // 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;
    }
} 

Source article: http://www.codeproject.com/Tips/635715/Steganography-Simple-Implementation-in-Csharp



回答2:

You can also refer this.. Image Steganography Application C#