The code challenge was, as Buzzly correctly figured out, an image encoded using only the least significant bits of a second image. Heres the code I wrote to decrypt (desteg actually..) the 'message3.png file:
<?php
$source = imagecreatefrompng("message3.png");
$output = imagecreatetruecolor(imagesx($source),imagesy($source));
for ($x=0;$x<imagesx($source);$x++) {
for ($y=0;$y<imagesy($source);$y++) {
$rgb=imagecolorat($source,$x,$y);
$r=(((($rgb>>16)&0xFF)&1)==1)?255:0;
$g=(((($rgb>>8)&0xFF)&1)==1)?255:0;
$b=((($rgb&0xFF)&1)==1)?255:0;
$col=imagecolorallocate($output,$r,$g,$b);
imagesetpixel($output,$x,$y,$col);
}
}
header("Content-Type: image/png");
imagepng($output);
?>
Creating the steganographically encoded image was just as easy. I took the original image of my cats face, and a black and white (2 colours, not greyscale..) image of the text to be encoded, and wrote a little script to combine the two:
<?php
$source = imagecreatefrompng("message1.png");
$message = imagecreatefrompng("message2.png");
$output = imagecreatetruecolor(imagesx($source),imagesy($source));
for ($x=0;$x<imagesx($source);$x++) {
for ($y=0;$y<imagesy($source);$y++) {
$rgb = imagecolorat($source,$x,$y);
$r=(($rgb>>16)&0xFF);$g=(($rgb>>8)&0xFF);$b=($rgb&0xFF);
$rgb = imagecolorat($message,$x,$y);
if ($rgb == 0) {
$r=$r&~1;$g=$g&~1;$b=$b&~1;
} else {
$r=$r|1;$g=$g|1;$b=$b|1;
}
$col = imagecolorallocate($output,$r,$g,$b);
imagesetpixel($output,$x,$y,$col);
}
}
header("Content-Type: image/png");
imagepng($output);
?>
Nothing overly complicated really. Of course, it'd be possible to encode a different message per colour channel, or even 8 different messages per channel for a total of 24 message.. feel free to play with this code.