Stegasaurus is a steganography tool for embedding an encrypted message payload into an image. It uses Syndrome-Trellis Codes and a local variance cost function to hide the message in areas with complex texture. Additionally, a randomized Huffman encoding is applied to allow signature free embedding: Stegasaurus uses no fixed markers or header elements. Stegasaurus is written entirely in Julia.
| Original | Embedded | Difference |
|---|---|---|
![]() |
![]() |
![]() |
| Empty | Contains Speech | Difference |
The "embedded" image above contains the full text of JFK's 1962 speech at Rice University. The speech text is 12178 bytes and the uncompressed image size is roughly 936 kbytes. The payload consumes roughly 10.2% of the available capacity, and required modifying approximately 3.8% of the image bytes, achieving nearly 2.7 message bits per byte modification. The difference image highlights the pixels where information is hidden, clearly demonstrating how the syndrome-trellis codes and inverse variance cost function hide data in the most textured regions of the image. To recover the speech, run the extraction command:
$ julia --project=. src/stegasaurus.jl extract assets/moon-embedded.png
Password: stegasaurusStegasaurus is composed of the following algorithmic components:
Stegasaurus uses Syndrome-Trellis Codes to find a minimum cost embedding of the message payload. While not currently adaptive, generator polynomials are configurable at the source level.
The cost function used is the inverse local variance of the 5x5 pixel block centered on each pixel. The goal is to favor pixels in areas of high variation.
Prior to embedding, the pixels are reordered via a Fisher-Yates shuffle using a cryptographically secure PRNG (AES-256-CTR). This spatially distributes the pixels providing increased opportunity for the STC process while simultaneously adding a layer of randomization to the encoding.
AES-256-CBC encryption is applied to the payload prior to encoding.
A randomized Huffman encoding is generated with 257 symbols. The 257th symbol is used as an end-of-message marker to recognize message termination during decoding. This allows the message to be embedded with no fixed place markers for length, starting position, or ending position. The randomization is achieved using a cryptographically secure PRNG (AES-256-CTR). Importantly, Huffman encoding is not being used for compression purposes; its sole purpose is to allow a signature free embedding.
Stegasaurus uses LSB-Matching (
The current implementation derives a salt value from the password itself; this means that the same Huffman encoding and permutation will be repeated if the same password is used multiple times. It is strongly suggested to use a unique password for each embedding.
Stegasaurus was written using Julia 1.12.6. Clone the repository and instantiate the environment to download the required cryptographic and image processing dependencies.
git clone https://github.com/tgaloppo/stegasaurus.git
cd stegasaurus
julia --project=. -e 'using Pkg; Pkg.instantiate()'To embed the message "Hello World!" into the image "test.jpg" resulting in the image "hello.png":
julia --project=. src/stegasaurus.jl embed -m "Hello World!" test.jpg hello.pngTo embed the file "secret_recipe.txt" into the image "test.jpg" resulting in the image "recipe.png":
julia --project=. src/stegasaurus.jl embed -f secret_recipe.txt test.jpg recipe.pngIMPORTANT: You MUST use an output image format with LOSSLESS compression. Using a non-lossless compression will corrupt the embedding.
To extract the embedded payload from file "secret.png" into file "output.txt":
julia --project=. src/stegasaurus.jl extract secret.png output.txtDuring extraction only, if no output file is specified, the output will be printed to stdout. If no message is found, or if the password is incorrect, the tool will simply report no message found.


