Skip to main content

Module shadow

Module shadow 

Source
Expand description

Shadow messages: Y-channel direct LSB embedding + RS ECC (headerless brute-force).

Shadow messages provide plausible deniability for Ghost mode steganography. Multiple messages can be hidden in a single image, each with a different passphrase. They are embedded as absolute-value LSBs into Y-channel nzAC positions (the same domain as primary STC), using nsf5 modification.

The system auto-sorts messages by size: the largest becomes the primary (embedded via STC for full stealth), smaller messages become shadow channels (embedded via direct LSB with Reed-Solomon error correction).

§Headerless design

No magic byte, no frame_data_len in the bitstream. The decoder brute-forces all (parity, fdl) combinations. AES-256-GCM-SIV authentication is the only validator — successful decryption proves correct parameters.

§Short STC + Dynamic w

Since shadows and primary STC share the same Y-channel LSBs, the primary STC uses “short” message mode: only the actual m message bits are passed (not zero-padded to m_max). With dynamic w = min(floor(n/m), 10), small messages get high w, meaning 2,500x fewer modifications. When w >= 2, shadow positions get f32::INFINITY cost in STC, so Viterbi routes around them, achieving BER ~ 0% on shadows.

§Cost-pool position selection

Shadow positions are selected in two tiers for stealth:

  1. Tier 1 (cost pool): Filter all Y nzAC positions to the cheapest fraction (5%, 10%, 20%, 50%, or 100%) by UNIWARD cost. Cheap positions are in textured regions — modifications there are least detectable.
  2. Tier 2 (hash permutation): Within the cost pool, select positions by keyed hash ChaCha20(seed, flat_idx) priority.

Encoder uses cover-image costs; decoder uses stego-image costs. The cost pools differ slightly at the boundary (~2-5% positions), but RS error correction handles the resulting BER. Primary Ghost proves this works: encoder and decoder already use cover vs stego costs for STC positions. The decoder brute-forces the fraction alongside parity and fdl.

§Frame format (inside RS-encoded data, no header)

RS-encoded frame (all positions):
    Inner: [plaintext_len: 2B] [salt: 16B] [nonce: 12B] [ciphertext: N+16B]

§nzAC invariance

The nsf5 anti-shrinkage rule (|coeff|==1 -> away from zero) ensures no coefficient ever becomes zero. Since both shadow embedding and primary STC use nsf5, the Y nzAC set is identical at encoder and decoder, guaranteeing position agreement.

Structs§

ShadowState
State for a single shadow layer during encoding.

Functions§

embed_shadow_lsb
Embed shadow intended bits as absolute-value LSBs into the Y DctGrid.
prepare_shadow
Prepare a shadow layer for embedding.
rebuild_shadow
Rebuild a shadow state with new parity and/or fraction.
shadow_capacity
Compute shadow capacity in plaintext bytes from Y nzAC count.
shadow_extract
Full shadow decode pipeline (headerless brute-force).
verify_shadow
Verify a shadow layer can be correctly decoded from the current image state.
verify_shadow_decoder_side
Verify a shadow can be decoded from the decoder’s perspective.