REALITY.5b: byte-matching ServerHello emission + server key schedule (4588+X25519, round-trip proven) #85
No reviewers
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
femboy/yip!85
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/reality-5b-serverhello-emit"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
REALITY.5b — byte-matching ServerHello emission + server key schedule
Stacked on #83 (REALITY.5a). Base is
feat/reality-5a-dest-flight-capture; review the 5b delta here, merge after #83. PR 2 of 4 for REALITY.5 (#76).The server-side counterpart to REALITY.2's client. Given the
desttemplate captured in 5a, the relay emits a byte-matching ServerHello — structurally identical todest's (cipher, ordered extensions incl. GREASE, chosen group) but keyed on the relay's own ephemeral, so the relay holds the session keys. A passive DPI byte-matches the cleartext ServerHello;dest's realkey_share/randomare per-connection random too, so substituting the relay's own values is indistinguishable.What's here
yip-utls::server::server_key_share— the relay's server-side KEX.Decapsulate) + X25519 DH;server_key_share = ct(1088) ‖ x25519_pub(32),shared = mlkem_ss ‖ x25519_ss— the same combiner order the client uses.Err(UnsupportedGroup)(5d degrades to splice-only; P256/P384 + HelloRetryRequest deferred to #84).yip-utls::server::emit_server_hello— rebuilds the ServerHello verbatim from the capturedServerHelloShape, substituting only a fresh 32-byte random, the client'slegacy_session_idecho, and thekey_shareext body (the relay's own). Derives handshake keys over transcript = ClientHello ‖ ServerHello via REALITY.2'sderive_handshake_keys(reused unchanged).yip-rendezvous::reality—ClientHelloInfo.key_share_mlkem_ekextracted from the group-4588 key_share entry (mlkem_ek(1184) ‖ x25519(32)), fail-closed on a hostile/malformed ClientHello. This is what 5d feeds toemit_server_hello.Correctness gate: the round-trip
The proof is a genuine round-trip (not a tautology): a test client — REALITY.2's own
parse_server_hello+ the client KEX (decapsulate/DH, separate RNGs) +derive_handshake_keys— parses the relay's emitted ServerHello and derives the byte-identicalHandshakeKeys, for both 4588 and X25519. If the combiner order or X25519 direction were wrong, no keys would match. Plus a byte-match test asserting only random/session_id/key_share differ from the template (GREASE and extension order preserved).Scope / non-goals
tls_frontwiring (5d) here — additive, server-side only.5d hand-off notes
…‖ x25519(32)tail), not the standalone0x001dentry. Safe within 5b because yip's own client reuses one ephemeral across both shares; 5d must either thread the 4588-tail x25519 through or assert that invariant. Fails closed (dead session), no security downgrade, if ever violated.server_key_share'srngdrives ML-KEM encapsulation + the X25519 ephemeral; 5d must wire an OS-CSPRNG-backedRandomSource.Tests
server_key_shareshapes/secret-lengths for 4588 + 29; unsupported group + missing ek →Err.emit_server_helloround-trips (4588 + 29) with identical keys; byte-match except substituted fields; u24 body / u16 ext length guards.parse_client_helloextracts the 1184-byte mlkem_ek; wrong-length 4588 entry →None; distinct x25519 in the two entries proveskey_share_x25519stays sourced from0x001d.Final whole-branch review (opus): READY TO MERGE — KEX verified end-to-end, every network-reachable path fail-closed, ServerHello byte-fidelity preserved,
forbid-unsafe/ noas/ no bare#[allow].Pull request closed