diff --git a/docs/rfcs/RFC-0015_Transport_Skins.md b/docs/rfcs/RFC-0015_Transport_Skins.md new file mode 100644 index 0000000..333502d --- /dev/null +++ b/docs/rfcs/RFC-0015_Transport_Skins.md @@ -0,0 +1,393 @@ +# RFC-0015: Pluggable Transport Skins (PTS) + +**Status:** Draft +**Author:** Frankie (Silicon Architect) +**Date:** 2026-02-03 +**Target:** Janus SDK L0 Transport Layer +**Classification:** CRYPTOGRAPHIC / CENSORSHIP-RESISTANT + +--- + +## Summary + +Transport Skins provide **pluggable censorship resistance** for Libertaria's L0 Transport layer. Each "skin" wraps the standard LWF (Lightweight Wire Format) frame to mimic benign traffic patterns, defeating state-level Deep Packet Inspection (DPI) as deployed by China's GFW, Russia's RKN, Iran's Filternet, and similar adversaries. + +**Core Innovation:** Per-session **Polymorphic Noise Generator (PNG)** ensures no two sessions ever exhibit identical traffic patterns. + +--- + +## Threat Model + +### Adversary Capabilities (GFW-Class) +| Technique | Capability | Our Counter | +|-----------|------------|-------------| +| Magic Byte Detection | Signature matching at line rate | Skins remove/replace magic bytes | +| TLS Fingerprinting (JA3/JA4) | Statistical TLS handshake analysis | utls-style parroting (Chrome/Firefox mimicry) | +| SNI Inspection | Cleartext server name identification | ECH (Encrypted Client Hello) + Domain Fronting | +| Packet Size Analysis | Fixed MTU detection | Probabilistic size distributions | +| Timing Correlation | Inter-packet timing patterns | Exponential/Gamma jitter | +| Flow Correlation | Long-term traffic statistics | Epoch rotation (100-1000 packets) | +| Active Probing | Sending test traffic to suspected relays | Honeytrap responses + IP blacklisting | +| DNS Manipulation | Poisoning, blocking, inspection | DoH (DNS-over-HTTPS) tunneling | + +### Non-Goals +- **Traffic confirmation attacks** (end-to-end correlation): Out of scope; use L2 Membrane mixing +- **Physical layer interception**: Out of scope; requires steganographic hardware +- **Compromised endpoints**: Out of scope; requires TEE/SEV-SNP attestation + +--- + +## Architecture + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ RFC-0015: TRANSPORT SKINS │ +│ "Submarine Camouflage" │ +├─────────────────────────────────────────────────────────────────────────┤ +│ │ +│ L3+ Application │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ LWF FRAME │ │ +│ │ • 1350 bytes (configurable) │ │ +│ │ • XChaCha20-Poly1305 encrypted │ │ +│ │ • Magic bytes: LWF\0 (internal only) │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ POLYMORPHIC NOISE GENERATOR (PNG) │ │ +│ │ • ECDH-derived per-session seed │ │ +│ │ • Epoch-based profile rotation (100-1000 packets) │ │ +│ │ • Deterministic both ends (same seed = same noise) │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ SKIN SELECTOR │ │ +│ │ │ │ +│ │ ┌─────────┐ ┌─────────────┐ ┌───────────┐ ┌───────────┐ │ │ +│ │ │ RAW │ │MIMIC_HTTPS │ │MIMIC_DNS │ │MIMIC_VIDEO│ │ │ +│ │ │ UDP │ │WebSocket/TLS│ │DoH Tunnel │ │HLS chunks │ │ │ +│ │ └────┬────┘ └──────┬──────┘ └─────┬─────┘ └─────┬─────┘ │ │ +│ │ │ │ │ │ │ │ +│ │ └──────────────┴───────────────┴──────────────┘ │ │ +│ │ │ │ │ +│ │ Auto-selection via probing │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ NETWORK (ISP/GFW/RKN sees only the skin's traffic pattern) │ +│ │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Polymorphic Noise Generator (PNG) + +### Design Principles +1. **Per-session uniqueness:** ECDH handshake secret seeds ChaCha20 RNG +2. **Deterministic:** Both peers derive identical noise from shared secret +3. **Epoch rotation:** Profile changes every N packets (prevents long-term analysis) +4. **Distribution matching:** Sample sizes/timing from real-world captures + +### Noise Parameters (Per Epoch) +```zig +pub const EpochProfile = struct { + // Packet size distribution + size_distribution: enum { Normal, Pareto, Bimodal, LogNormal }, + size_mean: u16, // e.g., 1440 bytes + size_stddev: u16, // e.g., 200 bytes + + // Timing distribution + timing_distribution: enum { Exponential, Gamma, Pareto }, + timing_lambda: f64, // For exponential: mean inter-packet time + + // Dummy packet injection + dummy_probability: f64, // 0.0-0.15 (0-15% fake packets) + dummy_distribution: enum { Uniform, Bursty }, + + // Epoch boundaries + epoch_packet_count: u32, // 100-1000 packets before rotation +}; +``` + +### Seed Derivation +``` +Session Secret (ECDH) → HKDF-SHA256 → 256-bit PNG Seed + ↓ + ┌───────────────────────┐ + │ ChaCha20 RNG State │ + └───────────────────────┘ + ↓ + ┌───────────────────────┐ + │ Epoch Profile Chain │ + │ (deterministic) │ + └───────────────────────┘ +``` + +--- + +## Transport Skins + +### Skin 0: RAW (Unrestricted Networks) +**Use case:** Friendly jurisdictions, LAN, high-performance paths + +| Property | Value | +|----------|-------| +| Protocol | UDP direct | +| Port | 7844 (default) | +| Overhead | 0% | +| Latency | Minimal | +| Kenya Viable | ✅ Yes | + +**Wire format:** +``` +[LWF Frame: 1350 bytes] +``` + +--- + +### Skin 1: MIMIC_HTTPS (Standard Censorship Bypass) +**Use case:** GFW, RKN, corporate firewalls (90% coverage) + +| Property | Value | +|----------|-------| +| Protocol | WebSocket over TLS 1.3 | +| Port | 443 | +| SNI | Domain fronting capable (ECH preferred) | +| Overhead | ~5% (TLS + WS framing) | +| Latency | +50-100ms | +| Kenya Viable | ✅ Yes | + +**TLS Fingerprinting Defense:** +- utls-style parroting (exact Chrome/Firefox JA3 signatures) +- HTTP/2 settings matching browser defaults +- ALPN: `h2, http/1.1` + +**Wire format:** +``` +TLS 1.3 Record Layer { + Content Type: Application Data (23) + TLS Ciphertext: { + WebSocket Frame { + FIN: 1 + Opcode: Binary (0x02) + Masked: 0 (server→client) / 1 (client→server) + Payload: [PNG Noise] + [LWF Frame] + } + } +} +``` + +**WebSocket Handshake (Cover):** +``` +GET /api/v3/stream HTTP/1.1 +Host: cdn.cloudflare.com +Upgrade: websocket +Connection: Upgrade +Sec-WebSocket-Key: +Sec-WebSocket-Version: 13 +User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)... +``` + +--- + +### Skin 2: MIMIC_DNS (Deep Censorship Bypass) +**Use case:** UDP blocked, HTTPS throttled, Iran/Turkmenistan edge cases + +| Property | Value | +|----------|-------| +| Protocol | DNS-over-HTTPS (DoH) | +| Endpoint | 1.1.1.1, 8.8.8.8, 9.9.9.9 | +| Overhead | ~300% (Base64url encoding) | +| Latency | +200-500ms | +| Kenya Viable | ⚠️ Marginal (bandwidth-heavy) | + +**DNS Tunnel Defenses:** +- **DoH not raw DNS:** Blends with real DoH traffic +- **Query distribution:** Match real DoH query timing (not regular intervals) +- **Label entropy:** Use dictionary words for subdomain labels (not base32) + +**Wire format:** +``` +POST /dns-query HTTP/2 +Host: cloudflare-dns.com +Content-Type: application/dns-message +Accept: application/dns-message + +Body: DNS Message { + Question: + QTYPE: TXT (or HTTPS for larger payloads) +} +``` + +--- + +### Skin 3: MIMIC_VIDEO (High-Bandwidth Bypass) +**Use case:** Video-streaming-whitelisted networks, QoS prioritization + +| Property | Value | +|----------|-------| +| Protocol | HTTPS with HLS (HTTP Live Streaming) chunk framing | +| Mimics | Netflix, YouTube, Twitch | +| Overhead | ~10% (HLS `.ts` container) | +| Latency | +100-200ms | +| Kenya Viable | ✅ Yes | + +**Wire format:** +``` +HTTP/2 200 OK +Content-Type: video/mp2t +X-LWF-Sequence: + +Body: [HLS MPEG-TS Container] { + Adaptation Field: [PNG padding] + Payload: [LWF Frame] +} +``` + +--- + +### Skin 4: STEGO_IMAGE (Nuclear Option) +**Use case:** Total lockdown, emergency fallback only + +| Property | Value | +|----------|-------| +| Protocol | HTTPS POST to image hosting (Imgur, etc.) | +| Stego Method | Generative steganography (StyleGAN encoding) | +| Bandwidth | ~1 byte per image (extremely slow) | +| Latency | Seconds to minutes | +| Kenya Viable | ❌ Emergency only | + +**Note:** Traditional LSB steganography is broken against ML detection. Use generative encoding only. + +--- + +## Automatic Skin Selection + +### Probe Sequence +```zig +pub const SkinProbe = struct { + /// Attempt skin selection with timeouts + pub async fn auto_select(relay: RelayEndpoint) !TransportSkin { + // 1. RAW UDP (fastest, 100ms timeout) + if (try probe_raw(relay, 100ms)) { + return .raw; + } + + // 2. HTTPS WebSocket (500ms timeout) + if (try probe_https(relay, 500ms)) { + return .mimic_https(relay); + } + + // 3. DNS Tunnel (1s timeout) + if (try probe_dns(relay, 1s)) { + return .mimic_dns(relay); + } + + // 4. Nuclear option (no probe, async only) + return .stego_async(relay); + } +}; +``` + +### Multi-Path Agility (MPTCP-Style) +```zig +pub const MultiSkinSession = struct { + primary: TransportSkin, // 90% bandwidth (HTTPS) + secondary: TransportSkin, // 10% bandwidth (DNS keepalive) + + /// If primary throttled, signal via secondary + pub fn adapt_to_throttling(self: *Self) void { + if (self.primary.detect_throttling()) { + self.secondary.signal_endpoint_switch(); + } + } +}; +``` + +--- + +## Active Probing Defenses + +### Honeytrap Responses +When probed without valid session state: +1. **HTTPS Skin:** Respond as legitimate web server (nginx default page) +2. **DNS Skin:** Return NXDOMAIN or valid A record (not relay IP) +3. **Rate limit:** Exponential backoff on failed handshakes + +### Reputation Tokens +Prevent rapid relay scanning: +``` +Client → Relay: ClientHello + PoW (Argon2, 100ms) +Relay → Client: ServerHello (only if PoW valid) +``` + +--- + +## Implementation Phases + +### Phase 1: Foundation (Sprint 5) +- [ ] PNG core (ChaCha20 RNG, epoch rotation) +- [ ] RAW skin (baseline) +- [ ] MIMIC_HTTPS skin (WebSocket + TLS) +- [ ] utls fingerprint parroting +- [ ] Automatic probe selection + +### Phase 2: Deep Bypass (Sprint 6) +- [ ] MIMIC_DNS skin (DoH tunnel) +- [ ] ECH support (Encrypted Client Hello) +- [ ] Active probing defenses +- [ ] Multi-path agility + +### Phase 3: Advanced (Sprint 7) +- [ ] MIMIC_VIDEO skin (HLS framing) +- [ ] Distribution matching from real captures +- [ ] Steganography (generative only) +- [ ] Formal security audit + +--- + +## Kenya Compliance Check + +| Skin | RAM | Binary Size | Cloud Calls | Viable? | +|------|-----|-------------|-------------|---------| +| RAW | <1MB | +0KB | None | ✅ | +| MIMIC_HTTPS | <2MB | +50KB (TLS) | None (embedded TLS) | ✅ | +| MIMIC_DNS | <1MB | +10KB | DoH to public resolver | ✅ | +| MIMIC_VIDEO | <2MB | +20KB (HLS) | None | ✅ | +| STEGO | >100MB | +500MB (ML models) | Image host upload | ❌ | + +--- + +## Security Considerations + +### TLS Fingerprinting (Critical) +**Risk:** Rustls default JA3 signature is trivially blockable. +**Mitigation:** Mandatory utls parroting; exact Chrome/Firefox match. + +### DNS Tunnel Detectability (High) +**Risk:** Base32 subdomains have high entropy (4.8 vs 2.5 bits/char). +**Mitigation:** Use DoH to major providers; dictionary-word labels. + +### Flow Correlation (Medium) +**Risk:** Long-term traffic statistics identify protocol. +**Mitigation:** PNG epoch rotation; per-session uniqueness. + +--- + +## References + +1. **utls:** [github.com/refraction-networking/utls](https://github.com/refraction-networking/utls) — TLS fingerprint parroting +2. **Snowflake:** [Tor Project](https://snowflake.torproject.org/) — WebRTC pluggable transport +3. **Conjure:** [refraction.network](https://refraction.network/) — Refraction networking +4. **ECH:** RFC 9446 — Encrypted Client Hello +5. **DoH:** RFC 8484 — DNS over HTTPS + +--- + +*"The submarine wears chameleon skin. The hull remains the same."* +⚡️ diff --git a/features/transport/polymorphic_noise.feature b/features/transport/polymorphic_noise.feature new file mode 100644 index 0000000..1acb851 --- /dev/null +++ b/features/transport/polymorphic_noise.feature @@ -0,0 +1,251 @@ +Feature: RFC-0015 Polymorphic Noise Generator (PNG) + As a Libertaria protocol developer + I want cryptographically secure per-session traffic shaping + So that state-level DPI cannot fingerprint or correlate sessions + + Background: + Given the PNG is initialized with ChaCha20 RNG + And the entropy source is the ECDH shared secret + + # ============================================================================ + # Seed Derivation and Determinism + # ============================================================================ + + Scenario: PNG seed derives from ECDH shared secret + Given Alice and Bob perform X25519 ECDH + And the shared secret is 32 bytes + When Alice derives PNG seed via HKDF-SHA256 + And Bob derives PNG seed via HKDF-SHA256 + Then both seeds should be 256 bits + And the seeds should be identical + And the derivation should use "Libertaria-PNG-v1" as context + + Scenario: Different sessions produce different seeds + Given Alice and Bob perform ECDH for Session A + And Alice and Bob perform ECDH for Session B + When PNG seeds are derived for both sessions + Then the seeds should be different + And the Hamming distance should be ~128 bits + + Scenario: PNG seed has sufficient entropy + Given 1000 independent ECDH handshakes + When PNG seeds are derived for all sessions + Then no seed collisions should occur + And the distribution should pass Chi-square randomness test + + # ============================================================================ + # Epoch Profile Generation + # ============================================================================ + + Scenario: Epoch profile contains all noise parameters + Given a PNG with valid seed + When the first epoch profile is generated + Then it should contain size_distribution variant + And size_mean and size_stddev parameters + And timing_distribution variant + And timing_lambda parameter + And dummy_probability between 0.0 and 0.15 + And epoch_packet_count between 100 and 1000 + + Scenario: Sequential epochs are deterministic + Given a PNG with seed S + When epoch 0 profile is generated + And epoch 1 profile is generated + And a second PNG with same seed S + When epoch 0 and 1 profiles are generated again + Then all corresponding epochs should match exactly + + Scenario: Different seeds produce uncorrelated epochs + Given PNG A with seed S1 + And PNG B with seed S2 + When 10 epochs are generated for both + Then size_mean of corresponding epochs should not correlate + And timing_lambda values should not correlate + And Kolmogorov-Smirnov test should show different distributions + + # ============================================================================ + # Packet Size Noise + # ============================================================================ + + Scenario Outline: Packet size distributions match theoretical models + Given the epoch profile specifies distribution + And size_mean = bytes + And size_stddev = bytes + When 10000 packet sizes are sampled + Then the empirical distribution should match theoretical + And the Chi-square test p-value should be > 0.05 + + Examples: + | distribution | mean | stddev | + | Normal | 1440 | 200 | + | Pareto | 1440 | 400 | + | Bimodal | 1200 | 300 | + | LogNormal | 1500 | 250 | + + Scenario: Packet sizes stay within valid bounds + Given any epoch profile + When packet sizes are sampled + Then all sizes should be >= 64 bytes + And all sizes should be <= 1500 bytes (Ethernet MTU) + And sizes should never exceed interface MTU + + Scenario: Bimodal distribution matches video streaming + Given video streaming capture data + And epoch specifies Bimodal distribution + When PNG samples packet sizes + Then the two modes should be at ~600 bytes and ~1440 bytes + And the ratio should be approximately 1:3 + And the distribution should match YouTube 1080p captures + + # ============================================================================ + # Timing Noise (Inter-packet Jitter) + # ============================================================================ + + Scenario Outline: Timing distributions match theoretical models + Given the epoch profile specifies timing + And timing_lambda = + When 10000 inter-packet delays are sampled + Then the empirical distribution should match theoretical + + Examples: + | distribution | lambda | + | Exponential | 0.01 | + | Gamma | 0.005 | + | Pareto | 0.001 | + + Scenario: Timing jitter prevents clock skew attacks + Given an adversary measures inter-packet timing + When the PNG applies jitter with Exponential distribution + Then the coefficient of variation should be high (>0.5) + And timing side-channel attacks should fail + + Scenario: Maximum latency bound enforcement + Given real-time voice application requirements + And maximum acceptable latency of 500ms + When timing noise is applied + Then no single packet should be delayed >500ms + And 99th percentile latency should be <300ms + + # ============================================================================ + # Dummy Packet Injection + # ============================================================================ + + Scenario: Dummy injection rate follows probability + Given dummy_probability = 0.10 (10%) + When 10000 transmission opportunities occur + Then approximately 1000 dummy packets should be injected + And the binomial 95% confidence interval should contain the count + + Scenario: Dummy packets are indistinguishable from real + Given a mix of real and dummy packets + When examined by adversary + Then packet sizes should have same distribution + And timing should follow same patterns + And entropy analysis should not distinguish them + + Scenario: Bursty dummy injection pattern + Given dummy_distribution = Bursty + And dummy_probability = 0.15 + When dummies are injected + Then they should arrive in clusters (bursts) + And inter-burst gaps should follow exponential distribution + And intra-burst timing should be rapid + + # ============================================================================ + # Epoch Rotation + # ============================================================================ + + Scenario: Epoch rotates after packet count threshold + Given epoch_packet_count = 500 + When 499 packets are transmitted + Then the profile should remain unchanged + When the 500th packet is transmitted + Then epoch rotation should trigger + And a new epoch profile should be generated + + Scenario: Epoch rotation preserves session state + Given an active encrypted session + And epoch rotation triggers + When the new epoch begins + Then encryption keys should remain valid + And sequence numbers should continue monotonically + And no rekeying should be required + + Scenario: Maximum epoch duration prevents indefinite exposure + Given epoch_packet_count = 1000 + And a low-bandwidth application sends 1 packet/minute + When 60 minutes elapse with only 60 packets + Then the epoch should rotate anyway (time-based fallback) + And the maximum epoch duration should be 10 minutes + + # ============================================================================ + # Integration with Transport Skins + # ============================================================================ + + Scenario: PNG noise applied before skin wrapping + Given MIMIC_HTTPS skin is active + And an LWF frame of 1350 bytes + When PNG adds padding noise + Then the total size should follow epoch's distribution + And the padding should be added before TLS encryption + And the WebSocket frame should contain padded payload + + Scenario: PNG noise subtraction by receiving peer + Given PNG adds 50 bytes of padding to a packet + When the packet arrives at destination + And the peer uses same PNG seed + Then the padding should be identifiable + And the original 1350-byte LWF frame should be recoverable + + Scenario: Different skins use same PNG instance + Given a session starts with RAW skin + And PNG is seeded + When skin switches to MIMIC_HTTPS + Then the PNG should continue same epoch sequence + And noise patterns should remain consistent + + # ============================================================================ + # Statistical Security Tests + # ============================================================================ + + Scenario: NIST SP 800-22 randomness tests + Given 1MB of PNG output (ChaCha20 keystream) + When subjected to NIST statistical test suite + Then all 15 tests should pass + Including Frequency, Runs, FFT, Template matching + + Scenario: Dieharder randomness tests + Given 10MB of PNG output + When subjected to Dieharder test suite + Then no tests should report "WEAK" or "FAILED" + + Scenario: Avalanche effect on seed changes + Given PNG seed S1 produces output stream O1 + When one bit is flipped in seed (S2 = S1 XOR 0x01) + And output stream O2 is generated + Then O1 and O2 should differ in ~50% of bits + And the correlation coefficient should be ~0 + + # ============================================================================ + # Performance and Resource Usage + # ============================================================================ + + Scenario: PNG generation is fast enough for line rate + Given 1 Gbps network interface + And 1500 byte packets + When PNG generates noise for each packet + Then generation time should be <1μs per packet + And CPU usage should be <5% of one core + + Scenario: PNG memory footprint is minimal + Given the PNG is initialized + When measuring memory usage + Then ChaCha20 state should use ≤136 bytes + And epoch profile should use ≤64 bytes + And total PNG overhead should be <1KB per session + + Scenario: PNG works on constrained devices + Given a device with 10MB RAM (Kenya compliance) + When 1000 concurrent sessions are active + Then total PNG memory should be <10MB + And each session PNG overhead should be <10KB diff --git a/features/transport/transport_skins.feature b/features/transport/transport_skins.feature new file mode 100644 index 0000000..711f7ed --- /dev/null +++ b/features/transport/transport_skins.feature @@ -0,0 +1,214 @@ +Feature: RFC-0015 Pluggable Transport Skins + As a Libertaria node operator in a censored region + I want to automatically select camouflaged transport protocols + So that my traffic evades detection by state-level DPI (GFW, RKN, etc.) + + Background: + Given the L0 transport layer is initialized + And the node has a valid relay endpoint configuration + And the Polymorphic Noise Generator (PNG) is seeded with ECDH secret + + # ============================================================================ + # Skin Selection and Probing + # ============================================================================ + + Scenario: Automatic skin selection succeeds with RAW UDP + Given the network allows outbound UDP to port 7844 + When the skin probe sequence starts + And the RAW UDP probe completes within 100ms + Then the transport skin should be "RAW" + And the LWF frames should be sent unmodified over UDP + + Scenario: Automatic skin selection falls back to HTTPS + Given the network blocks UDP port 7844 + And HTTPS traffic to port 443 is allowed + When the RAW UDP probe times out after 100ms + And the HTTPS WebSocket probe completes within 500ms + Then the transport skin should be "MIMIC_HTTPS" + And the LWF frames should be wrapped in WebSocket frames over TLS 1.3 + + Scenario: Automatic skin selection falls back to DNS tunnel + Given the network blocks all UDP except DNS + And blocks HTTPS to non-whitelisted domains + When the RAW UDP probe times out + And the HTTPS probe times out after 500ms + And the DNS DoH probe completes within 1s + Then the transport skin should be "MIMIC_DNS" + And the LWF frames should be encoded as DNS queries over HTTPS + + Scenario: Automatic skin selection reaches nuclear option + Given the network implements deep packet inspection on all protocols + And all previous probes fail + When the probe sequence reaches the steganography fallback + Then the transport skin should be "STEGO_IMAGE" + And the user should be warned of extreme latency + + # ============================================================================ + # Polymorphic Noise Generator (PNG) + # ============================================================================ + + Scenario: PNG generates per-session unique noise + Given two independent sessions to the same relay + And both sessions complete ECDH handshake + When Session A derives PNG seed from shared secret + And Session B derives PNG seed from its shared secret + Then the PNG seeds should be different + And the epoch profiles should be different + And the packet size distributions should not correlate + + Scenario: PNG generates deterministic noise for session peers + Given a single session between Alice and Bob + And they complete ECDH handshake + When Alice derives PNG seed from shared secret + And Bob derives PNG seed from same shared secret + Then the PNG seeds should be identical + And Alice's noise can be subtracted by Bob + + Scenario: PNG epoch rotation prevents long-term analysis + Given a session using MIMIC_HTTPS skin + And the epoch length is set to 500 packets + When 499 packets have been transmitted + Then the packet size distribution should follow Profile A + When the 500th packet is transmitted + Then the epoch should rotate + And the packet size distribution should follow Profile B + And Profile B should be different from Profile A + + Scenario: PNG matches real-world distributions + Given MIMIC_HTTPS skin with Netflix emulation + When the PNG samples packet sizes + Then the distribution should be Pareto with mean 1440 bytes + And the distribution should match Netflix video chunk captures + + # ============================================================================ + # MIMIC_HTTPS Skin (WebSocket over TLS) + # ============================================================================ + + Scenario: HTTPS skin mimics Chrome TLS fingerprint + Given the transport skin is "MIMIC_HTTPS" + When the TLS handshake initiates + Then the ClientHello should match Chrome 120 JA3 signature + And the cipher suites should match Chrome defaults + And the extensions order should match Chrome + And the ALPN should be "h2,http/1.1" + + Scenario: HTTPS skin WebSocket handshake looks legitimate + Given the transport skin is "MIMIC_HTTPS" + When the WebSocket upgrade request is sent + Then the HTTP headers should include legitimate User-Agent + And the request path should look like a real API endpoint + And the Origin header should be set appropriately + + Scenario: HTTPS skin hides LWF magic bytes + Given an LWF frame with magic bytes "LWF\0" + When wrapped in MIMIC_HTTPS skin + Then the wire format should be TLS ciphertext + And the magic bytes should not appear in cleartext + And DPI signature matching should fail + + Scenario: HTTPS skin with domain fronting + Given the relay supports domain fronting + And the cover domain is "cdn.cloudflare.com" + And the real endpoint is "relay.libertaria.network" + When the TLS handshake initiates + Then the SNI should be "cdn.cloudflare.com" + And the HTTP Host header should be "relay.libertaria.network" + + Scenario: HTTPS skin with ECH (Encrypted Client Hello) + Given the relay supports ECH + And the client has ECH config for the relay + When the TLS handshake initiates + Then the ClientHelloInner should contain real SNI + And the ClientHelloOuter should have encrypted SNI + And passive DPI should not see the real destination + + # ============================================================================ + # MIMIC_DNS Skin (DoH Tunnel) + # ============================================================================ + + Scenario: DNS skin uses DoH not raw DNS + Given the transport skin is "MIMIC_DNS" + When a DNS query is sent + Then it should be an HTTPS POST to 1.1.1.1 + And the Content-Type should be "application/dns-message" + And not use raw port 53 UDP + + Scenario: DNS skin avoids high-entropy labels + Given the transport skin is "MIMIC_DNS" + When encoding LWF data as DNS queries + Then subdomain labels should use dictionary words + And the Shannon entropy should be < 3.5 bits/char + And not use Base32/Base64 encoding + + Scenario: DNS skin matches real DoH timing + Given the transport skin is "MIMIC_DNS" + When sending queries + Then the inter-query timing should follow Gamma distribution + And not be perfectly regular + And should match Cloudflare DoH query patterns + + # ============================================================================ + # Anti-Fingerprinting and Active Defense + # ============================================================================ + + Scenario: Active probe receives honeytrap response + Given an adversary sends probe traffic to relay + And the probe has no valid session cookie + When the relay receives the probe + Then it should respond as nginx default server + And return HTTP 200 with generic index.html + And not reveal itself as Libertaria relay + + Scenario: Rate limiting on failed handshakes + Given an adversary attempts rapid handshake scanning + When more than 10 failed handshakes occur from same IP in 1 minute + Then subsequent connections should be rate limited + And exponential backoff should apply + + Scenario: PoW prevents relay enumeration + Given the relay requires proof-of-work + When a client connects without valid PoW + Then the connection should be rejected + When a client connects with valid Argon2 PoW (100ms compute) + Then the connection should proceed to handshake + + # ============================================================================ + # Multi-Path Agility + # ============================================================================ + + Scenario: Primary skin throttling triggers fallback + Given primary skin is MIMIC_HTTPS at 90% bandwidth + And secondary skin is MIMIC_DNS at 10% bandwidth + When GFW detects and throttles HTTPS traffic + Then the secondary channel should signal endpoint switch + And the primary should migrate to new relay IP + + Scenario: Seamless skin switching without rekeying + Given an active session with MIMIC_HTTPS + When the skin switches to MIMIC_DNS due to blocking + Then the LWF encryption keys should remain valid + And no re-handshake should be required + And in-flight packets should not be lost + + # ============================================================================ + # Error Handling and Edge Cases + # ============================================================================ + + Scenario: All probes fail raises alert + Given all network paths are blocked + When the skin probe sequence completes + And no viable skin is found + Then the user should receive "Network severely restricted" alert + And manual configuration option should be offered + + Scenario: Skin mid-session failure recovery + Given a session is active with MIMIC_HTTPS + When the TLS connection drops unexpectedly + Then automatic reconnection should attempt same skin first + And fallback to next skin after 3 retries + + Scenario: Invalid skin configuration is rejected + Given the configuration specifies unknown skin "MIMIC_UNKNOWN" + When the transport initializes + Then initialization should fail with "Invalid skin" + And fallback to automatic selection should occur