C# source files - 9.43 Kb

Introduction

This article describes how any data can be hidden in the noise pixels of an image.

Background

There is only one save place for private data and messages: The place where nobody looks for it.
A file encrypted with algorithms like PGP are not readable, but everybody knows that there is something hidden. Wouldn't it be nice, if everyone could open your encrypted files, and see noisy photos of some old friends instead of your private data? They surely wouldn't  look for pieces of encrypted messages in the pixel values.

How it works

To see how the application works, you should view the source.
Here is a summary about hiding:

And about extracting:

The process starts with writing the length of the entire message into the first pixel. We'll need this value before extracting the message later on.

messageLength = (Int32)messageStream.Length;

//do some length conflict checking here
//...
//Write length of the message into the first pixel
int colorValue = messageLength;
int red = colorValue >> 2;
colorValue -= red << 2;
int green = colorValue >> 1;
int blue = colorValue - (green << 1);
pixelColor = Color.FromArgb(red, green, blue);
bitmap.SetPixel(0,0, pixelColor);

Then it reads a byte from the key stream to calculate the position of the next pixel to use:

//start with second pixel
Point pixelPosition = new Point(1,0);

//Loop over the message
for(int messageIndex=0; messageIndex<messageLength; messageIndex++){
        //repeat the key, if it is shorter than the message
        if(keyStream.Position == keyStream.Length){
        keyStream.Seek(0, SeekOrigin.Begin);
}
//Get the next pixel-count from the key, use "1" if it's 0
currentStepWidth = keyStream.ReadByte() + 1;

//Perform line breaks, if current step is wider than the image
while(currentStepWidth > bitmapWidth){
        currentStepWidth -= bitmapWidth;
        pixelPosition.Y++;
}

//Move X-position
if((bitmapWidth - pixelPosition.X) < currentStepWidth){
        pixelPosition.X = currentStepWidth - (bitmapWidth - pixelPosition.X);
        pixelPosition.Y++;
}else{
        pixelPosition.X += currentStepWidth;
}

Now get the pixel and put the message-byte into one color component (or all components, if the grayscale flag is set):

 //Get color of the "clean" pixel
 pixelColor = bitmap.GetPixel(pixelPosition.X, pixelPosition.Y);

 //To add a bit of confusion, xor the byte with the current pixel distance
 int currentByte = messageStream.ReadByte() ^ currentKeyByte;

 if(useGrayscale){
  pixelColor = Color.FromArgb(currentByte, currentByte, currentByte);
 }else{
  //Change one component of the color to the message-byte
  SetColorComponent(ref pixelColor, currentColorComponent, currentByte);
  //Rotate color components
  currentColorComponent = (currentColorComponent==2) ? 0 : (currentColorComponent+1);
 }
} //end of for - proceed to next byte

If the method runs in extraction mode, it reads the message's length and the color components instead of setting it. Here is how to get the length from the first pixel:

pixelColor = bitmap.GetPixel(0,0);
messageLength = (pixelColor.R << 2) + (pixelColor.G << 1) + pixelColor.B;
messageStream = new MemoryStream(messageLength);

The pixel coordinates are calculated the same way as described above. Then the hidden byte is extracted from the color value:

 //Get color of the modified pixel
 pixelColor = bitmap.GetPixel(pixelPosition.X, pixelPosition.Y);
 //Extract the hidden message-byte from the color
 byte foundByte = (byte)(currentKeyByte ^ GetColorComponent(pixelColor, currentColorComponent));
 messageStream.WriteByte(foundByte);
 //Rotate color components
 currentColorComponent = (currentColorComponent==2) ? 0 : (currentColorComponent+1);
} //end of for - proceed to next byte