Zero-Trust Mesh Networking Without Certificates
Traditional secure networking assumes certificates. You get a cert from a CA, configure your server, and clients validate the chain of trust. This model works for the web. It doesn't work for a mesh network where every node is both client and server, where nodes appear and disappear, and where no central authority should be a single point of failure.
RavenFabric uses Noise XX — the same cryptographic handshake pattern used by WireGuard. Here's how it enables zero-trust mesh networking without a single certificate.
The Noise Protocol Framework
Noise is a framework for building cryptographic protocols. Unlike TLS (which is a single, enormous protocol with hundreds of extensions), Noise defines simple building blocks that compose into handshake patterns. Each pattern provides different security properties.
RavenFabric uses:
Noise_XX_25519_ChaChaPoly_BLAKE2s
Breaking that down:
- XX — the handshake pattern (mutual authentication, identity hiding)
- 25519 — X25519 Diffie-Hellman for key agreement
- ChaChaPoly — ChaCha20-Poly1305 for authenticated encryption
- BLAKE2s — BLAKE2s for hashing
Why XX?
Noise defines many handshake patterns. The important ones for our use case:
| Pattern | Auth | Identity Hiding | Round Trips |
|---|---|---|---|
| IK | Mutual | Initiator only | 1 |
| IX | Mutual | None | 1 |
| XX | Mutual | Both | 1.5 |
| NK | Server only | Initiator only | 1 |
We chose XX because:
- Mutual authentication — both sides prove their identity. Not just "is this the right server?" but also "is this an authorized client?" Every node must prove who it is.
- Identity hiding from both sides — static public keys are encrypted during the handshake. A network observer (including a relay!) cannot determine who is talking to whom. This is critical when routing through untrusted relays.
- No pre-shared knowledge required — unlike IK (where the initiator must already know the responder's key), XX works even on first contact. This enables enrollment flows where a new agent connects without prior key distribution.
The XX Handshake (3 Messages)
The XX pattern exchanges three messages:
→ e (Initiator sends ephemeral key)
← e, ee, s, es (Responder sends ephemeral + static)
→ s, se (Initiator sends static, encrypted)
In human terms:
- Message 1 (→) — Initiator generates a fresh ephemeral keypair, sends the public half. No identity revealed yet.
- Message 2 (←) — Responder generates its own ephemeral keypair, performs DH operations (ee, es), then sends its static public key encrypted under the session keys. The responder's identity is now proven to the initiator, but hidden from observers.
- Message 3 (→) — Initiator sends its static public key encrypted under the session keys. The initiator's identity is now proven to the responder, and hidden from observers.
After these three messages, both sides have:
- Verified each other's long-term identity
- Derived shared session keys with forward secrecy
- Hidden both identities from any network observer
Identity is a Key, Not a Certificate
In RavenFabric, an agent's identity is simply its static Curve25519 public key (32 bytes). There's no X.509 certificate, no CA chain, no expiry date to manage, no revocation list to check.
# Generate a new agent identity
$ rf-agent --generate-key /etc/ravenfabric/agent.key
Generated static key: rF_k1_8Jna3...xQ2p (base62)
Public key: rF_pub_mT7vK...9bWn
Trust is established by adding a public key to your trust store — similar to SSH's known_hosts, but with a cryptographic enrollment flow (OTP-based) for first contact.
Enrollment (First Contact)
When a new agent joins the mesh:
- Administrator generates a one-time enrollment token (OTP)
- OTP is communicated out-of-band (copy-paste, QR code, sealed envelope)
- Agent connects to a relay, presents the OTP
- Controller validates OTP (hash-stored, single-use, TTL-enforced)
- Noise XX handshake exchanges static keys
- Both sides add each other to their trust store
- OTP is burned — can never be reused
After enrollment, the agent and controller recognize each other by key alone. No OTP needed again. No certificate renewal. No CA dependency.
Relay Opacity
RavenFabric's relay broker forwards encrypted bytes between agents and clients. Because the Noise XX handshake encrypts static keys (identity hiding), the relay learns nothing:
- It doesn't know which agent is connected (keys are encrypted)
- It can't decrypt the payload (no session keys)
- It can't forge messages (no MAC keys)
- It can't replay old sessions (ephemeral keys differ every time)
The relay is a dumb pipe. If compromised, the attacker gains the ability to observe encrypted traffic timing and sizes — but not identities or content. This is a massive improvement over TLS-terminating load balancers that see everything in plaintext.
Forward Secrecy
Every connection generates fresh ephemeral Curve25519 keypairs. The session keys are derived from DH operations between ephemeral keys (ee) combined with static keys (es, se). This means:
- Compromising a static key doesn't decrypt past sessions — past sessions used different ephemeral keys that no longer exist
- Each session is independent — breaking one connection reveals nothing about others
- Keys are zeroed from memory after use — RavenFabric uses Rust's
zeroizecrate to wipe sensitive material on drop
Wire Protocol
After the Noise XX handshake completes, data flows as encrypted frames:
┌──────────────────────────────────────────────┐
│ RVNF (4 bytes magic) │
│ Version (1 byte) │
│ [Noise XX Handshake — 3 messages] │
├──────────────────────────────────────────────┤
│ Frame: [length: 4B BE][ciphertext + 16B MAC] │
│ Frame: [length: 4B BE][ciphertext + 16B MAC] │
│ ... │
└──────────────────────────────────────────────┘
The magic bytes (RVNF) and version byte are validated on every connection. This prevents protocol confusion attacks and enables graceful version negotiation in the future.
Each encrypted frame carries a 16-byte Poly1305 MAC. Any tampering — even a single bit flip — causes immediate rejection and connection termination. In RavenFabric, tamper detection also triggers automatic transport migration to an alternative path.
Comparison with TLS
| Property | TLS 1.3 | Noise XX |
|---|---|---|
| Code complexity | ~70,000 LOC (OpenSSL) | ~1,600 LOC (rf-crypto) |
| Certificate needed | Yes (server), optional (client) | No |
| CA dependency | Yes | No |
| Mutual auth | Awkward (client certs) | Default |
| Identity hiding | Server name in ClientHello (ECH draft) | Both sides hidden |
| Forward secrecy | Yes | Yes |
| Round trips | 1 (0-RTT with PSK) | 1.5 (0-RTT with PSK possible) |
| Attack surface | Large (extensions, cipher suites, legacy) | Minimal (fixed primitives) |
TLS's attack surface is enormous because it must support every browser connecting to every server. Noise XX is purpose-built for peer-to-peer communication where both sides are known software.
Post-Quantum Readiness
RavenFabric's crypto layer includes a hybrid KEM (Key Encapsulation Mechanism) that combines X25519 with a post-quantum algorithm. The session key derivation concatenates both shared secrets:
session_key = BLAKE2s(x25519_shared || pq_kem_shared || context)
If the post-quantum algorithm turns out to be broken, X25519 still provides security. If a quantum computer breaks X25519, the PQ algorithm provides security. Belt and suspenders.
Why This Matters for Mesh Networking
In a mesh network, every node might connect to every other node. Connections are dynamic. Nodes go offline and come back. New nodes join. Traditional PKI (public key infrastructure) would require:
- A CA that's always reachable (single point of failure)
- Certificate renewal for every node (operational burden)
- CRL/OCSP checking on every connection (latency, availability)
- Trust hierarchy that maps poorly to peer-to-peer topology
With Noise XX, you need: a 32-byte key per node, and a trust store that maps keys to identities. That's it. No CA. No renewal. No revocation infrastructure. Just keys.
When a node is compromised, you remove its key from the trust store. When a new node joins, you add its key via OTP enrollment. The mesh self-heals around key changes without any central infrastructure.
This is zero-trust in the truest sense: trust nothing by default, verify everything cryptographically, and never depend on infrastructure that might not be reachable.