Skip to main content

Embed and extract files hidden inside PNG images using N-bit LSB steganography.

Project description

LSB Tool

Embed files inside a PNG image or extract previously hidden files using N-bit LSB steganography secured by a password.

Files are scattered across pixels in a password-derived pseudo-random order so the hidden data is not readable by standard steganalysis tools that scan sequential pixel runs.


Features

All image modes 1-bit, 8-bit grayscale/palette, 16-bit grayscale, RGB, RGBA
N-bit embedding Store 1–N bits per channel (N limited by channel bit-depth)
Multiple files Embed any number of files in a single carrier image
Filename storage Optionally preserve original filenames on extraction
Error codes Every failure exits with a distinct code — see ERRORS.md

Requirements

  • Python 3.8+
  • Pillow ≥ 8.0
  • NumPy ≥ 1.20
pip install -r requirements.txt

Usage

Embed

python main.py -E -i carrier.png -p password -f file1.txt file2.bin

Options:

Flag Description
-i Carrier image (any PIL-supported format; output is always PNG)
-p Password used to derive the pixel-shuffle seed and verification hash
-f One or more files to embed
-l Bits per channel to use — embedding depth (default 1, max depends on image type)
-n Filename field length in bytes 0–255 (default 0 = filenames not stored)
-v Print capacity and hash diagnostics after the operation

Output: <original_name>_embedded.png in the current directory.

Extract

python main.py -e -i carrier_embedded.png -p password

Extracted files are written to the current directory. If -n was used during embedding, the original filenames are restored; otherwise files are named extracted_file_0, extracted_file_1, …


Embedding depth (-l)

Higher depth stores more bits per channel, multiplying capacity roughly proportionally, but making changes more visible to the human eye.

Image type Max depth Capacity formula (bytes)
1-bit (1) 1 (pixels − 5) × 1 / 8
8-bit (L, LA, RGB, RGBA, P) 8 (pixels − preamble) × channels × depth / 8
16-bit grayscale (I;16) 16 same formula

If you request a depth greater than the image supports, the tool warns and clamps to the maximum automatically.


Examples

# Embed two files at depth 1 (default)
python main.py -E -i photo.png -p hunter2 -f report.pdf archive.zip

# Extract (restores original files)
python main.py -e -i photo_embedded.png -p hunter2

# Embed with filename storage and depth 4
python main.py -E -i photo.png -p hunter2 -f secret.txt -l 4 -n 32

# Extract — file is written as "secret.txt" instead of "extracted_file_0"
python main.py -e -i photo_embedded.png -p hunter2

# Check capacity (verbose)
python main.py -E -i photo.png -p hunter2 -f data.bin -v

Image format note

Always use PNG for the carrier image. Lossy formats (JPEG, WebP) alter pixel values after saving and will destroy the hidden data. The tool always saves output as PNG regardless of the input format.


Running tests

pip install pytest
pytest tests/ -v

Error codes

All errors exit with a specific code and print [Exx] … to stderr. See ERRORS.md for the full reference.

Code Meaning
E02 No mode selected (-E or -e required)
E03 Carrier image not found
E04 A file to embed was not found
E05 Files too large for this image at the chosen depth
E06 Wrong password or no embedded data
E07 Image file is corrupt or unsupported
E08 Cannot write an output file
E10 Internal error (bug)

How it works

  1. Key derivation — The password and image dimensions are hashed (SHA-256, iterated width × height times) to produce a 64-character hex digest.
  2. Pixel shuffle — A NumPy PCG64 RNG seeded from the digest shuffles all pixel coordinates into a pseudo-random order.
  3. Preamble — The first ⌈13/channels⌉ shuffled pixels store a 13-bit header at LSB-only depth: 5 bits for the embedding depth, 8 bits for the filename-field length.
  4. Main data — Remaining shuffled pixels carry the payload at the chosen depth using the formula bit k → pixel = k ÷ (channels × depth), channel = (k ÷ depth) mod channels, bit_pos = k mod depth.
  5. Verification — The first 512 bits of the main region store the password-derived SHA-256 hash as ASCII. Extraction fails with E06 if it does not match.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lsb_tool-2.0.0-py3-none-any.whl (14.9 kB view details)

Uploaded Python 3

File details

Details for the file lsb_tool-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: lsb_tool-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 14.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for lsb_tool-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d949144bc7554d6f9d72fb911d8581d3c27a3d1c2d2e9c308f45bce851c87ffc
MD5 34af09e15d6608a992821da65a05b9e0
BLAKE2b-256 e61ac024fe94fecfc994a54f74a7b3d27bfb890b6f983fd4ed41d36c1fe17d25

See more details on using hashes here.

Provenance

The following attestation bundles were made for lsb_tool-2.0.0-py3-none-any.whl:

Publisher: publish.yml on Rkoed97/LSB-tool

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page