Overview
Quantum-resistant tunnels add an additional layer of security to WireGuard by negotiating a pre-shared key (PSK) using quantum-safe KEMs. This PSK is mixed into WireGuard’s cryptographic handshake, ensuring that even if quantum computers break the elliptic curve cryptography in the future, past traffic remains secure.Key Features
- Post-Quantum KEMs: ML-KEM-1024 (NIST standardized) and HQC-256 for hybrid security
- Ephemeral Peers: Short-lived peers with unique PSKs for each tunnel session
- Multihop Support: Independent PSKs for entry and exit peers in multihop configurations
- Automatic Negotiation: Transparent PSK exchange over the tunnel before full activation
Code References
- Ephemeral peer negotiation:
talpid-wireguard/src/ephemeral.rs - KEM client implementation:
talpid-tunnel-config-client/src/lib.rs - ML-KEM implementation:
talpid-tunnel-config-client/src/ml_kem.rs - HQC implementation:
talpid-tunnel-config-client/src/hqc.rs - Protocol definition:
talpid-tunnel-config-client/proto/ephemeralpeer.proto
Cryptographic Primitives
ML-KEM-1024 (FIPS 203)
Algorithm: Module-Lattice-Based Key-Encapsulation Mechanism Standardization: NIST FIPS 203 (formerly Kyber) Implementation (ml_kem.rs):
- Provides 256-bit post-quantum security
- Encapsulation key: 1568 bytes
- Ciphertext: 1568 bytes
- Shared secret: 32 bytes
- NIST standardized (published August 2024)
- Fast performance with small keys
- No practical benefit to using lower security levels
HQC-256
Algorithm: Hamming Quasi-Cyclic Implementation (hqc.rs):
- Encapsulation key: 7245 bytes (larger than ML-KEM)
- Ciphertext: 13909 bytes
- Shared secret: 64 bytes (hashed to 32)
- Code-based cryptography (different mathematical foundation than ML-KEM)
- Provides defense-in-depth through algorithm diversity
- NIST Round 4 candidate
PSK Derivation Protocol
KEM Combination via XOR
The final WireGuard PSK is derived by XORing the shared secrets from both KEMs (lib.rs:289-294):
- If either B or C is secret, A = B ⊕ C remains secret
- Both B and C must be compromised to compute any bit in A
- All involved KEMs must be broken before the PSK is revealed
- WireGuard’s HKDF uniformly distributes entropy regardless of input distribution
ephemeralpeer.proto:103-119):
The PSK to be used in WireGuard’s preshared-key field is computed by XORing the resulting shared secrets of all the KEM algorithms. All currently supported and planned to be supported algorithms output 32 bytes, so this is trivial. Since the PSK provided to WireGuard is directly fed into a HKDF, it is not important that the entropy in the PSK is uniformly distributed. The actual keys used for encrypting the data channel will have uniformly distributed entropy anyway, thanks to the HKDF. Mixing with XOR (A = B ^ C) is fine since nothing about A is revealed even if one of B or C is known. Both B and C must be known to compute any bit in A.
Secret Zeroization
Shared secrets are zeroized immediately after use (lib.rs:194-213):
ml_kem.rs:31-35):
Always inline in order to try to avoid potential copies of shared_secret to multiple places on the stack. This is almost pointless as with optimization all bets are off regarding where the shared secrets will end up in memory. In the future we can try to do better, by cleaning the stack. But this is not trivial.
Ephemeral Peer Negotiation
Protocol Overview
Quantum-resistant tunnels use ephemeral peers to avoid breaking existing tunnels during PSK negotiation:- Normal Peer Connects: Client establishes tunnel with long-lived credentials
- Generate Ephemeral Keys: Client generates new WireGuard keypair and KEM keypairs
- Request Exchange: Client sends ephemeral public keys to server over tunnel
- Server Response: Server encapsulates secrets to client’s KEM public keys
- Derive PSK: Client decapsulates ciphertexts and derives PSK via XOR
- Switch to Ephemeral: Client reconfigures tunnel with ephemeral key + PSK
gRPC Service Definition
The ephemeral peer service (ephemeralpeer.proto) defines:
Client Implementation
The negotiation client (lib.rs:113-134):
lib.rs:268-287):
Service Configuration
Port: 1337 (CONFIG_SERVICE_PORT) Connection (lib.rs:296-317):
Timeout Configuration
Timeout increases with retry attempts (ephemeral.rs:21-23):
ephemeral.rs:275-279):
- Attempt 0: 8 seconds
- Attempt 1: 16 seconds
- Attempt 2: 32 seconds
- Attempt 3+: 48 seconds (capped)
Integration with WireGuard
Trigger Conditions
Ephemeral peer negotiation is triggered when (lib.rs:283, ephemeral.rs:100-108):
Traffic Restrictions During Negotiation
During ephemeral peer negotiation, tunnel traffic is restricted (lib.rs:603-626):
lib.rs:628-631).
Configuration Update
After deriving the PSK, the tunnel configuration is updated (ephemeral.rs:162-182):
- Stopping obfuscation (if active)
- Restarting obfuscation with new config
- Calling
tunnel.set_config()to apply new WireGuard parameters
Multihop Quantum-Resistant Tunnels
Dual PSK Negotiation
In multihop mode, two separate PSKs are negotiated (ephemeral.rs:126-160):
- Exit Peer PSK: Negotiated first using exit relay’s config service
- Entry Peer PSK: Negotiated second using entry relay’s config service
Negotiation Sequence
Security Properties
Multihop + Quantum Resistance provides:- Two Independent PSKs: Entry and exit peers each have unique quantum-resistant PSKs
- One Ephemeral Keypair: Same ephemeral WireGuard key used with both peers
- Nested Encryption: Traffic is encrypted twice:
- Inner layer: Client ↔ Exit (with PSK₁)
- Outer layer: Client ↔ Entry (with PSK₂)
- Attacker must break both quantum-resistant PSKs to decrypt traffic
- Even if one relay is compromised, the other PSK protects the tunnel
- Forward secrecy is maintained through ephemeral WireGuard keys
Windows-Specific Implementation
MTU Workaround
Windows requires a temporary MTU reduction during ephemeral peer negotiation (ephemeral.rs:26-60):
Performance Characteristics
Key Generation Timing
Logged during negotiation (lib.rs:146-149):
- ML-KEM-1024 keypair generation: <1ms
- HQC-256 keypair generation: ~5ms
- Total: ~5-10ms
Network Overhead
Request Size:- WireGuard public keys: 2 × 32 bytes = 64 bytes
- ML-KEM-1024 encapsulation key: 1568 bytes
- HQC-256 encapsulation key: 7245 bytes
- Protobuf overhead: ~100 bytes
- Total: ~9KB request
- ML-KEM-1024 ciphertext: 1568 bytes
- HQC-256 ciphertext: 13909 bytes
- DAITA configuration: ~500 bytes (if enabled)
- Protobuf overhead: ~100 bytes
- Total: ~16KB response
Error Handling
Ephemeral Peer Errors
Timeout Handling
Ciphertext Validation
Testing Example
The repository includes a test example (examples/psk-exchange.rs):
Related Documentation
- WireGuard Implementation - Core tunnel implementation
- Obfuscation Protocols - Obfuscation layer that wraps quantum-resistant tunnels
- Protocol Specification:
talpid-tunnel-config-client/proto/ephemeralpeer.proto