I am working on a simple steganography project that should allow to encrypt text inside the LSB of images pixels, i am using python and the PIL image module, it seems that i can correctly modify the LSB but when i open the output image the first 8 LSBs don't match the first letter of the text
First i convert the text to a binary string and terminate it with a byte of zeros
def text_to_binary(text): # Convert input text into binary binary_text = ''.join(format(ord(char), '08b') for char in text) # Terminator sequence used later in decryption binary_text = binary_text +"00000000" return binary_textthen i encrypt the text like this:
def encryptLSB(text, image, output_path): image = Image.open(image) binary_text = text_to_binary(text) width, height = image.size if len(binary_text) > width * height: raise ValueError('Text too long to be encrypted in this image, provide a larger image') # The index of the data bit currently being processed index = 0 data_done = False for y in range(height): for x in range(width): if not data_done: pixel = list(image.getpixel((x, y))) current_data_bit = int(binary_text[index], base=2) # Distributing the data in all three RGB values allows less noticeable changes in the final image # we need to access the LSB of each of those channels and replace it with our data for channel in range(3): # Set the LSB to the value of the current binary data pixel[channel] = (pixel[channel] & ~1) | current_data_bit # Update the pixel image.putpixel((x, y), tuple(pixel)) # Pass to the next data bit index += 1 # if done with the text, set flag to true and exit if index == len(binary_text): data_done = True # Save the image image.save(output_path)To check if the encryption is succesful i try to read the first 8 LSB and see if they match the first character of the text
def readLSB(image): image = Image.open(image) # width, height = image.size byte = "" for x in range(8): pixel = list(image.getpixel((x, 0))) # The lsb is extracted and appended to the byte string byte += str(pixel[0] & 1) print(byte)for example in the case of
text = "string"encryptLSB(text, "img.jpg", "out.jpg")readLSB("out.jpg")>>00010000but it should be 01110011 as that's the s char binary rapresentation
What am i missing? has the jpg compression got something to do with this or is my code just wrong? should i save it in other ways? Thanks!