Steganography is the art of hiding something in something else in plain sight. Usually images or text are hidden within other images or sound files. For example, in the image below of trees there is an image of a cat hidden inside it. Wikipedia explains that for each component of each RGB value, if you take just the last 2 bits of it and then turn the brightness up 85%, you get a picture of the cat. The whole point is so the image of the trees looks identical to an image of the trees without an image hidden inside to the human eye.
import sys import png def decode(line): """ Takes in a line of RGB values. Each value is replaced by the last two bits of the value multiplied by 85 """ new_line =  for p in line: p = p & 3 # 3 is 00000011 in binary p = 85 * p # scale p to be between 0 and 255 (255/3 = 85) new_line.append(p) return new_line def encode(line, hideLine): """ Takes in the same line of RGB values from the file to hide in (A) and the file to be hidden (B). Each value of B is turned into a number between 0 and 3 and then ORed with the first 6 bits of A. """ new_line =  for p, q in zip(line, hideLine): x = int(round(q / 85)) p = (p & 252) | x new_line.append(p) return new_line def hide_image(file, hiddenfile): """ Hides 'hiddenfile' within 'file' """ im = png.Reader(filename=file) width, height, pixels, meta = im.read() imHide = png.Reader(filename=hiddenfile) widthHide, heightHide, pixelsHide, metaHide = imHide.read() out_file = open('hidden.png', 'wb') # transform new_pixels = [encode(line, hideLine) \ for line, hideLine in zip(pixels, pixelsHide)] # output image writer = png.Writer(width=width, height=height, **meta) writer.write(out_file, new_pixels) def reveal_image(file): """ Reveals an image hidden within 'file' """ # input image im = png.Reader(filename=file) width, height, pixels, meta = im.read() out_file = open('recovered.png', 'wb') # transform new_pixels = [decode(line) for line in pixels] # output image writer = png.Writer(width=width, height=height, **meta) writer.write(out_file, new_pixels) def main(): try: if sys.argv == "encode": try: hide_image(sys.argv, sys.argv) except IndexError: print "Please supply two PNG files. The first is \ the file the image will be hidden in, the second \ is the image to hide." elif sys.argv == "decode": try: reveal_image(sys.argv) except IndexError: print "Please supply a PNG with a hidden image." else: print "invalid argument. Please use 'encode' or 'decode'" except IndexError: print "Please type 'encode' or 'decode' after the python \ file followed by two PNG files for encode, and one for decode." if __name__ == "__main__": main()
To reveal an image, just type:
python steg.py decode file-with-hidden-image.png
To hide an image, type:
python steg.py encode file-to-hide-data-in.png file-to-be-hidden.png
Decoding will output an image called recovered.png and encoding will output an image called hidden.png. To encode, you’ll need to use two PNGs of exactly the same height and width, and it only works really well if the image to be hidden has a low resolution with high contrasting colours. Black text on white/transparent works perfectly.
Can you decode the message I’ve hidden in the image below?