Hiding Data Inside an Image With Python

Least Significant Bit steganography with randomly chosen pixels

I frequently find myself playing with code and most of the time it happens that I rewrite things from scratch, to write them better. In this case, the same thing happened for the Python tool I show you today.

This post assumes a basic knowledge of Python, steganography and the Least Significant Bit technique. If you don’t know anything about steganography, go check it out on Wikipedia.

What is different here?

LSB methods are extremely easy to implement and capable of hiding large quantities of information, but they also have a few drawbacks.

Apart from being vulnerable to changes resulting from lossy compression or image processing, LSB methods are also vulnerable to steganalysis. To level up confidentiality, there are two main methods:

  1. Encryption of the message: you need a key to understand the message
  2. Bits placement randomization: you need to know the seed used by a pseudo-random number generator algorithm to rebuild the message

I’m going to use the second approach.

All the code is available at this link. I show you the most important parts of the code.

1. Hide data

Photo by Author

To hide data inside our image, we need 4 arguments:

  1. A seed, used for the pseudo-random number generator. This is extremely important and must be known both from the sender and the receiver.
  2. input_data, contains the text that we want to hide
  3. output_file is just the name of the image that we are going to create
  4. A carrier, which is basically the container used to hide our text

From line 3 to 5, we open the image using PIL.

Then, at line 6 we initialize the PRNG.

At line 7, we create a set to keep track of the pixels used to hide data. We need it to avoid choosing the same pixel multiple times.

The code below, is responsible for the hiding process.

Snippet taken from main.py with a focus on LSB hiding function

At line 1, we randomly choose a pixel that will contain the next 3 bits of data.

Then, we get the Least Significant Bit of every color integer (lines 5–12) and we use bit manipulation (lines 14–18) in order to modify it accordingly to the bit we want to hide. Finally, we save the modified pixel (line 19).

2. Retrieve hidden data

To retrieve hidden text inside an image, we essentially need 2 things:

  1. The seed used to initialize the PRNG while encoding
  2. input_file, an image file

The core part of the retrieving process is the one below:

Snippet taken from main.py with a focus on LSB retrieving function

Until the retrieving process is not finished, we get the LSB from every pixel (line 8) and we convert every byte found to ASCII (remember: the right seed is necessary for the PRNG to rebuild the hidden message!).

If the last characters decoded are the ones used as End of File markers, it means that the hidden message is completly recovered (lines 18–19).

Final notes

This code is written for fun and learning purposes, so don’t use it for sensitive activities because it can have bugs and security holes. Use it responsibly.

This is my first post on Medium: if you notice that something is wrong/incorrect, please contact me and I will modify it as soon as possible.

The full code used in this post is available here, if you want to give it a try.

Thank you for your time 😉!

I almost forgot: I used Python 3.6 for this project

I’m a Computer Science student, with a passion for questioning things. In the last years, I embraced this motto: No excuses, we can always do better