feat: add post-quantum hybrid KEM + SQLCipher persistence
Feature 1 — Post-Quantum Hybrid KEM (X25519 + ML-KEM-768): - Create hybrid_kem.rs with keygen, encrypt, decrypt + 11 unit tests - Wire format: version(1) | x25519_eph_pk(32) | mlkem_ct(1088) | nonce(12) | ct - Add uploadHybridKey/fetchHybridKey RPCs to node.capnp schema - Server: hybrid key storage in FileBackedStore + RPC handlers - Client: hybrid keypair in StoredState, auto-wrap/unwrap in send/recv/invite/join - demo-group runs full hybrid PQ envelope round-trip Feature 2 — SQLCipher Persistence: - Extract Store trait from FileBackedStore API - Create SqlStore (rusqlite + bundled-sqlcipher) with encrypted-at-rest SQLite - Schema: key_packages, deliveries, hybrid_keys tables with indexes - Server CLI: --store-backend=sql, --db-path, --db-key flags - 5 unit tests for SqlStore (FIFO, round-trip, upsert, channel isolation) Also includes: client lib.rs refactor, auth config, TOML config file support, mdBook documentation, and various cleanups by user. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
194
docs/src/roadmap/milestones.md
Normal file
194
docs/src/roadmap/milestones.md
Normal file
@@ -0,0 +1,194 @@
|
||||
# Milestone Tracker
|
||||
|
||||
This page tracks the project milestones for quicnprotochat, from initial transport
|
||||
layer through post-quantum cryptography. Each milestone produces production-ready,
|
||||
tested, deployable code -- see [Coding Standards](../contributing/coding-standards.md)
|
||||
for what that means in practice.
|
||||
|
||||
---
|
||||
|
||||
## Milestone Summary
|
||||
|
||||
| # | Name | Status | What it adds |
|
||||
|---|------|--------|-------------|
|
||||
| M1 | QUIC/TLS Transport | **Complete** | QUIC + TLS 1.3 endpoint, length-prefixed framing, Ping/Pong |
|
||||
| M2 | Authentication Service | **Complete** | Ed25519 identity, KeyPackage generation, AS upload/fetch |
|
||||
| M3 | Delivery Service + MLS Groups | **Complete** | DS relay, GroupMember create/join/add/send/recv |
|
||||
| M4 | Group CLI Subcommands | **Next** | Persistent CLI (create-group, invite, join, send, recv); `demo-group` already available |
|
||||
| M5 | Multi-party Groups | Planned | N > 2 members, Commit fan-out, Proposal handling |
|
||||
| M6 | Persistence | Planned | SQLite key store, durable group state |
|
||||
| M7 | Post-quantum | Planned | PQ hybrid for MLS/HPKE (X25519 + ML-KEM-768) |
|
||||
|
||||
---
|
||||
|
||||
## M1 -- QUIC/TLS Transport (Complete)
|
||||
|
||||
**Goal:** Two processes establish a QUIC connection over TLS 1.3 and exchange
|
||||
typed Cap'n Proto frames.
|
||||
|
||||
**Deliverables:**
|
||||
|
||||
- `schemas/envelope.capnp`: `Envelope` struct with `MsgType` enum (Ping/Pong at this stage)
|
||||
- `quicnprotochat-proto`: `build.rs` invoking `capnpc`, generated type re-exports,
|
||||
canonical serialisation helpers
|
||||
- `quicnprotochat-core`: static X25519 keypair generation, Noise\_XX initiator and
|
||||
responder, length-prefixed Cap'n Proto frame codec (Tokio `Encoder`/`Decoder`)
|
||||
- `quicnprotochat-server`: QUIC listener with TLS 1.3 (quinn/rustls), Ping to Pong
|
||||
handler, one tokio task per connection
|
||||
- `quicnprotochat-client`: connects over QUIC, sends Ping, receives Pong, exits 0
|
||||
- Integration test: server and client in same test binary using `tokio::spawn`
|
||||
- `docker-compose.yml` running the server
|
||||
|
||||
**Tests:** codec (7 unit tests), keypair (3 unit tests), Noise transport integration.
|
||||
|
||||
**Branch:** `feat/m1-noise-transport`
|
||||
|
||||
---
|
||||
|
||||
## M2 -- Authentication Service (Complete)
|
||||
|
||||
**Goal:** Clients register an Ed25519 identity and publish/fetch MLS KeyPackages
|
||||
via Cap'n Proto RPC.
|
||||
|
||||
**Deliverables:**
|
||||
|
||||
- `schemas/auth.capnp`: `AuthenticationService` interface (`uploadKeyPackage`,
|
||||
`fetchKeyPackage`)
|
||||
- `quicnprotochat-core`: Ed25519 identity keypair generation, MLS KeyPackage
|
||||
generation via `openmls`
|
||||
- `quicnprotochat-server`: AS RPC server with `DashMap` store, atomic consume-on-fetch
|
||||
- `quicnprotochat-client`: `register-state` and `fetch-key` CLI subcommands
|
||||
- Integration test: Alice uploads KeyPackage, Bob fetches it, fingerprints match
|
||||
|
||||
**Tests:** auth\_service.rs integration tests (upload, fetch, consume semantics).
|
||||
|
||||
---
|
||||
|
||||
## M3 -- Delivery Service + MLS Groups (Complete)
|
||||
|
||||
**Goal:** Alice creates a group and adds Bob via MLS Welcome. Both exchange
|
||||
encrypted application messages through the Delivery Service.
|
||||
|
||||
**Deliverables:**
|
||||
|
||||
- Unified `NodeService` on port 7000 combining Authentication Service and Delivery
|
||||
Service into a single Cap'n Proto RPC interface
|
||||
- `GroupMember` struct with full MLS lifecycle: `create_group`, `add_member`,
|
||||
`join_from_welcome`, `send_message`, `receive_message`
|
||||
- DS relay with `enqueue`, `fetch`, and `fetchWait` (long-polling) operations
|
||||
- `demo-group` subcommand exercising the complete Alice/Bob flow in one process
|
||||
- Channel-aware delivery: messages routed by `(channelId, recipientKey)`
|
||||
|
||||
**Tests:** All passing -- codec (5+ tests), keypair (3 tests), group round-trip,
|
||||
group\_id lifecycle, MLS integration.
|
||||
|
||||
**Key design decisions from M3:**
|
||||
|
||||
1. **OpenMlsRustCrypto backend holds the HPKE init key in memory.** The same
|
||||
`GroupMember` instance that generated the KeyPackage must process the
|
||||
corresponding Welcome. If the process exits in between, the init private key
|
||||
is lost. This is by design for M3; persistence comes at M6.
|
||||
|
||||
2. **KeyPackage wire format: raw TLS-encoded bytes.** KeyPackages are serialised
|
||||
using `tls_serialize_detached()` rather than wrapped in `MlsMessageOut`. This
|
||||
avoids an extra layer of indirection and matches what `openmls` expects on the
|
||||
receive side via `KeyPackageIn::tls_deserialize_exact()`.
|
||||
|
||||
3. **openmls 0.5 API gotchas.** Several `openmls` methods changed signatures
|
||||
between 0.4 and 0.5 (e.g., `MlsGroup::new` vs `MlsGroup::new_with_group_id`,
|
||||
`BasicCredential::new` taking `Vec<u8>` directly). These differences are
|
||||
documented inline in `quicnprotochat-core/src/group.rs`.
|
||||
|
||||
**Branch:** `feat/m1-noise-transport`
|
||||
|
||||
---
|
||||
|
||||
## M4 -- Group CLI Subcommands (Next)
|
||||
|
||||
**Goal:** Persistent, composable CLI subcommands for group operations, replacing
|
||||
the monolithic `demo-group` proof-of-concept.
|
||||
|
||||
**Planned deliverables:**
|
||||
|
||||
- `create-group` -- creates a new MLS group, stores state locally
|
||||
- `invite <identity>` -- adds a member by fetching their KeyPackage from the AS
|
||||
- `join` -- processes a Welcome message and joins an existing group
|
||||
- `send <message>` -- encrypts and enqueues an application message
|
||||
- `recv` -- fetches and decrypts pending messages (or long-polls with `fetchWait`)
|
||||
|
||||
The `demo-group` subcommand remains available as a single-command demonstration
|
||||
of the full flow.
|
||||
|
||||
---
|
||||
|
||||
## M5 -- Multi-party Groups (Planned)
|
||||
|
||||
**Goal:** Support groups with N > 2 members, including Commit fan-out and
|
||||
Proposal handling.
|
||||
|
||||
**Planned deliverables:**
|
||||
|
||||
- Commit fan-out through the DS to all group members
|
||||
- Proposal handling (Add, Remove, Update)
|
||||
- Epoch synchronisation across N members
|
||||
- Criterion benchmarks: key generation, encap/decap, group-add latency
|
||||
(10/100/1000 members)
|
||||
|
||||
---
|
||||
|
||||
## M6 -- Persistence (Planned)
|
||||
|
||||
**Goal:** Server survives restart. Client state persists across sessions.
|
||||
|
||||
**Planned deliverables:**
|
||||
|
||||
- `quicnprotochat-server`: SQLite via `sqlx` for AS key store and DS message log,
|
||||
`migrations/` directory
|
||||
- `docker/Dockerfile`: multi-stage build (`rust:bookworm` builder, `debian:bookworm-slim` runtime)
|
||||
- `docker-compose.yml`: server + SQLite volume, healthcheck
|
||||
- Client reconnect with session resume (re-handshake + rejoin group epoch from
|
||||
DS log)
|
||||
|
||||
See [Future Research: SQLCipher](future-research.md#storage--persistence) for
|
||||
encrypted-at-rest options.
|
||||
|
||||
---
|
||||
|
||||
## M7 -- Post-quantum (Planned)
|
||||
|
||||
**Goal:** Replace the MLS crypto backend with a hybrid X25519 + ML-KEM-768 KEM,
|
||||
providing post-quantum confidentiality for all group key material.
|
||||
|
||||
**Planned deliverables:**
|
||||
|
||||
- Custom `OpenMlsCryptoProvider` with hybrid KEM in `quicnprotochat-core`
|
||||
- Hybrid shared secret derivation:
|
||||
|
||||
```
|
||||
SharedSecret = HKDF-SHA256(
|
||||
ikm = X25519_ss || ML-KEM-768_ss,
|
||||
info = "quicnprotochat-hybrid-v1",
|
||||
len = 32
|
||||
)
|
||||
```
|
||||
|
||||
- All M3/M4/M5 tests pass unchanged with the new ciphersuite
|
||||
- Follows the combiner approach from `draft-ietf-tls-hybrid-design`
|
||||
|
||||
The `ml-kem` crate is already vendored in the workspace. See
|
||||
[Hybrid KEM](../protocol-layers/hybrid-kem.md) for the detailed design and
|
||||
[ADR-006: PQ Gap in Noise Transport](../design-rationale/adr-006-pq-gap.md) for
|
||||
the accepted residual risk in the transport layer.
|
||||
|
||||
---
|
||||
|
||||
## Cross-references
|
||||
|
||||
- [Production Readiness WBS](production-readiness.md) -- phased work breakdown
|
||||
for hardening beyond the milestone track
|
||||
- [Auth, Devices, and Tokens](authz-plan.md) -- authentication and authorisation
|
||||
design that cuts across M4--M6
|
||||
- [1:1 Channel Design](dm-channels.md) -- DM channel schema and authz model
|
||||
- [Future Research](future-research.md) -- technology options for M6+ and beyond
|
||||
- [Testing Strategy](../contributing/testing.md) -- how tests are structured
|
||||
across milestones
|
||||
Reference in New Issue
Block a user