shadowforge 0.3.3

Quantum-resistant steganography toolkit for journalists and whistleblowers
Documentation

shadowforge

Shadowforge

"Forge secrets in the shadows, shield them from quantum eyes — and from the eyes of states."

Rust Edition License Build Tests Coverage Security

shadowforge is a quantum-resistant steganography toolkit for journalists, whistleblowers, and dissidents operating against nation-state adversaries.

It is a Rust reimplementation of shadowforge (Go), with PDF as a first-class citizen and a full suite of countermeasures designed specifically for the journalist-vs-nation-state threat model.


⚠️ Pre-Production Warning

This software has not been externally security audited. Use it as a supplementary layer alongside established tools (Signal, Tor, SecureDrop). See SECURITY.md and THREAT_MODEL.md.


Feature Matrix

Feature Go version Rust version
LSB image steganography
DCT JPEG steganography
Palette steganography
LSB audio (WAV)
Phase encoding (DSSS)
Echo hiding
Zero-width text ✅ (grapheme-cluster-safe)
PDF embedding ⚠️ afterthought ✅ first-class
PDF content-stream LSB
PDF XMP metadata embedding
PDF shard-per-page pipeline
ML-KEM-1024 (NIST FIPS 203) via CIRCL (CGo) ✅ pure Rust
ML-DSA-87 (NIST FIPS 204) via CIRCL (CGo) ✅ pure Rust
Reed-Solomon K-of-N
4 distribution patterns
Adversarial embedding optimisation
Camera model fingerprint matching
Compression-survivable embedding
Deniable dual-payload steganography
Panic wipe
Dead drop mode
Canary shard tripwires
Time-lock puzzle payloads
Stylometric fingerprint scrubbing
Corpus steganography (zero-modification)
Amnesiac mode (zero disk writes)
Geographic threshold distribution
Forensic watermark tripwires

Quick Start

Installation

# From source (requires Rust 1.94.1)
git clone https://github.com/greysquirr3l/shadowforge-rs
cd shadowforge-rs
make release
sudo install target/release/shadowforge /usr/local/bin/

PDF Support (Optional)

PDF page rasterisation requires the pdfium shared library. Without it, PDF content-stream and metadata steganography still work, but the render-to-PNG pipeline is unavailable.

# macOS (Apple Silicon)
curl -L https://github.com/bblanchon/pdfium-binaries/releases/latest/download/pdfium-mac-arm64.tgz | tar xz
export PDFIUM_DYNAMIC_LIB_PATH="$(pwd)/lib"

# macOS (Intel)
curl -L https://github.com/bblanchon/pdfium-binaries/releases/latest/download/pdfium-mac-x64.tgz | tar xz
export PDFIUM_DYNAMIC_LIB_PATH="$(pwd)/lib"

# Linux (x86_64)
curl -L https://github.com/bblanchon/pdfium-binaries/releases/latest/download/pdfium-linux-x64.tgz | tar xz
export PDFIUM_DYNAMIC_LIB_PATH="$(pwd)/lib"

To persist the environment variable, add the export line to your shell profile (~/.bashrc, ~/.zshrc, etc.).


Building with Features

shadowforge uses Cargo's optional feature system to control which capabilities are compiled in. This allows users to reduce the attack surface and dependencies by disabling features they don't need.

Available Features

Feature Default Purpose
pdf PDF embedding/extraction and page rasterisation (requires pdfium)
corpus Corpus-based steganography (zero-modification cover selection)
adaptive Adaptive embedding (STC-inspired steganalysis evasion)
simd SIMD acceleration for Reed-Solomon (if available on platform)

Disabling Features

By default, pdf, corpus, and adaptive are enabled. To build with fewer features:

# Disable all optional features
cargo build --no-default-features

# Disable only PDF
cargo build --no-default-features --features corpus,adaptive

# Enable SIMD in addition to defaults (for performance-critical deployments)
cargo build --features simd

# Enable only SIMD without defaults
cargo build --no-default-features --features simd

Installing from crates.io

When using shadowforge as a dependency:

# In your Cargo.toml
[dependencies]
shadowforge = "0.3"  # All default features enabled

# Or with specific features
shadowforge = { version = "0.3", features = ["corpus"] }

# Or with no features
shadowforge = { version = "0.3", default-features = false }

Installing the Binary with Features

# Install with all features (default)
cargo install shadowforge

# Install without PDF support
cargo install shadowforge --no-default-features --features corpus,adaptive

# Install from source with specific features
git clone https://github.com/greysquirr3l/shadowforge-rs
cd shadowforge-rs
cargo install --path crates/shadowforge --features pdf,corpus,adaptive

PDF Support (Optional)

PDF page rasterisation requires the pdfium shared library. Without it, PDF content-stream and metadata steganography still work, but the render-to-PNG pipeline is unavailable.

The build process will auto-detect pdfium if:

  • Set via PDFIUM_DYNAMIC_LIB_PATH environment variable
  • Found in a standard system library directory (/usr/local/lib, /usr/lib, /usr/lib/x86_64-linux-gnu, /usr/lib/aarch64-linux-gnu on Linux/macOS; C:\Program Files\pdfium\lib on Windows)
  • Found via the OS dynamic loader's configured library search paths

If pdfium is not found, the build will emit a warning with setup instructions.

To manually set up pdfium:

# macOS (Apple Silicon)
curl -L https://github.com/bblanchon/pdfium-binaries/releases/latest/download/pdfium-mac-arm64.tgz | tar xz
export PDFIUM_DYNAMIC_LIB_PATH="$(pwd)/lib"

# macOS (Intel)
curl -L https://github.com/bblanchon/pdfium-binaries/releases/latest/download/pdfium-mac-x64.tgz | tar xz
export PDFIUM_DYNAMIC_LIB_PATH="$(pwd)/lib"

# Linux (x86_64)
curl -L https://github.com/bblanchon/pdfium-binaries/releases/latest/download/pdfium-linux-x64.tgz | tar xz
export PDFIUM_DYNAMIC_LIB_PATH="$(pwd)/lib"

Shell Completions

# Generate completions for your shell
shadowforge completions bash > ~/.local/share/bash-completion/completions/shadowforge
shadowforge completions zsh > ~/.zfunc/_shadowforge
shadowforge completions fish > ~/.config/fish/completions/shadowforge.fish

Basic Usage

# Generate a key pair
shadowforge keygen --algorithm kyber1024 --output ~/keys/

# Embed a payload in an image (adaptive mode — defeats commodity steganalysis)
shadowforge embed \
    --input secret.txt \
    --cover photo.jpg \
    --output stego.jpg \
    --key ~/keys/public.key \
    --technique lsb \
    --profile adaptive

# Extract
shadowforge extract \
    --input stego.jpg \
    --key ~/keys/secret.key \
    --output recovered.txt \
    --technique lsb

# Deniable embedding (two payloads, one cover, plausible deniability)
shadowforge embed \
    --input real_document.txt \
    --cover photo.jpg \
    --output stego.jpg \
    --key ~/keys/public.key \
    --deniable \
    --decoy-payload innocent.txt \
    --decoy-key ~/keys/decoy_public.key

# Analyse detectability before embedding
shadowforge analyze detectability --cover photo.jpg --technique lsb

# Dead drop: encode for Instagram (survives platform recompression)
shadowforge dead-drop encode \
    --cover photo.jpg \
    --input secret.txt \
    --platform instagram \
    --key ~/keys/public.key \
    --output upload_ready.jpg \
    --manifest-output retrieval.json

# Scrub stylometric fingerprints from a text payload
shadowforge scrub --input my_document.txt --output scrubbed.txt

# Distribute across multiple covers with geographic manifest
shadowforge embed-distributed \
    --input document.txt \
    --covers contact_photos/*.jpg \
    --data-shards 3 \
    --parity-shards 2 \
    --output-archive shards.zip \
    --key ~/keys/public.key \
    --canary \
    --geo-manifest geo.toml

# Zero-trace mode (no disk writes)
shadowforge embed --amnesia \
    --input payload.txt \
    --cover cover.jpg \
    --key public.key > output.jpg

Architecture

Cargo workspace mono-repo — all crates live under crates/. The main crate is crates/shadowforge, organised as Collapsed Hexagonal / DDD-lite with four layers: domain/ (pure, no I/O), adapters/ (I/O and FFI), application/ (thin orchestration), interface/ (CLI).

Seventeen bounded contexts live under domain/, sharing a single canonical type vocabulary (domain/types.rs). Nothing is re-invented per context.

Future crates (shadowforge-web, shadowforge-api, etc.) add as new members under crates/ — no restructuring required.

See the full architecture documentation for design rationale and bounded context details.


Threat Model

See THREAT_MODEL.md for the full threat model.

Adversary: Nation-state. Automated mass steganalysis, compelled decryption, traffic analysis, endpoint compromise, jurisdictional legal pressure, stylometric source identification.


Operational Security

Operational playbooks with step-by-step procedures for five common journalist scenarios are available in the source repository (clone to access). They cover border crossings, dead drops, geographic distribution, time-lock source protection, and zero-trace operation.

See docs/src/opsec/ after cloning.


Documentation

Full documentation is published at greysquirr3l.github.io/shadowforge-rs — covering CLI reference, threat model, architecture, and contributing guidelines.


Development

make build      # cargo build
make test       # cargo test
make lint       # cargo clippy -D warnings
make check      # fmt + lint + test + deny
make coverage   # cargo tarpaulin (requires install)
make deny       # cargo deny check
make completions # generate shell completions
make book       # build mdbook site locally
make doc        # build rustdoc API docs

Test Coverage

453 tests across all adapter, domain, and application modules — 85% line coverage. Key module coverage:

Module Coverage
application/services 100%
domain/types 100%
domain/analysis 98.6%
domain/crypto 93.5%
domain/distribution 89.2%
adapters/opsec 88%
adapters/media 86.4%
adapters/archive 86%
adapters/stego 84.5%

Coverage is enforced via cargo-tarpaulin with an 85% overall threshold and a 90% threshold for domain::crypto.

See the contributing guide for full development setup instructions.


License

Apache License 2.0 — see LICENSE.


Acknowledgements

Built on the shoulders of: ml-kem, ml-dsa, reed-solomon-erasure, lopdf, pdfium-render, unicode-segmentation, zeroize, subtle.

Go version: greysquirr3l/shadowforge