{"id":51578778,"url":"https://github.com/systemslibrarian/crypto-lab-pq-tls-handshake","last_synced_at":"2026-07-11T03:32:25.561Z","repository":{"id":367056507,"uuid":"1215256049","full_name":"systemslibrarian/crypto-lab-pq-tls-handshake","owner":"systemslibrarian","description":"Browser-based TLS 1.3 handshake simulation using the X25519MLKEM768 hybrid post-quantum key exchange (codepoint 0x11EC) per draft-ietf-tls-ecdhe-mlkem-04. Byte-level framing, full key schedule, side-by-side vs. classical X25519.","archived":false,"fork":false,"pushed_at":"2026-06-24T10:13:09.000Z","size":95,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-24T12:08:39.757Z","etag":null,"topics":["crypto-lab","cryptography","hkdf","hybrid-key-exchange","ietf-draft","key-schedule","kyber","ml-kem","ml-kem-768","noble-curves","noble-post-quantum","post-quantum-cryptography","pq-migration","rfc-8446","tls-1-3","tls-handshake","x25519","x25519mlkem768"],"latest_commit_sha":null,"homepage":"https://systemslibrarian.github.io/crypto-lab-pq-tls-handshake/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/systemslibrarian.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-19T17:24:18.000Z","updated_at":"2026-06-24T10:13:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/systemslibrarian/crypto-lab-pq-tls-handshake","commit_stats":null,"previous_names":["systemslibrarian/crypto-lab-pq-tls-handshake"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/systemslibrarian/crypto-lab-pq-tls-handshake","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fcrypto-lab-pq-tls-handshake","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fcrypto-lab-pq-tls-handshake/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fcrypto-lab-pq-tls-handshake/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fcrypto-lab-pq-tls-handshake/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/systemslibrarian","download_url":"https://codeload.github.com/systemslibrarian/crypto-lab-pq-tls-handshake/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fcrypto-lab-pq-tls-handshake/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35350133,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-11T02:00:05.354Z","response_time":104,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crypto-lab","cryptography","hkdf","hybrid-key-exchange","ietf-draft","key-schedule","kyber","ml-kem","ml-kem-768","noble-curves","noble-post-quantum","post-quantum-cryptography","pq-migration","rfc-8446","tls-1-3","tls-handshake","x25519","x25519mlkem768"],"created_at":"2026-07-11T03:32:25.476Z","updated_at":"2026-07-11T03:32:25.545Z","avatar_url":"https://github.com/systemslibrarian.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# crypto-lab-pq-tls-handshake\n\n## What It Is\n\nBrowser-based simulation of the TLS 1.3 handshake using the X25519MLKEM768 hybrid post-quantum key exchange per draft-ietf-tls-ecdhe-mlkem-04 (February 2026, named group codepoint 0x11EC).\n\nThis project demonstrates both sides of a TLS 1.3 handshake entirely in-browser (no backend server) using the hybrid key exchange `X25519MLKEM768`:\n\n- Client key share construction:\n  - `X25519_pub (32)` + `ML-KEM-768_pub (1184)` = `1216` bytes\n- Server key share construction:\n  - `X25519_pub (32)` + `ML-KEM-768_ciphertext (1088)` = `1120` bytes\n- Hybrid secret:\n  - `X25519_shared (32)` + `ML-KEM_shared (32)` = `64` bytes\n\nThe hybrid shared secret is fed into the standard TLS 1.3 key schedule (RFC 8446 Section 7.1) via `HKDF-Extract` and `HKDF-Expand-Label` exactly as TLS expects for `(EC)DHE` input.\n\nEverything shown is real, not mocked:\n\n- The **wire-format inspector** dumps the actual serialized `ClientHello`; every byte offset and length (including the `0x11EC` group position) is computed from the real message, not hardcoded.\n- The **classical X25519 comparison** is serialized through the exact same encoder, so the size difference is genuinely measured rather than asserted.\n- The **compute cost** is timed live in your browser with `performance.now()` over real keygen / encapsulation / decapsulation — reported as the minimum across samples. (The dominant real-world post-quantum cost is the extra bytes on the wire — ~1.1 KB added to the `ClientHello` alone, ~2.3 KB across both hellos — not these sub-millisecond computations, and the UI says so.)\n- All randomness comes from `crypto.getRandomValues` — a CI gate fails the build if `Math.random` ever appears in `src/`.\n\n## When to Use It\n\nUse this demo when you want to:\n\n- Understand what modern browsers and CDNs are negotiating on real HTTPS connections today\n- Teach hybrid PQ migration strategy for TLS 1.3 deployments\n- Inspect byte-level handshake framing and the `0x11EC` group on the wire\n- Study why TLS 1.3 key schedule logic does not need protocol changes for hybrid shared secrets\n- Compare classical and hybrid handshake size/latency behavior in a single interactive tool\n- Do NOT use this for production TLS — this is an educational simulation, not a hardened TLS stack. For production, use established libraries and runtimes.\n\n## Live Demo\n\n**[systemslibrarian.github.io/crypto-lab-pq-tls-handshake](https://systemslibrarian.github.io/crypto-lab-pq-tls-handshake/)**\n\nThe demo runs both client and server sides of an X25519MLKEM768 TLS 1.3 handshake in the browser. A wire-format inspector dumps the real serialized `ClientHello` with every byte offset and length (including the `0x11EC` group position), a classical X25519 comparison serialized through the same encoder shows the measured size difference, and live `performance.now()` timing reports real keygen / encapsulation / decapsulation cost. The hybrid shared secret feeds the standard RFC 8446 key schedule unchanged, illustrating why TLS 1.3 needs no protocol changes to adopt hybrid PQC.\n\n## What Can Go Wrong\n\n- **ClientHello fragmentation**: 1216-byte key-share payloads can push handshake messages near MTU boundaries and trigger fragmentation-sensitive middleboxes.\n- **Implementation side-channels**: educational code in JavaScript/TypeScript is not constant-time and is not suitable for protecting long-term secrets.\n- **Downgrade and interoperability pitfalls**: mismatched group support, extension handling, or middlebox tampering can force non-hybrid paths.\n- **Future cryptanalytic surprises**: hybrid protects if at least one primitive survives, but assumptions still need continuous review and patching.\n- **Slow-link latency amplification**: larger hello messages can increase handshake latency more noticeably on constrained or high-loss networks.\n\n## Real-World Usage\n\n- `X25519MLKEM768` (`0x11EC`) is specified in `draft-ietf-tls-ecdhe-mlkem-04` and replaces early deployment identifiers such as `X25519Kyber768Draft00` (`0x6399`, deprecated).\n- As of mid-September 2025, Cloudflare reported approximately 43% of human-generated HTTPS connections using hybrid post-quantum key exchange.\n- Chrome enabled hybrid by default in M124, and support also exists in Firefox, Edge, Brave, and Opera.\n- This makes hybrid PQ TLS one of the most broadly deployed post-quantum cryptographic mechanisms in active internet use.\n\n## How to Run Locally\n\n```bash\ngit clone https://github.com/systemslibrarian/crypto-lab-pq-tls-handshake\ncd crypto-lab-pq-tls-handshake\nnpm install\nnpm run dev\n```\n\n## Related Demos\n- [crypto-lab-hybrid-wire](https://systemslibrarian.github.io/crypto-lab-hybrid-wire/) — X25519 + ML-KEM-768 with HKDF and AES-256-GCM, the same hybrid handshake outside TLS framing.\n- [crypto-lab-hybrid-guide](https://systemslibrarian.github.io/crypto-lab-hybrid-guide/) — KEM combiners (X-Wing) and how classical and PQ shared secrets are safely mixed.\n- [crypto-lab-kyber-vault](https://systemslibrarian.github.io/crypto-lab-kyber-vault/) — ML-KEM (FIPS 203) on its own, the PQ half of this handshake.\n- [crypto-lab-key-exchange](https://systemslibrarian.github.io/crypto-lab-key-exchange/) — Diffie-Hellman, ECDH, X25519, and ML-KEM key exchange fundamentals.\n- [crypto-lab-pq-rotation](https://systemslibrarian.github.io/crypto-lab-pq-rotation/) — the operational migration plan that rolls hybrid TLS into production.\n\n## Verification\n\n```bash\nnpm run typecheck   # tsc strict, no emit\nnpm test            # crypto + handshake gates (RFC 8448 vectors, 100x round-trip, sizes, source scan)\nnpm run build       # type-check + production bundle\n```\n\n`npm test` runs every gate in `scripts/phase-checks.ts`, including the RFC 8448\n`HKDF-Expand-Label` test vector, a 100-iteration client/server agreement loop,\nexact key-share sizes (1216 / 1120 / 64 bytes), a live compute measurement, and\na source scan that rejects `Math.random`. The same gates run in CI\n(`.github/workflows/deploy.yml`) and **must pass before GitHub Pages deploys**.\n\n## License\n\n[MIT](LICENSE) © Paul Clark (systemslibrarian)\n\n---\n\n*One of 120+ browser demos in the [Crypto Lab](https://crypto-lab.systemslibrarian.dev/) suite.*\n\n*\"So whether you eat or drink or whatever you do, do it all for the glory of God.\" — 1 Corinthians 10:31*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsystemslibrarian%2Fcrypto-lab-pq-tls-handshake","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsystemslibrarian%2Fcrypto-lab-pq-tls-handshake","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsystemslibrarian%2Fcrypto-lab-pq-tls-handshake/lists"}