# Steganography with Python

Steganography is a common word for the art of hiding information. The etymology of steganography is the greek word steganos (στεγανός), and graphein (γράφειν). Combined, they are (freely) translated as concealed writing. From a technical perspective, data can easily be embedded in the color information of an image; altering the least significant bit (LSB) of the color values in a pixel is not noticeable by the human eye, since the resulting color is very close to the original one. As an example, consider the 8 bit word: By changing the last bit of 0xB4, the resulting value, 0xB5, is only a fraction 1/255 larger. We can use this bit to store data, say a string of characters, in, say, a PNG-file.  Of course any type of image can be used as a storage, assuming that it has a high color information. This to ensure that the difference between the two images are miniscule.

The following piece of Python code embeds data in the LSB in each RGB value of each pixel of an image. Due to a somewhat inefficient implementation of Python’s functions handling image data, it is a bit slow.

```#
#  Steganographic software to hide data in
#  lsbs of an image.
#
#  Copyleft Carl L\&quot;ondahl
#  grocid.net
#

import Image, operator

def convert_to_bits(string):
bitstring = []
for char in string:
bits = bin(ord(char))[2:]
bits = '00000000'[len(bits):] + bits
bitstring.extend([tuple([0xff&amp;int(bit) for bit in bits[0:4]]), \
tuple([0xff&amp;int(bit) for bit in bits[4:8]])])
return bitstring

def convert_to_byte(tuples, length):
chars = []
for b in range(length):
byte = [0x1x for x in tuples[2*b]]+[0x1&amp;x for x in tuples[2*b+1]]
chars.append(chr(int(''.join([str(bit) for bit in byte]), 2)))
return ''.join(chars)

def save_data(string):
im = Image.open('original.png')
data = im.getdata()
im.putdata([tuple(map(operator.and_,bitstring[y],data[y])) \
for y in xrange(len(bitstring))])
im.show()
im.save('newimage.png')

# read n bytes of data from image
def open_data(n):
im = Image.open('newimage.png')
data = im.getdata()
print convert_to_byte(data, n).decode('ascii','ignore')

string = 'Receive and transmit the letters of the Rasqiniaans'
bitstring = convert_to_bits(string)

# save data
save_data(bitstring)

#open data
open_data(200)
```