trueseal-noise — Overview
trueseal-noise is a thin Rust wrapper around snow, a well-tested Noise Protocol implementation. It exposes the two handshake patterns the trueseal stack actually uses, and nothing else. It’s the cryptographic transport layer everything else sits on top of.
What it does
Hand it a raw connection — a TCP socket, an in-memory pipe, anything that implements Read + Write — and it gives you back an encrypted, authenticated channel. After the handshake completes, both sides can send and receive arbitrary byte payloads, with these guarantees:
- Contents are encrypted; nobody on the wire can read them.
- Messages can’t be tampered with — any modification is detected and the message is rejected.
- The peer on the other end is who they say they are (depending on which handshake pattern you use).
- Past traffic stays unreadable even if a long-term session key leaks later (forward secrecy).
Cipher suite
Every session uses the same fixed suite: X25519_ChaChaPoly_BLAKE2s.
- X25519 — Diffie-Hellman key agreement. Produces a shared secret from two keypairs without either side ever sending its private key.
- ChaCha20-Poly1305 — authenticated encryption. Encrypts the payload and tacks on a 16-byte authentication tag. Modify either the ciphertext or the associated data and decryption fails.
- BLAKE2s — hashing, used both for key derivation (HKDF) and for the running handshake hash that binds all handshake messages together.
ChaCha20-Poly1305 over AES-GCM, for one specific reason: it runs in constant time in software. No timing side-channel without hardware AES support. That matters for devices that don’t have AES-NI.
Two handshake patterns
trueseal-noise implements exactly two patterns from the Noise spec:
Noise_XX_25519_ChaChaPoly_BLAKE2s — mutual authentication. Neither peer knows the other’s static key beforehand. After the handshake, both sides have verified each other. This is what Receive Sessions use.
Noise_NK_25519_ChaChaPoly_BLAKE2s — one-way authentication. The Initiator knows the Responder’s static key going in. The Responder never learns the Initiator’s static key — the Initiator stays anonymous. This is what Push Sessions use, so devices can send blobs to the relay without revealing who they are.
Spec compliance
snow is verified against the official cacophony test vectors. Those are published by the Noise authors and pin down the exact byte-level output of a correct implementation given fixed input keys and payloads. trueseal-noise rides on that compliance by wrapping snow.
Standalone
trueseal-noise doesn’t depend on anything else in the trueseal stack. It knows nothing about sync groups, relays, envelopes, or devices. It produces encrypted channels. What you push through them is your problem.
If you just need authenticated, forward-secret transport for something else entirely, you can use it on its own with no trueseal-sync or trueseal-relay anywhere in sight.
Framing
Every message is prefixed with a 2-byte big-endian length. This is necessary because Noise encrypts one message at a time — without a length prefix, a stream receiver has no way to tell where one message ends and the next begins. Max message size is 65535 bytes, set both by the 2-byte length prefix and by Noise’s own hard cap. Anything bigger has to be chunked by the caller.
Platforms
Rust, compiled for every platform the stack targets: macOS, Linux, iOS, Android. Swift and Kotlin bindings come from UniFFI, so iOS and Android callers get the same implementation without hand-written FFI glue.
Source
github.com/julianbonomini/trueseal-noise.
Going deeper
Three sub-pages: a primer if you’re new to Noise, then a page on each handshake pattern.
- Noise Protocol Primer — how Noise works, from scratch.
- XX Pattern — three-message mutual-auth handshake (Receive Sessions).
- NK Pattern — two-message anonymous-initiator handshake (Push Sessions).