3 minutes
Steganography - Hide data using the “Least Significant Bit” algorithm
First I looked online for an image to use for my carrier file. To break the chain of cats I chose a dog.bmp shown below. This file is 549 KBs and is large enough to carry an embedded file.
After this I found a file to embed into the dog.bmp. For this I chose the file below with the size of 1.48 KB.
Same as the previous post with recovery, I start off by reading in the two images as binary (“rb”) and hexlifying the content. Convert to binary and again fill in any missing zeros.
"""
Created on Tue Jun 25 14:29:28 2019
@author: Parth Patel
"""
import binascii
filename = 'dog.bmp'
file_embedded_name = 'embedded.jpg'
# read in dog.bmp file as the carrier and convert to hex
with open(filename, 'rb') as f_original:
content_original = f_original.read()
hex_str_original = binascii.hexlify(content_original)
# read in embedded.jpg as embedded and convert to hex
with open(file_embedded_name, 'rb') as f_embedded:
content_embedded = f_embedded.read()
hex_str_embedded = binascii.hexlify(content_embedded)
# convert to binary
bin_str_original = bin(int(hex_str_original, 16))[2:].zfill(8)
bin_str_embedded = bin(int(hex_str_embedded, 16))[2:].zfill(8)
# add missing leading 0
bin_str_original = '0000000' + bin_str_original
bin_str_embedded = '0000000' + bin_str_embedded
I decided to skip 54 bytes for the header information of the dog.bmp file. To account for this, I incremented my count by 432 bits (54*8 = 432) and added 7 to get to the last bit of the starting byte that will be used in LSB. This give me a count of 439 as a starting point. I loop though the embedded file (until that last bit is accounted for) and replace the least significant bit on the original dog.bmp. I converted the original string of binary to a list because python does not allow for edits on strings. Once the loop is completed, I joined the list of original plus modified bits together into a string.
# skip 54 bytes for header of bmp (convert to bits by multiply by 8) + 7 for the last bit
count = 439
i = 0
# loop through and replace the last bit of each byte of the original dog.bmp
# add the binary value for the embedded.jpg
List_bin_str_original = list(bin_str_original)
length_carrier = len(bin_str_embedded)
while i < len(bin_str_embedded):
List_bin_str_original[count] = bin_str_embedded[i]
count += 8
i += 1
# join the list of binary values with the embedded jpg file to create a string of binary values
bin_str_Infected = ''.join(List_bin_str_original)
print(len(bin_str_Infected))
Taking this modified/infected string of binary and changing back to hex (already a multiple of 8 so no modification necessary). Once again I remove the starting 2 non-hex values and strip away any spaces and new line characters and write to a new part2_EmbeddedFile.bmp (using wb) by unhelifying the hex string.
# multiple of 8 to convert to hex
LSB_hex_str = hex(int(bin_str_Infected, 2))
# remove the starting 2 non-hex values and strip away any spaces and new line values
print(len(LSB_hex_str))
filename_Output = 'part2_EmbeddedFile.bmp'
LSB_hex_str = LSB_hex_str[2:]
LSB_hex_str = LSB_hex_str.strip()
LSB_hex_str = LSB_hex_str.rstrip('\r\n')
# unhexlify and write new file back in binary with embedded hidden image
with open(filename_Output, "wb") as f_output:
f_output.write(binascii.unhexlify(LSB_hex_str))
This creates the new carrier file (part2_EmbeddedFile.bmp) that now contains the hidden embedded.jpg file as shown below.