docs(architecture): add RFC 7250 raw public key identity model
iroh uses RFC 7250 raw Ed25519 public keys for TLS instead of X.509 certificates. rustls already supports this. This means the quinn endpoint can also use raw public keys — same key-based identity model as iroh, but with direct QUIC over UDP. X.509 is optional, needed only for domain-facing identity (browser/WebTransport clients). Update StaticConfig with TlsIdentity enum (X509, RawKey, SelfSigned) and add iroh_relay field. Remove 'iroh deferred' language — iroh is a first-class connectivity mode.
This commit is contained in:
@@ -13,22 +13,46 @@ Immutable configuration resolved at startup. Cannot be changed without restartin
|
||||
|
||||
```rust
|
||||
pub struct StaticConfig {
|
||||
/// Bind address for the QUIC endpoint (e.g., "0.0.0.0:4433").
|
||||
pub listen_addr: SocketAddr,
|
||||
/// Bind address for the quinn endpoint (e.g., "0.0.0.0:4433").
|
||||
/// None if the quinn endpoint is not configured (iroh-only node).
|
||||
pub listen_addr: Option<SocketAddr>,
|
||||
|
||||
/// Path to TLS certificate file (PEM).
|
||||
/// Required for QUIC+TLS. The endpoint will not start without TLS configuration.
|
||||
pub tls_cert: Option<PathBuf>,
|
||||
/// TLS identity mode for the quinn endpoint.
|
||||
/// Required if listen_addr is Some.
|
||||
pub tls_identity: Option<TlsIdentity>,
|
||||
|
||||
/// Path to TLS private key file (PEM).
|
||||
/// Required alongside tls_cert.
|
||||
pub tls_key: Option<PathBuf>,
|
||||
/// iroh relay URL (e.g., "https://relay.iroh.network/").
|
||||
/// None if the iroh endpoint is not configured.
|
||||
pub iroh_relay: Option<RelayUrl>,
|
||||
|
||||
/// Drain timeout for graceful shutdown (default: 2 seconds).
|
||||
pub drain_timeout: Duration,
|
||||
}
|
||||
|
||||
/// TLS identity configuration for the quinn endpoint.
|
||||
pub enum TlsIdentity {
|
||||
/// X.509 certificate for domain-facing identity.
|
||||
/// Required for browser/WebTransport clients.
|
||||
X509 {
|
||||
cert: PathBuf,
|
||||
key: PathBuf,
|
||||
},
|
||||
|
||||
/// RFC 7250 raw Ed25519 public key.
|
||||
/// No domain, no CA, no cert renewal. Key = identity.
|
||||
/// Same model as iroh's NodeId, but for direct QUIC connections.
|
||||
RawKey(SecretKey),
|
||||
|
||||
/// Self-signed X.509 cert for development.
|
||||
/// Generated on startup, not validated by external clients.
|
||||
SelfSigned,
|
||||
}
|
||||
```
|
||||
|
||||
### Why `TlsIdentity` instead of `tls_cert`/`tls_key` options
|
||||
|
||||
The original `tls_cert: Option<PathBuf>` / `tls_key: Option<PathBuf>` assumed X.509 was the only TLS identity model. RFC 7250 raw public keys (used by iroh, supported by rustls) provide an alternative: Ed25519 key as identity, no X.509, no CA, no domain. This is a separate mode, not just "no cert."
|
||||
|
||||
### Key differences from reference implementation
|
||||
|
||||
The reference `StaticConfig` (in `alknet-main/crates/alknet-core/src/config/static_config.rs`) is SSH-centric: it holds `host_key`, `host_key_algorithm`, `proxy_config`, `stealth`, `transport_mode`, and `listeners`. The new model removes all of these:
|
||||
@@ -36,8 +60,7 @@ The reference `StaticConfig` (in `alknet-main/crates/alknet-core/src/config/stat
|
||||
- **No `host_key`/`host_key_algorithm`**: SSH host keys are managed by the SSH handler, not by core config. The endpoint uses TLS certs, not SSH host keys.
|
||||
- **No `proxy_config`**: Outbound proxy is an SSH-specific concern (SOCKS5/HTTP CONNECT forwarding). Not in core config.
|
||||
- **No `stealth`**: ALPN eliminates the need for stealth/byte-peeking. See [ADR-001](../../decisions/001-alpn-protocol-dispatch.md).
|
||||
- **No `transport_mode`/`listeners`**: The old `ServeTransportMode` and `ListenerConfig` enum are replaced by a single `listen_addr`. QUIC+TLS+ALPN replaces multiple listener types. See [ADR-010](../../decisions/010-alpn-router-and-endpoint.md).
|
||||
- **No `iroh_relay`**: iroh transport is deferred (OQ-05). The v1 endpoint uses quinn directly.
|
||||
- **No `transport_mode`/`listeners`**: The old `ServeTransportMode` and `ListenerConfig` enum are replaced by `listen_addr` (quinn) and `iroh_relay` (iroh). Both are optional — a node can use either or both. See [ADR-010](../../decisions/010-alpn-router-and-endpoint.md).
|
||||
|
||||
### Construction
|
||||
|
||||
|
||||
@@ -161,13 +161,31 @@ A key distinction that the ALPN model makes explicit:
|
||||
|
||||
| Layer | Purpose | Mechanism |
|
||||
|-------|---------|-----------|
|
||||
| **Network identity** | How a client finds and verifies the node | TLS cert (quinn), NodeId (iroh) |
|
||||
| **Network identity** | How a client finds and verifies the node | X.509 cert (domain) or RFC 7250 raw key (Ed25519) or iroh NodeId |
|
||||
| **Auth identity** | Who the peer is and what they can do | SSH key, API token, certificate (handlers) |
|
||||
|
||||
The TLS cert is the node's network-facing identity — it's what `alknet.example.com` resolves to. It's NOT the node's authentication identity. Auth happens inside the handler via `IdentityProvider`.
|
||||
The TLS cert (or raw public key, or NodeId) is the node's network-facing identity. It's NOT the node's authentication identity. Auth happens inside the handler via `IdentityProvider`.
|
||||
|
||||
This matches the reference implementation: the TLS cert encrypts and camouflages, but SSH key exchange handles the actual authentication.
|
||||
|
||||
## RFC 7250: Raw Public Keys in TLS
|
||||
|
||||
iroh uses RFC 7250 raw public keys instead of X.509 certificates for TLS. The implementation is ~100 lines (see `iroh/iroh/src/tls/resolver.rs`): take an Ed25519 key, wrap its SPKI public key as a `CertificateDer`, tell rustls `only_raw_public_keys() -> true`. No X.509, no CAs, no domain names, no cert renewal.
|
||||
|
||||
rustls already supports RFC 7250. This means the quinn endpoint can also use raw Ed25519 public keys instead of X.509 certs:
|
||||
|
||||
- **No domain required**: A node without a domain name can use raw public keys for the quinn path — key-based identity, but with direct QUIC over UDP instead of relay-assisted connections.
|
||||
- **Key = identity**: The Ed25519 public key IS the node's identity. No CA trust chain, no cert expiry. The key can be derived from alknet-vault.
|
||||
- **X.509 is optional**: Domain-facing identity (replicators, public services) uses X.509 certs. Key-based identity (personal nodes, P2P) uses raw public keys. Both work with the same quinn endpoint.
|
||||
- **Browser limitation**: Browsers don't support RFC 7250. For browser/WebTransport clients, X.509 certs are needed. For alknet-native clients, raw public keys work fine.
|
||||
|
||||
This reframes the connectivity model. The quinn and iroh paths share the same key-based identity model via RFC 7250. They're distinguished by **connection establishment** (direct UDP vs relay-assisted), not by identity:
|
||||
|
||||
| Path | Connection establishment | Identity (domain-facing) | Identity (key-facing) |
|
||||
|------|------------------------|------------------------|---------------------|
|
||||
| quinn | Direct UDP, public IP | X.509 cert (domain name) | RFC 7250 raw key |
|
||||
| iroh | Relay-assisted P2P | N/A | RFC 7250 raw key (NodeId) |
|
||||
|
||||
## TLS Certificate Provisioning
|
||||
|
||||
For the quinn endpoint, `StaticConfig` provides TLS configuration via file paths:
|
||||
|
||||
@@ -132,6 +132,24 @@ This is the same model as the reference implementation's TLS mode: the cert make
|
||||
|
||||
For the iroh endpoint, the `NodeId` serves as network identity. No TLS cert is needed — iroh's QUIC uses the NodeId for connection verification.
|
||||
|
||||
### RFC 7250: Raw Public Keys in TLS
|
||||
|
||||
iroh uses RFC 7250 raw public keys instead of X.509 certificates for TLS. The implementation is strikingly simple (see `iroh/iroh/src/tls/resolver.rs`): take an Ed25519 key, wrap its SPKI public key as a `CertificateDer`, and tell rustls `only_raw_public_keys() -> true`. No X.509, no CAs, no domain names, no cert renewal.
|
||||
|
||||
rustls already supports RFC 7250. This means the quinn endpoint can also use raw Ed25519 public keys instead of X.509 certs. The implications:
|
||||
|
||||
1. **No domain required.** A node without a domain name can use raw public keys for the quinn path — the same key-based identity model as iroh, but with direct QUIC over UDP instead of relay-assisted connections.
|
||||
2. **Key = identity.** The Ed25519 public key IS the node's identity. No CA trust chain, no cert expiry, no renewal. The key is derived from alknet-vault or generated at startup.
|
||||
3. **X.509 is optional.** Domain-facing identity (for replicators, public services) uses X.509 certs. Key-based identity (for personal nodes, P2P) uses raw public keys. Both work with the same quinn endpoint.
|
||||
4. **Browser compatibility.** Browsers don't support RFC 7250 — they require X.509. For browser/WebTransport clients, X.509 certs are needed. For alknet-native clients, raw public keys work fine.
|
||||
|
||||
This reframes the connectivity model. The quinn and iroh paths are not distinguished by their identity model (both can use Ed25519 keys). They're distinguished by how the connection is established:
|
||||
|
||||
| Path | Connection establishment | Identity model (v1) | Identity model (future) |
|
||||
|------|------------------------|--------------------|-------------------------|
|
||||
| quinn | Direct UDP, public IP | X.509 (domain) | X.509 or RFC 7250 raw key |
|
||||
| iroh | Relay-assisted P2P | RFC 7250 raw key (NodeId) | Same |
|
||||
|
||||
### Error taxonomy
|
||||
|
||||
```rust
|
||||
|
||||
Reference in New Issue
Block a user