Skip to content

feat: RS erasure-coded handshake chunking for PQ key exchange#30

Merged
disentangle-network merged 5 commits intomasterfrom
feat/rs-chunked-handshake
Mar 8, 2026
Merged

feat: RS erasure-coded handshake chunking for PQ key exchange#30
disentangle-network merged 5 commits intomasterfrom
feat/rs-chunked-handshake

Conversation

@disentangle-network
Copy link
Owner

Summary

  • Adds Reed-Solomon erasure coding for oversized ML-DSA-87 post-quantum handshake messages (~9KB), splitting them into small UDP chunks (<=1200 bytes each) that fit within IPv6 minimum MTU
  • Implements HandshakeIXPSK0Chunked message subtype with 8-byte chunk header for reassembly metadata
  • RS encode/decode with dynamic data shard calculation (k = ceil(payload/1200)) and 3 parity shards, enabling recovery from up to 3 lost chunks
  • Reassembly buffer manager with 256-session limit, 5-second expiry, and duplicate chunk handling
  • Backward compatible: messages <= 1200 bytes skip chunking entirely, non-PQ handshakes are unaffected

Architecture

The chunking layer sits between Noise (untouched) and UDP:

Noise IX message (~9KB) -> rsEncode (k+3 chunks) -> UDP send per chunk
UDP recv per chunk -> ReassemblyManager -> rsDecode -> Noise IX message

Key files:

  • header/header.go: HandshakeIXPSK0Chunked subtype, ChunkHeader struct
  • rs_chunking.go: rsEncode, rsDecode, needsChunking, send helpers
  • rs_reassembly.go: ReassemblyManager, HandleChunk
  • handshake_manager.go: Integration in HandleIncoming and handleOutbound
  • handshake_ix.go: Chunked send in ixHandshakeStage1 (responder path)

Test plan

  • Unit tests: RS encode/decode round-trip, missing shard recovery, various payload sizes, small message rejection
  • Reassembly tests: basic reassembly, missing shards, duplicate chunks, multiple concurrent sessions, buffer expiry, buffer limit, too-short packets
  • PQ e2e test: TestGoodHandshakePQ verifies full chunked handshake completes and bidirectional tunnel works
  • Non-PQ e2e tests: all existing tests pass (backward compatibility)
  • Quality gates: go build, go vet, full test suite

Closes #28

privsim added 5 commits March 7, 2026 22:39
Add RS erasure-coded chunk header types for oversized PQ handshakes.
The 8-byte ChunkHeader carries handshake_id, noise message number,
chunk index, total chunks, and data shard count for reconstruction.
Add Reed-Solomon encoding for oversized handshake messages (PQ
handshakes ~9KB). Messages exceeding 1200 bytes are automatically
split into k+m chunks where k=ceil(payload/1200) and m=3 parity.
Any k of k+m chunks arriving suffices for reconstruction.

Send paths modified: handleOutbound (initiator), ixHandshakeStage1
(responder direct + relay), and ErrAlreadySeen cached resend.
Non-PQ handshakes below threshold bypass chunking entirely.
Add ReassemblyManager for reconstructing chunked handshake messages.
Chunks are buffered by (handshakeID, noiseMsgNum) key and RS-decoded
when k shards arrive. Buffers are bounded (256 max) and expired
(5s timeout) for DoS mitigation. HandleIncoming dispatches chunked
packets to reassembly and re-injects completed messages.
RS encode now prepends a 4-byte big-endian length prefix before
splitting into shards, allowing the decoder to strip RS padding
that was corrupting protobuf unmarshal. Updated all unit tests to
account for the +4 byte prefix in data shard count calculations.
Rewrote TestGoodHandshakePQ to use router-based assertTunnel
approach since chunked handshakes produce multiple UDP packets.

All unit tests, reassembly tests, PQ e2e test, and non-PQ e2e
tests pass -- backward compatibility confirmed.
Use assert.LessOrEqual instead of assert.True for comparison,
and assert.Empty instead of assert.Len(0) per golangci-lint
testifylint rules.
@codecov
Copy link

codecov bot commented Mar 8, 2026

Codecov Report

❌ Patch coverage is 49.83165% with 149 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
handshake_ix.go 0.00% 53 Missing ⚠️
rs_chunking.go 55.43% 31 Missing and 10 partials ⚠️
handshake_manager.go 2.85% 34 Missing ⚠️
rs_reassembly.go 76.92% 16 Missing and 5 partials ⚠️

📢 Thoughts on this report? Let us know!

@disentangle-network disentangle-network merged commit c8bad89 into master Mar 8, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RS-chunked handshake transport for PQ key material

2 participants