throughput: fast ring ChaCha20-Poly1305 data-plane AEAD (~3.3×) #52

Merged
vxfemboy merged 7 commits from feat/throughput-fast-aead into main 2026-07-11 18:07:13 +00:00
vxfemboy commented 2026-07-11 17:53:49 +00:00 (Migrated from github.com)

What

Replaces the data-plane AEAD implementation: yip_crypto::Session::seal/open now use ring's ChaCha20-Poly1305 keyed by snow's secret Split() transport keys, instead of snow's slower RustCrypto transport path. Same 256-bit ChaCha20-Poly1305 cipher (CLAUDE.md-conformant), byte-identical wire, ~3.3× faster. snow is now used for the handshake only. Lever 2 of 3 for single-core 10-Gbit (cheap FEC ✓ → fast AEAD ✓ → AF_XDP/batched I/O).

Why

Post-P+Q, AEAD seal (~2.1 µs) was the dominant single-core per-packet cost. A probe on the target VPS (Ryzen 9 3900X, 1 core, AVX2+AES-NI) showed openssl does asm ChaCha20-Poly1305 at ~0.73 µs — a ~3× implementation gap within the same cipher. So this is purely a faster impl: no cipher change, no security-model change, handshake untouched. (Post-quantum is a separate handshake-layer milestone; symmetric ChaCha20 is already quantum-safe.)

How (A2, chosen by a spike)

A spike (Task 1) proved that ring ChaCha20-Poly1305 — using snow's extracted dangerously_get_raw_split() keys + the Noise nonce ([0,0,0,0] ++ counter.to_le_bytes(), empty AAD) — is byte-for-byte identical to snow's write_message, and ~4× faster, so it's wire-compatible with existing nodes.

  • crates/yip-crypto/src/lib.rsSession holds two directional ring::aead::LessSafeKeys; into_session extracts the secret Split() keys and role-maps them (is_initiator: k0=initiator-send/responder-recv). seal/open use ring. Added no-alloc seal_into/open_into.
  • crates/yip-crypto/Cargo.toml — add ring; snow gains risky-raw-split.
  • bin/yipd/src/dataplane.rs — tx hot loop uses seal_into + mem::take into the retx buffer (2→1 alloc/packet, removes a per-packet clone).

Keys come from the secret Split() output — never the channel binding (the handshake hash isn't secret). Nonce uniqueness is guaranteed by the monotonic per-direction counter; the Noise handshake, replay window, and counter semantics are untouched.

Results

  • aead_seal_1300: ~2.1 µs → 0.63 µs (~3.3×).
  • A durable in-crate byte-identity KAT proves Session::seal output == snow's write_message for both directions across counters (teeth-verified: a wrong nonce endianness or swapped key mapping makes it fail). yip-crypto 18/18, workspace 351/351, clippy clean, #![forbid(unsafe_code)] intact (ring's SIMD is internal).
  • netns end-to-end (real sudo): tunnel, 10%-loss recovery, and ARQ integrity (99.4% delivery, 116 retransmits) all pass — a session establishes and passes traffic with the new cipher.

Final whole-branch review (opus): READY TO MERGE — traced no nonce-reuse path (ARQ regenerates FEC over stored ciphertext, never re-encrypts) and no send/recv key mismatch (guarded by the both-directions KAT).

Notes

  • A per-task review caught a missing durable byte-identity KAT (the proof lived only in the throwaway spike); it was added + teeth-verified before merge. The throwaway spike + its dev-deps were then removed.
  • Minor (documented): seal_buf is moved into the retx buffer on most packets, so it isn't reused across packets — still a net 2→1 alloc.

Design docs

  • Spec: docs/superpowers/specs/2026-07-11-throughput-fast-aead-design.md
  • Plan: docs/superpowers/plans/2026-07-11-throughput-fast-aead.md

🤖 Generated with Claude Code

https://claude.ai/code/session_01RVP6NnbDMAg1iTsMMTfL86

## What Replaces the data-plane AEAD implementation: `yip_crypto::Session::seal`/`open` now use **`ring`'s ChaCha20-Poly1305** keyed by snow's secret `Split()` transport keys, instead of snow's slower RustCrypto transport path. **Same 256-bit ChaCha20-Poly1305 cipher** (CLAUDE.md-conformant), **byte-identical wire**, ~3.3× faster. snow is now used for the handshake only. Lever 2 of 3 for single-core 10-Gbit (cheap FEC ✓ → **fast AEAD** ✓ → AF_XDP/batched I/O). ## Why Post-P+Q, AEAD seal (~2.1 µs) was the dominant single-core per-packet cost. A probe on the target VPS (Ryzen 9 3900X, 1 core, AVX2+AES-NI) showed `openssl` does asm ChaCha20-Poly1305 at ~0.73 µs — a ~3× *implementation* gap within the same cipher. So this is purely a faster impl: no cipher change, no security-model change, handshake untouched. (Post-quantum is a separate *handshake*-layer milestone; symmetric ChaCha20 is already quantum-safe.) ## How (A2, chosen by a spike) A spike (Task 1) proved that `ring` ChaCha20-Poly1305 — using snow's extracted `dangerously_get_raw_split()` keys + the Noise nonce (`[0,0,0,0] ++ counter.to_le_bytes()`, empty AAD) — is **byte-for-byte identical** to snow's `write_message`, and ~4× faster, so it's wire-compatible with existing nodes. - `crates/yip-crypto/src/lib.rs` — `Session` holds two directional `ring::aead::LessSafeKey`s; `into_session` extracts the secret Split() keys and **role-maps** them (`is_initiator`: k0=initiator-send/responder-recv). `seal`/`open` use ring. Added no-alloc `seal_into`/`open_into`. - `crates/yip-crypto/Cargo.toml` — add `ring`; snow gains `risky-raw-split`. - `bin/yipd/src/dataplane.rs` — tx hot loop uses `seal_into` + `mem::take` into the retx buffer (2→1 alloc/packet, removes a per-packet clone). **Keys come from the secret `Split()` output — never the channel binding** (the handshake hash isn't secret). Nonce uniqueness is guaranteed by the monotonic per-direction counter; the Noise handshake, replay window, and counter semantics are untouched. ## Results - **`aead_seal_1300`: ~2.1 µs → 0.63 µs (~3.3×).** - A **durable in-crate byte-identity KAT** proves `Session::seal` output == snow's `write_message` for both directions across counters (teeth-verified: a wrong nonce endianness or swapped key mapping makes it fail). `yip-crypto` 18/18, workspace 351/351, clippy clean, `#![forbid(unsafe_code)]` intact (ring's SIMD is internal). - netns end-to-end (real sudo): tunnel, 10%-loss recovery, and **ARQ integrity** (99.4% delivery, 116 retransmits) all pass — a session establishes and passes traffic with the new cipher. Final whole-branch review (opus): **READY TO MERGE** — traced no nonce-reuse path (ARQ regenerates FEC over stored ciphertext, never re-encrypts) and no send/recv key mismatch (guarded by the both-directions KAT). ## Notes - A per-task review caught a missing durable byte-identity KAT (the proof lived only in the throwaway spike); it was added + teeth-verified before merge. The throwaway spike + its dev-deps were then removed. - Minor (documented): `seal_buf` is moved into the retx buffer on most packets, so it isn't reused across packets — still a net 2→1 alloc. ## Design docs - Spec: `docs/superpowers/specs/2026-07-11-throughput-fast-aead-design.md` - Plan: `docs/superpowers/plans/2026-07-11-throughput-fast-aead.md` 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01RVP6NnbDMAg1iTsMMTfL86
Sign in to join this conversation.
No description provided.