This project implements a command line utility that can be used to embed an image within another. The method used here is known as least significant bit steganography specifically using the lowest 4-bits of each color channel to embed hidden information in a container image. Be wary, this method is susceptible to noise detection techniques and so is not a particularly effective method if one's goal is to go undetected!
Below is a capture showing merged and unmerged images. On the left is the result of merging a container image with a secret image. On the right, we have the unmerged image. There's some obvious loss in quality, but the extracted image is still recognizable.
To build the project locally, you will need the following libraries and tools installed:
- CMake3.13+
- C++ compiler supporting C++20 features
- libpng developer libraries
- libjpeg developer libraries
- Boost version 1.76.0+
To build the project, change directory to the scripts/
directory and run
build.sh
(optionally pass the -g
flag to build with debug symbols):
./build.sh
After a successful build, you will find the binary installed to
steganography/bin/steganography
.
The project includes a Dockerfile that builds an image with the
steganography
tool installed. To build the image, run the following command
from the project root directory:
docker build . -t steganography:latest
Included in the scripts/
directory is the container.sh
script which launches
the steganography container with a host volume mounted. The host volume can
contain images to be run against the tool. Just edit the STEG_IMAGES
variable
to the absolute path of the directory containing your images, then navigate to
/mnt/images
within the container shell and run the tool as explained in the
Program Usage section.
The steganography
tool interprets three commands: help
, merge
, and
unmerge
.
The help
command prints program usage info:
steganography help
The merge
command takes three arguments where the first is the container
image, the second is the secret image, and the final is the desired name for the
merged image:
steganography merge container.jpg secret.jpg merged.png
Note The output image is ALWAYS in the PNG format. The reason is that the JPEG format uses lossy compression meaning we cannot reliably unmerge a merged image written as a JPEG.
The unmerge
command takes two arguments where the first argument is an image
previously constructed using the merge
command and the second argument is the
desired name for the unmerged image:
steganography unmerge merged.png unmerged.jpg
Only JPEG and PNG formats are supported as output formats.