Skip to content

Commit ceb101a

Browse files
committed
encryption: the sealed channel — an actual encrypted connection, not a sealed record
This is the POC the session was for and had not delivered. What existed was `envelope`, which seals a RECORD under a password. The job was a CONNECTION between the browser and the server, above TLS, so that the proxy / TLS terminator / remote-desktop layer in front of the server sees ciphertext only. `channel.rs` is that, end to end: handshake: client -> server ephemeral X448 public key (56 bytes) record: counter (8, BE) | ciphertext | Poly1305 tag (16) nonce = direction (1) | zeros (15) | counter (8) aad = direction (1) | counter (8) Server authentication comes from the key agreement, NOT from a signature: the client holds the server's static X448 public key (pinned in the client build), both sides compute X448(ephemeral, static), and only the holder of the static private key derives the same value. A man in the middle can substitute its own key and complete a handshake — and then nothing it forwards opens, in either direction. That is a test, not a claim. The whole Ed25519/Ed448 detour earlier in this session was unnecessary: the DH IS the authentication (Noise NK shape). Directions are separated by key AND nonce, so a record cannot be reflected back at its sender. The per-direction counter is strictly increasing and only committed after the tag verifies, so replays and rewinds are refused and a forged record cannot advance the window to lock out real traffic. x448 comes from the AdaWorldAPI fork of RustCrypto/elliptic-curves — no dalek, and crypto-bigint underneath means no foreign AVX2 intrinsics for the polyfill to have to displace. hkdf_sha384.rs is HMAC-SHA384 + HKDF written directly on the crate's own sha384, deliberately: the `hmac`/`hkdf` crates sit on the digest 0.11 trait generation while this crate's sha2 is 0.10, and dragging a second generation in for forty lines is the tail wagging the dog. It is pinned by RFC 4231 vectors (cases 1, 2 and 6 — case 6 covers the oversized-key branch), not by trust. Measured, release, this box: handshake (both sides) 1.55 ms record 64 B seal+open 1.17 us 52 MiB/s record 4096 B seal+open 8.26 us 473 MiB/s record 65536 B seal+open 122.20 us 512 MiB/s So the per-session cost is one 1.5 ms handshake and the steady state runs at ~500 MiB/s. X448 is the slow part; that is the price of the non-dalek curve. 15 new tests (9 channel, 6 kdf), 40 green in the crate, clippy clean. Not in scope here, and stated rather than hidden: x448's own README says the code has not been audited. And the server process still sees plaintext — this is not zero-knowledge against the operator, and the module doc says so where someone reading the code will find it. Generated by [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mwq1QKpw4zRd6oaGRoJhF2
1 parent 3694a3c commit ceb101a

5 files changed

Lines changed: 879 additions & 7 deletions

File tree

0 commit comments

Comments
 (0)