3 KiB
3 KiB
Encryption — Phase 1.1
Phase 1.1 status: Fully implemented. ChaCha20-Poly1305 AEAD with X25519 ECDH + HKDF-SHA256 key exchange. Both TCP (control) and UDP (voice) paths are now encrypted. Forward secrecy via ephemeral session keys.
Goal
Replace all plaintext traffic (TCP + UDP) with ChaCha20-Poly1305 AEAD encryption. X25519 ECDH ephemeral key exchange during handshake for forward secrecy.
✅ COMPLETED in Phase 1.1
Key exchange (during HELLO handshake)
- Server generates ephemeral X25519 keypair per session
- Server sends public key in
HELLOpacket - Client generates own ephemeral X25519 keypair
- Both compute shared secret via X25519 ECDH
- Shared secret → HKDF-SHA256 → two keys:
client→serverencryption keyserver→clientencryption key
- Ephemeral keys discarded after session (forward secrecy)
Packet encryption
- Algorithm: ChaCha20-Poly1305 (AEAD)
- 96-bit nonce:
session_id || packet_sequence - 16-byte Poly1305 authentication tag per packet
- Applied to ALL packets on both TCP and UDP
Why ChaCha20-Poly1305 over AES-GCM
- Constant-time on all platforms (no hardware AES requirement)
- Faster in software on ARM (common for mobile — Phase 3)
- Simpler nonce management (no IV collision risk)
Implementation plan
✅ Client (DONE)
client/src/net/crypto.rs— SessionCrypto with ChaCha20-Poly1305client/src/net/voice.rs—build_packet()encrypts voice payloads with c2s_keyclient/src/net/voice.rs—spawn_recv()decrypts incoming voice with s2c_keyclient/src/net/session/session_loop.rs— voice_seq counter for encryption nonces
✅ Gateway (DONE)
gateway/src/proto/crypto.rs— X25519 ECDH, HKDF-SHA256, ChaCha20-Poly1305gateway/src/net/handshake.rs— ephemeral key exchange in HELLO/AUTHgateway/src/net/io.rs— TCP framing with encryption
✅ Voice
client/src/net/voice.rs— encrypted voice packets on UDP (plaintext at rest in voice-node, encrypted on wire)- Voice-node treats packets as opaque bytes (transparent relay)
- End-to-end encryption: client A → encrypted → voice-node → encrypted → client B
Nonce management
Each session has a monotonic sequence counter:
- Start at 0 on session establishment
- Increment per packet (both directions independently)
- Nonce =
session_id (8 bytes) || sequence (4 bytes) - 12-byte nonce fits ChaCha20-Poly1305 standard
Key dependencies
Already in Cargo.toml (workspace):
chacha20poly1305 = "0.10"x25519-dalek = { version = "2", features = ["static_secrets"] }
Need to add:
hkdf = "0.12"for key derivationsha2 = "0.10"(HKDF dependency, likely already transitive)
Testing
- ✅ Unit test: encrypt → decrypt round-trip with known keys (
client/src/net/crypto.rs) - ✅ Unit test: tampered ciphertext fails authentication
- ✅ Unit test: build_packet creates valid encrypted packets
- Manual test: Run client + gateway + voice-node, join voice channel, verify packets encrypted
- Wireshark: Capture UDP traffic, confirm it's not readable plaintext