Nodes/ComfyUI EncryptMaster/EncryptMaster — Stego Embed Image (LSB/AES-GCM)
ComfyUI Node

EncryptMaster — Stego Embed Image (LSB/AES-GCM)

Hide one image inside another — compressed, encrypted, and invisible

By orion4d·Created 12 months ago·Updated 12 months ago· 5
EncryptMaster — Stego Embed Image (LSB/AES-GCM)
  • cover_image
  • secret_image
  • image
  • report
passphrase
bits_per_channel1
secret_encodepng
jpeg_quality85
associated_data
resize_secret_to_covertrue

Stego Embed Image is the heavyweight sibling of Stego Embed Text: instead of a message, it hides an entire image inside another image. The cover looks completely normal, the secret image is compressed, encrypted, and buried in the least-significant bits, and only Stego Extract Image plus your passphrase can pull it back out.

This is the node for "look at this innocent photo" moments - embedding a watermark, a preview, a secret version of a render inside a public one, or just smuggling a picture through a channel where an obvious image file would raise questions. It's the closest thing in the pack to the classic "image-in-image" steganography you've seen in spy-movie explainers, except the hidden image is also AES-256-GCM encrypted, so even extracting it reveals nothing without the passphrase.

How it works

The secret image is handled smarter than a naive LSB implementation. It's compressed first - that's the trick that makes whole-image stego feasible - then encrypted, then embedded:

  1. The secret is encoded as PNG (lossless) or JPEG (jpeg_quality, default 85). Compression shrinks it dramatically: a 1216×1600 secret at JPEG q85 is roughly 200–400 KB versus megabytes of raw pixels.
  2. The compressed bytes are encrypted with AES-256-GCM (scrypt key derivation), prefixed with a 50-byte header storing the secret's dimensions and encoding type, and flattened to bits.
  3. Those bits overwrite the cover's least-significant bits at bits_per_channel (1 or 2).

With resize_secret_to_cover on (default), the secret is scaled to the cover's dimensions first - which is almost always what you want, since a same-size secret gives the embedder its best fit.

Inputs and outputs that matter

  • cover_image (IMAGE) - the innocent carrier.
  • secret_image (IMAGE) - the image to hide.
  • passphrase (STRING, masked) - required; exact match at extraction.
  • bits_per_channel - 1 or 2. For whole images, you'll usually want 2.
  • secret_encode - png (lossless, bigger) or jpeg (much smaller, slight quality loss). Default is png, but jpeg is the practical choice for hiding whole images - the README calls it "recommended."
  • jpeg_quality (INT, 50–95, default 85) - quality of the JPEG-encoded secret.
  • associated_data (STRING, optional) - authenticated tag; must match at extraction.

Outputs are image (the carrier with the secret inside) and a report (STRING) telling you what was embedded and at what bit depth.

Capacity - the thing to actually care about

LSB capacity is width × height × 3 × bits_per_channel bits, and ciphertext is incompressible, so the budget is real. The README's numbers, from experience: a 1216×1600 cover at 1 bpc holds ~712 KB; at 2 bpc ~1.42 MB. A JPEG q85 version of that same-size secret lands around 200–400 KB, which fits comfortably at 2 bpc. Lossless PNG of a full image usually will not fit at 1 bpc - that's the classic first-time failure.

Good news: unlike the text embedder, this node tells you when it fails. If the payload is too big it returns the unmodified cover with a clear [StegoImage ERROR] Capacity too small... message in the report, with tips (use jpeg, bigger cover, or 2 bpc).

Installing it

Part of the ComfyUI EncryptMaster pack. Try ComfyUI Manager (search "ComfyUI EncryptMaster"), or:

cd ComfyUI/custom_nodes
git clone https://github.com/orion4d/Comfyui_EncryptMaster

Then the real dependencies (no requirements.txt in the repo - this is the list that installs):

pip install cryptography pillow numpy

Restart ComfyUI. No models, no GPU.

The rules that never change

Save the output as PNG or TIFF - JPEG recompression destroys the embedded bits. And remember that "looks invisible" is the point, not a side effect: at 2 bpc, flat gradient areas of the cover can show faint banding if you zoom in. If the cover needs to look perfect under scrutiny, 1 bpc is the safer bet and you pay for it with capacity. One light aside: this is the node you reach for when a whole secret image beats a text note - for short messages, the text stego pair is cheaper and simpler.

CategoryEncryptMaster

Inputs (8)

NameTypeDefaultDescription
cover_imageIMAGE
secret_imageIMAGE
passphraseSTRING
bits_per_channelCOMBO12 options: 1, 2
secret_encodeCOMBOpng2 options: png, jpeg
jpeg_qualityoptINT8550–95
associated_dataoptSTRING
resize_secret_to_coveroptBOOLEANtrue

Outputs (2)

NameTypeDescription
imageIMAGE
reportSTRING