StegoToolkit

Steghide Online

Hide text or files inside a JPEG, WAV, AU, or BMP using a client-side reimplementation of the steghide algorithm — graph-theoretic minimum-distortion matching, AES-256-CBC encryption, and the same passphrase-seeded position selection real steghide uses. In our tests on synthetic covers, files it makes extract correctly with steghide 0.6.0, and vice versa (every cipher on JPEG, a subset on WAV, AU and BMP). Processed in your browser, not uploaded.

steghide-compatible
AES-256-CBC
JPEG
WAV
AU
BMP

Try the demo instantly

Loads a 400×400 gradient JPEG — no upload needed

Drop your JPEG, WAV, AU, or BMP here or click to browse

.jpg / .jpeg / .wav / .au / .bmp · Max 50 MB

Parsed locally in your browser — nothing uploaded

Processed in your browser — Steghide-Compatible

A from-scratch TypeScript implementation of steghide's graph-matching embedding for JPEG (DCT coefficients), WAV/AU (PCM/mu-law samples), and BMP (palette indices or 24-bit RGB pixels), verified against official crypto test vectors and cross-checked against steghide 0.6.0 (files from either tool extract correctly in the other). Your file is processed in this tab and is not sent to a server; usage statistics may record which options were used, never your file or passphrase.

How to Embed Data in a JPEG, WAV, AU, or BMP with Steghide Online (4 steps)

  1. Upload a JPEG (.jpg/.jpeg), WAV (.wav), AU (.au/.snd), or BMP (.bmp, 1/4/8-bit palette or 24-bit RGB) cover file — the graph-matching algorithm embeds into DCT coefficients (JPEG), PCM/mu-law samples (WAV/AU), or palette indices / RGB pixel values (BMP).
  2. Type your secret message or upload a file to hide. Check the capacity estimate — capacity depends on carrier complexity/length, not just file size.
  3. Enter a passphrase (optional — even a blank one is used for position selection). In Standard/Forensic mode, choose compression, checksum, and encryption.
  4. Click 'Embed & Download' — embedding runs entirely in your browser via a from-scratch TypeScript port of steghide's own graph-matching algorithm. Only a small number of carrier samples are adjusted, so the result is intended to look or sound the same as the original (not measured here).

Steghide Algorithm — Overview

MethodTechniqueDetectabilityBest For
Steghide graph-matching (DCT/PCM)Groups carrier samples into vertices, finds a minimum-distortion matching so most vertices need only a 1-value 2-for-1 swap instead of an independent changeChanges few values: JPEG coefficients by at most 1, 16-bit WAV/AU samples by up to 20 (steghide's own radius; measured 19, the same as real steghide), 24-bit BMP pixels by a squared colour distance of at most 100; detection rates against steganalysis tools have not been measured hereCTF challenges expecting real steghide output, covert JPEG/WAV/AU/BMP payloads that must survive casual inspection

What this tool is, and what it is not

steghide is a command-line program that hides data in JPEG, BMP, WAV and AU files. This page is a from-scratch reimplementation of its algorithm in TypeScript that runs in your browser. It is not the original program compiled to WebAssembly, so the stego bytes it writes are not identical to what steghide would write for the same input (steghide itself gives different bytes on every run: with encryption off, three runs with identical inputs gave three different files).

What was tested: files made here were extracted with a real steghide 0.6.0 build, and files made by that build were extracted here, in the default test run with every cipher on JPEG and a subset of 11 ciphers on WAV, AU and BMP, using synthetic covers. The comparison is whether the other program recovers the exact payload, not whether the bytes match.

Capacity depends on the picture or sound, not on the file size

A JPEG hides data in the DCT coefficients that are not zero, so a smooth image has little room and a detailed one has more. Two synthetic 320 × 240 JPEGs made with the same encoder settings held 231 bytes (smooth) and about 1,750 bytes (noisy). WAV and AU files hold data in their samples, and BMP files in palette indices or pixel colours, so their capacity follows their length or size more directly.

The capacity figure is shown before you embed. Compression can shrink the payload or, on data that does not compress, make it slightly larger; encryption and steghide's payload framing (header, checksum, file name, cipher padding and IV) always add bytes. The bar already counts that framing and assumes compressed data does not shrink, so a payload at the displayed figure is accepted.

The passphrase always matters

In steghide the passphrase decides which positions in the file carry the data. That happens even when encryption is off, so a file made with a blank passphrase is still read only with a blank passphrase, and a file made with "blue" is not read with "Blue". Encryption is a separate option: with it on, the same passphrase also derives the key for AES-256-CBC (steghide's default, Rijndael-128 with a 256-bit key) or one of 21 other ciphers.

A short or common passphrase can be guessed by anyone with the file. The data is also not hidden from someone who knows steghide was used: this tool does not claim the file is undetectable.

If the file is changed afterwards

The data lives in the exact values of the coefficients, samples or pixels. A program that re-encodes the file (re-saving a JPEG, converting audio, resizing an image) rewrites those values and the data may be lost. We did not measure what any particular program or website does to an uploaded file, so test your own route by extracting from the copy you receive.

Examples

Input: Hide the text "Meet at 9" in a WAV file with the passphrase blue, then extract with blue, with Blue and with an empty passphrase.

Result: With blue the text comes back (Meet at 9). With Blue and with an empty passphrase the extractor reports that no data could be extracted with that passphrase.

Meaning: The passphrase is case sensitive and selects the positions, so a different one reads different samples and finds nothing.

Input: Embed a short message (about 40 bytes) in a one-second 16-bit mono WAV, then compare every sample with the original.

Result: A few hundred samples change, none by more than 19 (the limit steghide uses for 16-bit audio is 20). Real steghide gave the same maximum of 19 on the same file.

Meaning: Changes are small, but 16-bit audio is not limited to plus or minus 1. JPEG coefficients did stay within 1 in all 6 files we checked.

How the Steghide Hider Works

Read the carrier

The file is parsed into the values steghide can change: DCT coefficients for JPEG, PCM or mu-law samples for WAV and AU, palette indices or RGB pixels for BMP.

Build the payload stream

A magic number, the encryption settings, a compression flag, an optional CRC32, the file name and the data are written as one bit stream. Compression is zlib, encryption is optional.

Choose positions from the passphrase

The passphrase seeds a pseudorandom permutation of the carrier's values, so the bits of the stream go to scattered positions that only the same passphrase reproduces.

Match and write

A graph-matching step groups values so that as few of them as possible have to change, then the file is written back. WAV, AU and BMP keep their size; a JPEG is re-encoded and its size changes.

What the results mean

ResultWhat it meansWhat to do
The capacity bar is redAfter compression and encryption the payload does not fit this carrier.Use a larger or more detailed cover, shorten the payload, or switch compression on.
The JPEG came out a different sizeJPEG covers are re-encoded when the data is written, so the byte size changes.Normal. WAV, AU and BMP covers keep exactly the same size.
The upload was refusedThe file is not a supported carrier, or it is damaged (16-bit, 32-bit and compressed BMPs are refused, as real steghide refuses them).Convert it to a JPEG, WAV, AU or a 1, 4, 8 or 24-bit BMP.

Limitations

  • Only JPEG, WAV, AU and uncompressed BMP (1, 4, 8 or 24-bit) are accepted. The upload limit is 50 MB (15 MB on phones).
  • The stego bytes differ from real steghide's output; interoperability was tested on synthetic covers, not on every kind of real file.
  • Detectability was not measured here: no steganalysis tool was run against the output.
  • Survival after re-saving, converting or uploading to a website was not measured.
  • The CRC32 is an integrity check, not a signature; the encryption protects the content only as well as the passphrase does.

Privacy

The cover file, the payload and the passphrase are processed in this browser tab and are not sent to our server. Usage statistics may record which options were used (never the file, the payload or the passphrase), and our host keeps ordinary request logs.

Which Tool Next?

Frequently Asked Questions

Is this actually compatible with the real steghide CLI?

This is a from-scratch TypeScript reimplementation of steghide's algorithm. The wire format, key derivation, AES-256-CBC encryption and passphrase-seeded position selection follow steghide exactly (verified against official cryptographic test vectors for MD5, FIPS-197 AES-256 and CRC-32). The graph-matching embedder follows steghide's strategy but is not a bit-for-bit copy of its C++ heuristics, so the exact stego bytes differ from what steghide would produce (steghide itself gives different output on every run). It is cross-checked against a real compiled steghide 0.6.0 binary on synthetic cover files: for JPEG, WAV, AU, and BMP (1/4/8-bit palette and 24-bit RGB), files this tool produces extract correctly with real steghide, and files real steghide produces extract correctly here. The default run tries every cipher on JPEG and a subset of 11 on the other formats; the stego bytes themselves are not compared, only whether the other program recovers the exact payload.

Which carrier formats are supported? What about 24-bit BMP?

JPEG (DCT-coefficient), WAV, AU (PCM-sample), and BMP (1-bit/4-bit/8-bit palette and 24-bit RGB) graph-matching are all implemented, sharing the same Selector/passphrase/EmbData wire format underneath. 24-bit BMPs use real steghide's RGB mode: each pixel carries 2 embedded bits derived from the LSBs of its R, G, and B values, and the matching engine searches a small 3D color-space neighbourhood (squared distance up to 100) for the least-visible pixel swaps. Other bit depths (16/32-bit) and compressed BMPs are rejected with a clear error, exactly as real steghide does.

Which encryption algorithms can I choose when embedding?

Real steghide's default cipher — Rijndael-128/CBC — is literally standard AES-256-CBC (a 128-bit block, 256-bit key Rijndael configuration IS AES-256 by definition). In Forensic mode, the Cipher dropdown also lets you pick DES, Triple-DES, Blowfish, RC2, CAST-128, Twofish, Serpent, XTEA, SAFER SK-64, SAFER SK-128, SAFER+, CAST-256, 3-WAY, GOST, Rijndael-192, Rijndael-256, LOKI97, Enigma, ARCFOUR (RC4), WAKE, or PANAMA — all 22 are real steghide's own algorithms, and a file made with any of them decodes correctly with the real steghide CLI's own -e flag too. Enigma, ARCFOUR, WAKE, and PANAMA are genuinely different stream ciphers under the hood (no CBC) rather than block ciphers, though they work the same way from this tool's own UI. All 22 of real steghide's non-NONE algorithms are implemented.

Does the passphrase always matter, even without encryption?

Yes — unlike most steganography tools' password fields, steghide's passphrase seeds BOTH the embedding-position selection (which samples carry data) AND, if enabled, the AES-256-CBC encryption key. Even an empty passphrase produces a specific, deterministic position order — the extractor needs the exact same passphrase either way.

Does the file size change after embedding?

For WAV, AU, and BMP covers the file size stays exactly the same: steghide doesn't append or resize anything, it only adjusts the values of existing samples or pixels. JPEG covers are re-encoded, so the file size can change. On the three real camera photos we tried (0.7 to 0.8 MB each) the file grew by about 0.1% with a payload at 10% of capacity and by about 0.5% at 50%; other JPEGs can differ. Real steghide also re-encodes the file: with a 500-byte payload its output was 0.4% and 2.7% smaller on two of those photos. In every format the dimensions or duration are unchanged. How far a changed value moves depends on the format: a JPEG DCT coefficient by at most 1 (checked on 6 files, 5 of them real camera JPEGs), an 8-bit WAV sample by at most 1, a 16-bit WAV or AU sample by up to 20 (we measured 19, and real steghide gave the same on the same file), and a 24-bit BMP pixel is replaced by a colour within a squared distance of 100 (measured at most 100).

Can I password-protect a WAV or AU audio file, not just a JPEG?

Yes — the passphrase and AES-256-CBC encryption work identically across every supported carrier (JPEG, WAV, AU, and BMP 1/4/8/24-bit). The graph-matching embedder just swaps a different kind of sample per format (DCT coefficients for JPEG, PCM/mu-law samples for WAV/AU, palette indices or RGB pixel values for BMP) — the passphrase-seeded position selection and encryption layer on top are the same steghide algorithm either way.

Related Tools