![]() |
|||||||||||
|
|
||||||||||
IntroductionThis article describes how any data can be hidden in the noise pixels of an image. BackgroundThere is only one save place for private data and messages: The place where
nobody looks for it. How it works
To see how the application works, you should view the source.
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
|