Rename the entire workspace:
- Crate packages: quicnprotochat-{core,proto,server,client,gui,p2p,mobile} -> quicproquo-*
- Binary names: quicnprotochat -> qpq, quicnprotochat-server -> qpq-server,
quicnprotochat-gui -> qpq-gui
- Default files: *-state.bin -> qpq-state.bin, *-server.toml -> qpq-server.toml,
*.db -> qpq.db
- Environment variable prefix: QUICNPROTOCHAT_* -> QPQ_*
- App identifier: chat.quicnproto.gui -> chat.quicproquo.gui
- Proto package: quicnprotochat.bench -> quicproquo.bench
- All documentation, Docker, CI, and script references updated
HKDF domain-separation strings and P2P ALPN remain unchanged for
backward compatibility with existing encrypted state and wire protocol.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6.9 KiB
Introduction
quicproquo is a research-oriented, end-to-end encrypted group messaging system written in Rust. It layers the Messaging Layer Security protocol (MLS, RFC 9420) on top of QUIC + TLS 1.3 transport (via quinn and rustls), with all service RPCs and wire messages framed using Cap'n Proto. The project exists to explore how modern transport encryption (QUIC), a formally specified group key agreement protocol (MLS), and a zero-copy serialisation format (Cap'n Proto) compose in practice -- and to provide a readable, auditable reference implementation for security researchers, protocol designers, and Rust developers who want to study or extend the design.
Protocol stack
┌─────────────────────────────────────────────┐
│ Application / MLS ciphertext │ <- group key ratchet (RFC 9420)
├─────────────────────────────────────────────┤
│ Cap'n Proto RPC │ <- typed, schema-versioned framing
├─────────────────────────────────────────────┤
│ QUIC + TLS 1.3 (quinn/rustls) │ <- mutual auth + transport secrecy
└─────────────────────────────────────────────┘
Each layer addresses a distinct concern:
-
QUIC + TLS 1.3 provides authenticated, confidential transport with 0-RTT connection establishment and multiplexed streams. The server presents a TLS 1.3 certificate (self-signed by default); the client verifies it against a local trust anchor. ALPN negotiation uses the token
b"capnp". -
Cap'n Proto RPC defines the wire schema for all service operations (KeyPackage upload/fetch, message enqueue/fetch, health probes). Schemas live in
schemas/*.capnpand are compiled to Rust at build time. Because Cap'n Proto uses a pointer-based layout, messages can be read without an unpacking step -- though quicproquo currently uses the unpacked wire format for simplicity. -
MLS (RFC 9420) provides the group key agreement layer. Each participant holds an Ed25519 identity keypair and generates single-use HPKE KeyPackages. The MLS epoch ratchet delivers forward secrecy and post-compromise security: compromising a member's state at epoch n does not reveal plaintext from epochs < n (forward secrecy) or > n+1 (post-compromise security, once the compromised member updates).
Security properties
| Property | Mechanism |
|---|---|
| Transport confidentiality | TLS 1.3 over QUIC (rustls with TLS13 only) |
| Transport authentication | TLS 1.3 server certificate (self-signed, SANs: localhost, 127.0.0.1, ::1) |
| Group key agreement | MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 |
| Post-compromise security (PCS) | MLS epoch ratchet -- each Commit advances the key schedule |
| Identity | Ed25519 (ed25519-dalek); public key used as MLS BasicCredential |
| Framing | Cap'n Proto (unpacked wire format, schema-versioned) |
For a deeper discussion of the cryptographic guarantees, threat model, and known gaps, see:
Who is this for?
Security researchers studying how MLS composes with QUIC transport and Cap'n Proto framing. The codebase is intentionally small (four crates, ~2 500 lines of non-generated Rust) so that every cryptographic boundary is auditable.
Protocol designers evaluating MLS deployment patterns. quicproquo implements a concrete Authentication Service (AS) and Delivery Service (DS) pair, demonstrating single-use KeyPackage lifecycle, Welcome routing, and epoch advancement in a live system.
Rust developers looking for a working example of:
quinn+rustlsserver/client setup with self-signed certificatescapnp-rpcover QUIC bidirectional streams (including the!Send/LocalSetconstraint)openmlsgroup creation, member addition, and application message encryptionzeroize-on-drop key material handling
Quick links
| Section | What you will find |
|---|---|
| Comparison with Classical Protocols | Why quicproquo? IRC+SSL, XMPP, Telegram vs. our design |
| Prerequisites | Toolchain and system dependencies |
| Building from Source | cargo build, Cap'n Proto codegen, troubleshooting |
| Running the Server | Server startup, configuration, TLS cert generation |
| Running the Client | All CLI subcommands with examples |
| Docker Deployment | docker compose up, multi-stage build |
| Demo Walkthrough | Step-by-step Alice-and-Bob narrative with sequence diagram |
| Architecture Overview | Crate boundaries, service architecture, data flow |
| Protocol Layers | Deep dives into QUIC/TLS, Cap'n Proto, MLS, Hybrid KEM |
| Wire Format Reference | Cap'n Proto schema documentation |
| Cryptography | Identity keys, key lifecycle, forward secrecy, PCS, threat model |
| Design Rationale | ADRs and protocol design decisions |
| Roadmap | Milestone tracker and future research directions |
Current status
quicproquo is a proof of concept. It has not been audited by a third party.
Known limitations:
- The server uses a self-signed TLS certificate by default. No certificate pinning or CA-based server identity is enforced.
- MLS credentials use
CredentialType::Basic(raw public key). A production system would bind credentials to a certificate authority or use X.509 certificates. - The Delivery Service performs no authentication of the
recipientKeyfield -- anyone who knows a recipient's public key can enqueue messages for them. Access control is a future milestone. - The HPKE init private key generated during
register-stateis held in-process memory (or on-disk via the key store). If the process exits before the corresponding Welcome is consumed,joinwill fail because the private key is lost.
Multi-party groups (N > 2) are supported (milestone M5): Commit fan-out, send --all, and epoch sync work for all members.
For the full milestone tracker, see Milestones.
License
quicproquo is released under the MIT license. See LICENSE in the repository root.