0

I've written some code, it's just an experiment. I had an idea (probably has been done before) to create a random image and set pixels rgb values at random locations to an ascii character number in order to hide messages in the image. It almost works, but for some reason i get strange returns on the decryption such as "tiis is me secter text" instead of "this is my secret text" Well here is the code:

   public Form1()
    {
        InitializeComponent();
    }

    //storing pixel locations
    public static List<int> pixel_list = new List<int>();

    public static Bitmap bitmap = new Bitmap(144, 119);
    private void Form1_Load(object sender, EventArgs e)
    {

        bitmap = GenerateNoise(144, 119);

        bitmap = encrypt("this is my secret text",bitmap);

        pictureBox1.Image = bitmap;
    }

    public static void decrypt(Bitmap img) 
    {
        string str="";
        foreach (int pix in pixel_list)
        {
            //get the pixel from the list of pixel locations
            Color color = img.GetPixel(pix, pix);
            //convert the pixels rgb value in to a char and append it to str
            str += Convert.ToChar(color.R).ToString();

        }
        //we have the original message
        MessageBox.Show(str);
    }

    public Bitmap encrypt(string message, Bitmap img)
    {
        Random rnd = new Random();
        byte[] ASCIIValues = Encoding.ASCII.GetBytes(message);
        foreach (byte b in ASCIIValues)
        {
            //select a random pixel
            int pixelXY = rnd.Next(1, 119); 
            //add it to the list
            pixel_list.Add(pixelXY);
            //chnage that pixels rgb value to the ascii code (b)
            img.SetPixel(pixelXY, pixelXY, Color.FromArgb(b, b, b));
        }

        return img;
    }

    public Bitmap GenerateNoise(int width, int height)
    {
        Bitmap finalBmp = new Bitmap(width, height);
        Random r = new Random();

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                int num = r.Next(0, 256);
                finalBmp.SetPixel(x, y, Color.FromArgb(10, num, num, num));
            }
        }

        return finalBmp;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        decrypt(bitmap);
    }
user2864613
  • 169
  • 1
  • 4
  • 10
  • 2
    What if `rnd.Next(1, 119);` in the `encrypt` method returns the index value that has been already used? It will then rewrite the already used pixel with a new data value. You have to guarantee the uniqueness of each pixel index. – Eugene Podskal Mar 13 '15 at 14:23
  • yeah i did think about that but then disregarded it as "probably not the reason" i'll check now.. – user2864613 Mar 13 '15 at 14:24
  • i think you should use 2 integers pixelX and pixelY instead of pixelXY for pixel coordinates and check previous pixel_list entries before adding new one in case of duplication – Emre Mar 13 '15 at 14:27
  • 1
    If the Image is random you could go for inserting the magic pixels directly by using a seeded Random object. No need to store the pixels, just the seed will do.. – TaW Mar 13 '15 at 14:45
  • 1
    It's called [steganography](https://en.wikipedia.org/wiki/Steganography). – kenorb Mar 13 '15 at 15:00
  • @EugenePodskal is correct. I get similar errors at different places, presumably because my random generated produced different values. If you change it to use a counter instead of a random generator the problem goes away – Moby Disk Mar 13 '15 at 18:46

1 Answers1

1

I think when you are decrypting, you are using Unicode instead of ASCII. You should decrypt the reverse way to the way you encrypt. First of all store all your bytes in a byte array, then convert the array to a string using string str = System.Text.Encoding.ASCII.GetString(yourByteArray)

IglooGreg
  • 147
  • 5
  • Yes, that is an important moment(so +1) but it won't cause problems `such as "tiis is me secter text" instead of "this is my secret text"`, because such bytes (after (Char) cast) represent values that are both valid ASCII and UTF-16. The problem lies with the seed value of the `Random`. It should be stored in some predetermined pixels on encryption and then used to reseed the RNG on decryption - http://stackoverflow.com/questions/1785744/how-do-i-seed-a-random-class-to-avoid-getting-duplicate-random-values. – Eugene Podskal Mar 13 '15 at 18:59
  • @Eugene, I don't understand what you mean. The OP is saving the random values e.g. 5, 97, 66, etc in a List,and to decrypt they are going through this same list, e.g. get the colour from pixel (5,5) then pixel (97,97) etc. so why re-seed the Random? – IglooGreg Mar 15 '15 at 11:36
  • Oh, yes, sorry for this silliness. Seed storing and reseeding won't help on its own, values shall be made unique in any case - I just thought about it as a way to persist the indexes sequence in the image itself, but in a hurry miswrote it as a way to solve the problem. [Non-repetitive random number generator](http://stackoverflow.com/questions/1011198/non-repetitive-random-number) is the answer, just as a use of the simple `Distinct` over the initially generated indexes sequence. – Eugene Podskal Mar 15 '15 at 16:00