Remove Noise protocol references from wiki docs and tests

Delete 8 Noise-specific documentation pages (noise-xx.md,
transport-keys.md, adr-001/003/006, framing-codec.md) and update
~30 remaining wiki pages to reflect QUIC+TLS as the sole transport.
Remove obsolete Noise-based integration tests (auth_service.rs,
mls_group.rs). Code-side Noise removal was done in f334ed3.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-22 08:25:23 +01:00
parent f334ed3d43
commit 9fdb37876a
36 changed files with 125 additions and 2201 deletions

View File

@@ -20,8 +20,8 @@ how the crates relate to one another.
▼ ▼
┌────────────────────────┐ ┌────────────────────────┐
│ quicnprotochat-core │ │ quicnprotochat-server │
│ (crypto, Noise, │ │ (QUIC listener, │
MLS, hybrid KEM) │ │ NodeService RPC, │
│ (crypto, MLS, │ │ (QUIC listener, │
│ hybrid KEM) │ │ NodeService RPC, │
│ │ │ storage) │
└──────────┬─────────────┘ └─────────┬──────────────┘
│ │
@@ -42,27 +42,23 @@ serialisation. The server and client crates both depend on core and proto.
## quicnprotochat-core
**Role:** Pure cryptographic logic and transport primitives. No network I/O
(except for the Noise handshake helpers that take an existing `TcpStream`). No
async runtime dependency beyond what Noise transport needs.
**Role:** Pure cryptographic logic. No network I/O. No async runtime
dependency.
### Modules
| Module | Public API | Description |
|---------------|-----------------------------------------------------------------------------|-------------|
| `keypair` | `NoiseKeypair` | Static X25519 keypair for Noise_XX. `StaticSecret` is `ZeroizeOnDrop`. `private_bytes()` returns `Zeroizing<[u8; 32]>`. |
| `identity` | `IdentityKeypair` | Ed25519 signing keypair for MLS credentials. Seed stored as `Zeroizing<[u8; 32]>`. Implements `openmls_traits::Signer`. |
| `noise` | `handshake_initiator`, `handshake_responder`, `NoiseTransport` | Noise_XX_25519_ChaChaPoly_BLAKE2s handshake over TCP. `NoiseTransport` provides `send_frame`/`recv_frame`, envelope helpers, and `into_capnp_io()` bridge. |
| `codec` | `LengthPrefixedCodec`, `NOISE_MAX_MSG` | Tokio `Encoder<Bytes>` + `Decoder`. 4-byte LE length prefix. Max frame 65,535 bytes. |
| `group` | `GroupMember` | MLS group state machine wrapping `openmls::MlsGroup`. Lifecycle: `new` -> `generate_key_package` -> `create_group` / `join_group` -> `send_message` / `receive_message`. |
| `keypackage` | `generate_key_package` | Standalone KeyPackage generation (returns TLS-encoded bytes + SHA-256 fingerprint). |
| `keystore` | `DiskKeyStore`, `StoreCrypto` | `OpenMlsKeyStore` implementation backed by an in-memory `HashMap` with optional bincode flush to disk. `StoreCrypto` couples `RustCrypto` + `DiskKeyStore` into an `OpenMlsCryptoProvider`. |
| `hybrid_kem` | `HybridKeypair`, `HybridPublicKey`, `hybrid_encrypt`, `hybrid_decrypt` | X25519 + ML-KEM-768 hybrid KEM. HKDF-SHA256 key derivation, ChaCha20-Poly1305 AEAD. Versioned envelope wire format. |
| `error` | `CoreError`, `CodecError`, `MAX_PLAINTEXT_LEN` | Unified error types. `CoreError` covers Noise, Codec, Cap'n Proto, MLS, and hybrid KEM failures. |
| `error` | `CoreError`, `MAX_PLAINTEXT_LEN` | Unified error types. `CoreError` covers Cap'n Proto, MLS, and hybrid KEM failures. |
### What this crate does NOT do
- No network I/O beyond the Noise helpers (which take a pre-connected `TcpStream`).
- No network I/O.
- No QUIC or TLS -- that is the server and client crates' concern.
- No async runtime setup (it uses Tokio types internally but does not spawn or
manage a runtime).
@@ -70,10 +66,10 @@ async runtime dependency beyond what Noise transport needs.
### Key dependencies
`snow`, `x25519-dalek`, `ed25519-dalek`, `openmls`, `openmls_rust_crypto`,
`openmls_traits`, `tls_codec`, `ml-kem`, `chacha20poly1305`, `hkdf`, `sha2`,
`zeroize`, `capnp`, `quicnprotochat-proto`, `tokio`, `tokio-util`, `futures`,
`bytes`, `serde`, `bincode`, `serde_json`, `thiserror`.
`ed25519-dalek`, `openmls`, `openmls_rust_crypto`,
`openmls_traits`, `tls_codec`, `ml-kem`, `x25519-dalek`, `chacha20poly1305`,
`hkdf`, `sha2`, `zeroize`, `capnp`, `quicnprotochat-proto`, `tokio`,
`serde`, `bincode`, `serde_json`, `thiserror`.
---
@@ -87,7 +83,7 @@ for the wire format.
| Item | Description |
|---------------------------|-------------|
| `schemas/envelope.capnp` | `Envelope` struct and `MsgType` enum -- top-level wire message for Noise-channel traffic. |
| `schemas/envelope.capnp` | `Envelope` struct and `MsgType` enum -- top-level wire message. |
| `schemas/auth.capnp` | `AuthenticationService` interface -- `uploadKeyPackage`, `fetchKeyPackage`. |
| `schemas/delivery.capnp` | `DeliveryService` interface -- `enqueue`, `fetch`. |
| `schemas/node.capnp` | `NodeService` interface (unified AS+DS) -- all RPC methods plus `Auth` struct. |
@@ -148,7 +144,6 @@ is handled by `spawn_local`.
- No direct crypto operations (it delegates to `quicnprotochat-core` types
for fingerprinting and storage only).
- No MLS processing -- all payloads are opaque byte strings.
- No Noise transport (QUIC/TLS only).
### Key dependencies
@@ -192,7 +187,6 @@ group state to disk.
### What this crate does NOT do
- No server-side logic.
- No Noise transport (QUIC/TLS only for server communication).
- No direct crypto beyond calling `GroupMember` and verifying SHA-256
fingerprints.

View File

@@ -26,24 +26,15 @@ connection lifecycle, and the long-polling `fetchWait` mechanism.
---
## Dual-Key Model
## Identity Key Model
quicnprotochat uses two independent asymmetric key pairs per client, each
serving a distinct role:
Each quicnprotochat client holds a single Ed25519 signing keypair that serves
as its long-term identity:
```text
quicnprotochat Key Model
┌──────────────────────────────────────────────────┐
│ │
│ X25519 static keypair (Noise transport) │
│ ───────────────────────────────────── │
│ - Generated once per node identity │
│ - Used in the Noise_XX handshake (M1 stack) │
│ - Provides mutual authentication + │
│ channel confidentiality at the TCP layer │
│ - Classical only (no PQ protection) │
│ - Managed by NoiseKeypair, zeroize-on-drop │
│ │
│ Ed25519 signing keypair (MLS identity) │
│ ────────────────────────────────────── │
│ - Generated once per user/device │
@@ -55,17 +46,16 @@ serving a distinct role:
└──────────────────────────────────────────────────┘
```
| Property | X25519 (Noise) | Ed25519 (MLS) |
|-------------------|-------------------------------------|--------------------------------------------|
| Curve | Curve25519 (Montgomery) | Ed25519 (Twisted Edwards) |
| Purpose | Transport authentication + secrecy | Identity binding, signing, MLS credentials |
| Crate | `x25519-dalek` | `ed25519-dalek` |
| Zeroize on drop | Yes (`StaticSecret`) | Yes (`Zeroizing<[u8; 32]>`) |
| PQ protection | None (classical X25519) | MLS key schedule uses DHKEM(X25519); hybrid PQ KEM available at envelope level |
| Property | Ed25519 (MLS) |
|-------------------|--------------------------------------------|
| Curve | Ed25519 (Twisted Edwards) |
| Purpose | Identity binding, signing, MLS credentials |
| Crate | `ed25519-dalek` |
| Zeroize on drop | Yes (`Zeroizing<[u8; 32]>`) |
| PQ protection | MLS key schedule uses DHKEM(X25519); hybrid PQ KEM available at envelope level |
For details on the cryptographic properties of each key type, see
[Ed25519 Identity Keys](../cryptography/identity-keys.md) and
[X25519 Transport Keys](../cryptography/transport-keys.md).
For details on the cryptographic properties, see
[Ed25519 Identity Keys](../cryptography/identity-keys.md).
---
@@ -80,14 +70,9 @@ For details on the cryptographic properties of each key type, see
│ │ │ │
│ GroupMember │ │ GroupMember │
│ (MLS state) │ │ (MLS state) │
│ │ │ │
│ NoiseKeypair* │ │ NoiseKeypair* │
│ (X25519, M1) │ │ (X25519, M1) │
└────────┬─────────┘ └────────┬─────────┘
│ │
│ QUIC + TLS 1.3 (quinn/rustls) │
│ ─── or ─── │
│ Noise_XX over TCP (snow, M1 stack) │
│ │
▼ ▼
┌────────────────────────────────────────────────────────────────────────────┐
@@ -118,8 +103,7 @@ For details on the cryptographic properties of each key type, see
2. KeyPackages are single-use (RFC 9420 requirement). The AS atomically removes
a KeyPackage on fetch to enforce this invariant.
3. The QUIC + TLS 1.3 stack is the primary transport (M3+). The Noise_XX over
TCP stack from M1 remains available for environments where QUIC is blocked.
3. QUIC + TLS 1.3 is the sole transport layer.
---
@@ -127,9 +111,8 @@ For details on the cryptographic properties of each key type, see
The system stacks three protocol layers:
1. **Transport** -- QUIC + TLS 1.3 (primary) or Noise_XX over TCP (M1
fallback). Provides confidentiality, integrity, and server authentication.
See [Protocol Stack](protocol-stack.md).
1. **Transport** -- QUIC + TLS 1.3. Provides confidentiality, integrity, and
server authentication. See [Protocol Stack](protocol-stack.md).
2. **Framing / RPC** -- Cap'n Proto serialisation and RPC. Provides zero-copy
typed messages, schema versioning, and async method dispatch.
@@ -152,7 +135,7 @@ The implementation is split across four workspace crates:
| Crate | Role |
|----------------------------|-------------------------------------------------------------------|
| `quicnprotochat-core` | Crypto primitives, Noise transport, MLS state machine, hybrid KEM |
| `quicnprotochat-core` | Crypto primitives, MLS state machine, hybrid KEM |
| `quicnprotochat-proto` | Cap'n Proto schemas, codegen, and serialisation helpers |
| `quicnprotochat-server` | QUIC listener, NodeService RPC, storage |
| `quicnprotochat-client` | QUIC client, CLI subcommands, state persistence |
@@ -164,7 +147,7 @@ and dependency diagram.
## Further Reading
- [Protocol Stack](protocol-stack.md) -- layered comparison of the two transport stacks
- [Protocol Stack](protocol-stack.md) -- layered protocol stack description
- [Service Architecture](service-architecture.md) -- NodeService RPC methods, connection lifecycle, long-polling
- [End-to-End Data Flow](data-flow.md) -- registration, group creation, and message exchange sequence diagrams
- [Wire Format Overview](../wire-format/overview.md) -- Cap'n Proto schema reference

View File

@@ -2,16 +2,15 @@
quicnprotochat layers three protocol stages to move a plaintext message from
sender to recipient with end-to-end encryption, typed RPC framing, and
authenticated transport. This page describes each layer, explains why both the
QUIC and Noise transport stacks exist, and provides a side-by-side comparison.
authenticated transport. This page describes each layer and provides a
comparison table.
---
## Primary Stack (M3+): QUIC + TLS 1.3
## Transport: QUIC + TLS 1.3
Starting from milestone M3, the primary transport is QUIC over UDP with TLS 1.3
negotiated by `quinn` and `rustls`. Cap'n Proto RPC rides on a bidirectional
QUIC stream.
The transport layer is QUIC over UDP with TLS 1.3 negotiated by `quinn` and
`rustls`. Cap'n Proto RPC rides on a bidirectional QUIC stream.
```text
┌─────────────────────────────────────────────┐
@@ -56,90 +55,6 @@ QUIC stream.
`BasicCredential`.
- Ciphersuite: `MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519`.
---
## M1 Stack: Noise_XX over TCP
The original milestone-1 transport uses a Noise Protocol Framework handshake
directly over TCP. This stack is retained for environments where QUIC (UDP) is
blocked by middleboxes.
```text
TCP connection
└── Noise_XX handshake (snow)
└── Authenticated encrypted channel (ChaCha20-Poly1305)
└── [u32 frame_len LE][Cap'n Proto encoded message]
└── Cap'n Proto RPC (capnp-rpc)
```
### Layer details
**TCP**
- Reliable, ordered byte stream.
- No built-in encryption or authentication.
**Noise_XX** (`snow`)
- Pattern: `Noise_XX_25519_ChaChaPoly_BLAKE2s`.
- Three-message handshake that mutually authenticates both peers' static
X25519 keys:
```text
XX handshake (3 messages):
-> e (initiator sends ephemeral public key)
<- e, ee, s, es (responder: DH + static key)
-> s, se (initiator: static key + final DH)
```
- After the handshake, every frame is encrypted with ChaCha20-Poly1305 (AEAD)
using session keys derived from the Noise key schedule.
- Maximum Noise message size: 65,535 bytes.
**Length-Prefixed Codec** (`LengthPrefixedCodec` in `quicnprotochat-core`)
- Each frame is prefixed by a 4-byte little-endian `u32` length field.
- Little-endian was chosen for consistency with Cap'n Proto's segment table
encoding.
- Wire format:
```text
┌──────────────────────────┬──────────────────────────────────────┐
│ length (4 bytes, LE u32)│ payload (length bytes) │
└──────────────────────────┴──────────────────────────────────────┘
```
- Maximum payload size is `NOISE_MAX_MSG` (65,535 bytes), enforced on both
encode and decode.
- See [Length-Prefixed Framing Codec](../wire-format/framing-codec.md) for the
full specification.
**Cap'n Proto RPC**
- Same schema and RPC interface as the QUIC stack.
- The `NoiseTransport::into_capnp_io()` method bridges the message-oriented
Noise channel to the byte-stream interface that `capnp-rpc`'s
`twoparty::VatNetwork` expects, using a `tokio::io::duplex` pipe and a
background shuttle task.
---
## Why Both Stacks Exist
| Concern | QUIC + TLS 1.3 | Noise_XX over TCP |
|------------------------|----------------------------------------|----------------------------------------|
| **Milestone** | M3+ (primary) | M1 (original, retained) |
| **UDP availability** | Requires UDP; may be blocked on some networks | TCP-only; works everywhere |
| **Connection setup** | 1-RTT (or 0-RTT on resumption) | 1-RTT TCP + 1.5-RTT Noise handshake |
| **Multiplexing** | Native QUIC stream multiplexing | Single TCP connection, single stream |
| **Authentication** | Server cert (self-signed / CA-issued) | Mutual static-key authentication |
| **PQ gap** | TLS 1.3 key exchange is classical ECDHE | Noise key exchange is classical X25519 |
| **Crate** | `quinn`, `rustls` | `snow` |
Both stacks carry the same Cap'n Proto RPC and MLS layers on top, so
application logic is transport-agnostic. The Noise_XX stack may also serve as a
peer-to-peer transport in future mesh topologies where a QUIC server
certificate model does not apply.
---
@@ -148,7 +63,6 @@ certificate model does not apply.
| Layer | Provides | Crate(s) |
|-------------|------------------------------------------------------------------|-----------------------------------------|
| **Transport: QUIC + TLS 1.3** | Confidentiality, server authentication, forward secrecy, multiplexed streams, congestion control | `quinn`, `rustls` |
| **Transport: Noise_XX** | Confidentiality, mutual authentication, forward secrecy (per-session) | `snow` |
| **Framing: Cap'n Proto** | Zero-copy typed serialisation, schema versioning, async RPC with promise pipelining | `capnp`, `capnp-rpc` |
| **Encryption: MLS** | Group key agreement, forward secrecy, post-compromise security, identity binding | `openmls`, `openmls_rust_crypto` |
| **Encryption: Hybrid KEM** (optional) | Post-quantum confidentiality for individual payloads (X25519 + ML-KEM-768) | `ml-kem`, `x25519-dalek`, `chacha20poly1305`, `hkdf` |
@@ -175,12 +89,12 @@ TLS-encoded MlsMessageOut (opaque ciphertext blob)
Cap'n Proto: enqueue(recipientKey, payload)
│ ── serialised into NodeService RPC call ──
QUIC stream (TLS 1.3 encrypted) ─── or ─── Noise frame (ChaCha20-Poly1305)
QUIC stream (TLS 1.3 encrypted)
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ network ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
Server: NodeService.enqueue() stores payload in FIFO queue
@@ -200,8 +114,7 @@ The server **never** holds the MLS group key. It sees only the encrypted
## Further Reading
- [Architecture Overview](overview.md) -- high-level system diagram and dual-key model
- [Noise_XX Handshake](../protocol-layers/noise-xx.md) -- deep dive into the three-message handshake
- [Architecture Overview](overview.md) -- high-level system diagram and identity key model
- [QUIC + TLS 1.3](../protocol-layers/quic-tls.md) -- QUIC configuration, ALPN, and certificate handling
- [Cap'n Proto Serialisation and RPC](../protocol-layers/capn-proto.md) -- schema design and VatNetwork wiring
- [MLS (RFC 9420)](../protocol-layers/mls.md) -- ciphersuite selection, key schedule, and ratchet tree