Welcome to the first in a series of posts about Steganography. Something that I find both fascinating and oddly under-utilised. If you're reading this you likely have some idea of what it is, but just in case you don't, here's a brief description in the digital context.
Steganography is the practice of representing information within another message or physical object, in such a manner that the presence of the information is not evident to human inspection.
It's really that simple at a broad level. You take something you want to hide (target), another message/image (cover) and manipulate the cover material in such a way that the original is retrievable but not visible.
There are numerous applications for this such as monitoring assets as they pass through a system, tagging assets, sending encoded messages to people or even embedding metadata so that they aren't stripped out by automated processes.
There are multiple ways to achieve this but the main one and the one I'll focus on in this article is known as LSB (Least Significant Bit). This is where you take the pixel values of the cover image and alter the least significant bit to "store" data from your target image, one bit at a time. Here's a quick Python example to hide some text in an image:
from PIL import Image
def encode():
start = '#####'
stop = '*****'
full = start + 'Some string that you want to encode into an image' + stop
binary_text = ''.join('{0:08b}'.format(ord(x), 'b') for x in full)
print(binary_text, len(binary_text))
with Image.open("file.png") as im:
i = 0
w, h = im.size
for x in range(0, w):
for y in range(0, h):
if i >= len(binary_text):
i = 0
bit = binary_text[i]
pixel = im.getpixel((x, y))
if bit == "0":
# Is odd, should be even.
if pixel[0] % 2 != 0:
new_pix = (pixel[0] - 1, pixel[1], pixel[2])
im.putpixel((x, y), new_pix)
else:
# Is even, should be odd.
if pixel[0] % 2 == 0:
new_pix = (pixel[0] - 1, pixel[1], pixel[2])
im.putpixel((x, y), new_pix)
i += 1
im.save("file_enc.png")
With this, you translate some text into a string binary representation of the text, loop through every pixel and alter the Red value (which colour is mostly arbitrary, red just usually comes first when splitting out pixel data) to match the binary value. This will go through the entire image, loop through the binary text and encode it into the image. This might be overkill for you, but it gives the basic premise.
💡
Note the use of a start and stop string. This is important when encoding in a full loop since without it, you won't know where the actual string was encoded. This is also incredibly useful for robustness later on.
The decoding/retrieval part of this is simply the reverse. Get the pixel values, rebuild the binary string from the Red pixel value's LSB and then convert it back to a standard string.
def decode():
start = '#####'
stop = '*****'
binary_stop = ''.join('{0:08b}'.format(ord(x), 'b') for x in stop)
with Image.open("file_enc.png") as im:
w, h = im.size
binary_text = ''
for x in range(0, w):
for y in range(0, h):
pixel = im.getpixel((x, y))
if binary_text.endswith(binary_stop):
message = "".join([chr(int("".join(binary_text[i:i + 8]), 2)) for i in
range(0, len(binary_text) - 8, 8)])
start_point = message.find(start) + len(start)
end = message.find(stop)
message = message[start_point:end]
return message
if pixel[0] % 2 != 0:
binary_text += '1'
else:
binary_text += '0'
As I said, this is a very simple implementation though. It's done row by row, column by column in an image and repeats all over the image so is not very robust. It's also the most common form so not at all resistant to steganalysis.
That's all there is to it. Now, the above is not performant, it could be improved but it should provide a good base for starting to implement steganographic capabilities into your apps.
A full working example can be found on my Gitlab, here: https://gitlab.com/Vapourisation/steganography_python_example
Header image courtesy of Michael Maasen on Unsplash
Top comments (3)
Glad found someone with a good post about steganography. I just make one post with similar topic but focus on image instead. I would like to know your opinion on the way I approach it 😀
Exploring Steganography in the Wild - Part 1
Retiago Drago ・ Sep 12
A fellow steganography fan! It's so hard to find any good articles on it so I'm so happy other people are writing about it. It's so interesting and I really think it's going to be huge with the rise of AI.
I know right, it is such a fascinating field in the rise of AI and LLM as well