Hybrid X25519 + ML-KEM-1024 handshake and full PQ integration#6
Merged
disentangle-network merged 2 commits intofeature/pq-certificatesfrom Feb 19, 2026
Merged
Conversation
added 2 commits
February 19, 2026 06:06
Implement NIST-recommended hybrid key exchange for the Noise IX handshake.
When Curve_PQ is selected, the handshake uses X25519 DH for classical
security and layers ML-KEM-1024 KEM on top for post-quantum security.
Both shared secrets are mixed via HKDF-SHA256 into the final symmetric
keys. Breaking either primitive alone is insufficient.
Handshake flow for Curve_PQ:
Stage 0 (initiator): generate ephemeral ML-KEM-1024 keypair, include
KemPublicKey in NebulaHandshakeDetails
Stage 1 (responder): encapsulate to initiator's KEM pubkey, include
KemCiphertext in response, mix KEM shared secret into Noise-derived
dKey/eKey via HKDF
Stage 2 (initiator): decapsulate KEM ciphertext, mix shared secret
into dKey/eKey via same HKDF
Changes:
- connection_state.go: PQ KEM state fields, X25519 ephemeral keypair for
Noise DH (cert's ML-KEM key is for KEM exchange, not DH)
- handshake_ix.go: KEM exchange in all 3 stages, pqMixCipherStates
helper, PQ-aware cert pubkey validation
- nebula.proto/pb.go: KemPublicKey and KemCiphertext fields in
NebulaHandshakeDetails
- noiseutil/pq.go: PQKEMKeypair, PQKEMEncapsulate, PQKEMDecapsulate,
HybridMixKeys
- noiseutil/pq_test.go: 7 tests for KEM roundtrip, key mixing, full
handshake simulation
Security properties:
- AES-256-GCM transport (unchanged, already PQ-safe)
- X25519 DH provides defense-in-depth against KEM failures
- ML-KEM-1024 KEM provides FIPS 203 post-quantum key exchange
- ML-DSA-87 certificate signatures (Phase 1) authenticate identities
- HKDF-SHA256 combiner per NIST SP 800-56C rev2
Complete the PQ integration across the full Nebula stack: CLI (nebula-cert): - ca.go: -curve PQ generates ML-DSA-87 CA keypair (V2 only) - sign.go: PQ host certs use ML-KEM-1024 key agreement keys - keygen.go: -curve PQ generates ML-KEM-1024 keypair PKI integration: - pki.go: PQ certs marshal with full public key (not stripped) because MarshalForHandshakes assumes pubkey == Noise PeerStatic - cert.go: UnmarshalCertificateFromBytes for PQ cert reconstruction - cert_v2.go: fix VerifyPrivateKey to use Unpack for ML-KEM-1024 Handshake fixes: - handshake_ix.go: PQ path uses direct unmarshal instead of Recombine (cert pubkey is ML-KEM, not the X25519 PeerStatic) - Skip pubkey==PeerStatic check for PQ (different key types) Test infrastructure: - cert_test/cert.go: PQ cases for NewTestCaCert and NewTestCert - e2e/helpers_test.go: derive curve from CA cert (not hardcoded) - e2e/handshakes_test.go: TestGoodHandshakePQ -- full tunnel test TestGoodHandshakePQ proves: PQ CA signs host cert, two nodes establish tunnel via hybrid X25519+ML-KEM-1024 handshake, bidirectional encrypted data transfer works. 0.41s handshake time. Zero regressions in classical handshake tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Complete post-quantum integration across the full Nebula stack. Builds on #5 (PQ certificates).
Hybrid handshake (NIST SP 800-56C)
Handshake flow for Curve_PQ
nebula-cert CLI
nebula-cert ca -curve PQgenerates ML-DSA-87 CA (V2 only)nebula-cert signwith PQ CA generates ML-KEM-1024 host certsnebula-cert keygen -curve PQgenerates ML-KEM-1024 keypairsPKI integration
E2E test
Security stack
Test plan