Skip to main content

Module shadow_layer

Module shadow_layer 

Source
Expand description

Media-agnostic shadow-layer primitives.

Shadow messages provide plausible deniability: multiple messages can be hidden in a single cover (image, video, …), each with a different passphrase. The frame format, parity tier ladder, RS encoding shape, and capacity arithmetic are the same regardless of medium. Per-medium specifics (which positions to embed at, how to write into them, how to walk the cover at decode time) live in the medium-specific modules:

  • Image (Y-channel JPEG nzAC, cost-pool + hash priority): core/src/stego/ghost/shadow.rs
  • Video H.264 (4 bypass-bin domains, hash priority + additive bias for N>1): core/src/codec/h264/stego/shadow.rs

§Frame formats (no header, fdl recovered via first-block peek)

Two variants exist, distinguished by the width of the plaintext-length prefix:

Standard (image)SHADOW_FRAME_OVERHEAD = 46 bytes:

[plaintext_len: 2B u16 BE] [salt: 16B] [nonce: 12B] [ciphertext: N+16B]

Used by image stego (core/src/stego/ghost/shadow.rs). Hard cap: 65,535-byte plaintext per shadow. Adequate for image covers (Y-channel JPEG nzAC capacity ≈ tens of KB).

Wide (video)SHADOW_FRAME_OVERHEAD_WIDE = 48 bytes:

[plaintext_len: 4B u32 BE] [salt: 16B] [nonce: 12B] [ciphertext: N+16B]

Used by H.264 video stego (core/src/codec/h264/stego/shadow.rs). Hard cap: 4,294,967,295-byte plaintext per shadow. Required because video covers can support much larger payloads (file attachments, multi-MB shadows). The two formats are wire- incompatible by design — image stego has been released and the u16 layout is locked; video stego is pre-release and uses the wider layout natively.

No magic byte; AES-256-GCM-SIV authentication is the only validator. Decoders brute-force (parity, fdl) combinations using a first-block-peek heuristic to derive fdl from the plaintext-length prefix once the first 255-byte RS block decodes.

Structs§

ParsedShadowFrame
Parsed shadow frame — output of parse_shadow_frame.
ParsedShadowFrameWide
Parsed wide shadow frame — output of parse_shadow_frame_wide.
ShadowLayer
One shadow layer’s input — message + passphrase + optional file attachments. The encoder takes a slice of these (size-descending for primary-vs-shadow ordering by message size).

Constants§

MAX_SHADOW_FRAME_BYTES
Maximum RS-encoded frame bytes for the standard (image) format — guards against unreasonable allocations during decode brute-force. Implies plaintext ≤ ~256 KB before RS expansion; in practice u16 caps it at 65,535 bytes.
MAX_SHADOW_FRAME_BYTES_WIDE
Maximum RS-encoded frame bytes for the wide (video) format. Bumped to 16 MB to accommodate plausible large attachments (e.g., embedded photos as shadows in long videos). Decoder brute-force scan is bounded; this is the safety upper bound.
SHADOW_FRAME_OVERHEAD
Standard (image) frame overhead inside the RS-encoded payload: plaintext_len(2) + salt(16) + nonce(12) + tag(16) = 46 bytes. Used by image stego (stego::ghost::shadow); locked at u16 to preserve compatibility with released app versions.
SHADOW_FRAME_OVERHEAD_WIDE
Wide (video) frame overhead — same fields but with a u32 plaintext-length prefix: plaintext_len(4) + salt(16) + nonce(12) + tag(16) = 48 bytes. Used by H.264 video stego — covers can support multi-MB shadows (file attachments) so the u16 cap is too tight.
SHADOW_PARITY_TIERS
RS parity tiers. Brute-forced at decode.

Functions§

build_shadow_frame
Build the shadow inner frame (before RS encoding).
build_shadow_frame_wide
Build the wide shadow inner frame (u32 plaintext_len) — see module docs for layout. Used by video stego.
compute_max_shadow_fdl
Compute the maximum frame_data_len (bytes before RS encoding) that fits in max_rs_bytes of available LSB capacity at the given parity length.
parse_shadow_frame
Parse a shadow inner frame (after RS decoding).
parse_shadow_frame_wide
Parse a wide shadow inner frame (u32 plaintext_len). Used by video stego.