Architecture
One stack, four layers
From the Compose UI on the phone to the relays in the data center, every layer has exactly one job — and each is a separately auditable crate in the workspace.
Android app (Kotlin/Compose) and bots drive the Rust core through etoki-ffi — one UniFFI surface for invitations, sessions, groups, files and the directory.
etoki-agent owns conversations: PQ-hybrid handshakes, the double ratchet, MLS groups (etoki-group), reconnect and rekey policy.
etoki-client speaks the block protocol, dials by pinned fingerprint with IP hints or DNS-over-HTTPS, and picks the transport: plain TCP, WebSocket, TLS camouflage or SOCKS5/Tor.
Routers (2-hop onion), file relays (padded chunks), the @username directory, push relays, and the :443 camouflage gateway that fronts them all.
The cryptographic core
How the guarantees are built
Each mechanism below is a concrete component of the Rust core — not a design aspiration.
NST handshake
Transport setup combines X25519 with ML-KEM-768, so a recorded session stays sealed against a future quantum adversary. The peer's public-key fingerprint is pinned in the address itself — forged DNS or TLS answers cannot impersonate anyone. Long sessions rekey with fresh ephemerals in-channel.
Self-healing ratchet
Every double-ratchet DH step mixes in a fresh ML-KEM encapsulation. Forward secrecy on every message, and post-compromise security that also heals against harvest-now-decrypt-later collection.
2-hop onion path
The entry router learns your IP but not your contact; the destination router learns the queue but not you. Entry routers keep pooled always-on links to destinations and batch with jitter, blunting timing correlation.
Uniform block framing
All traffic moves in fixed 16 KiB blocks with exponential cover-traffic schedules and 0–400 ms send jitter — size and timing stop correlating with what you actually do.
Pluggable transports
Plain TCP for speed, WebSocket to pass through CDNs, a camouflaged TLS gateway that serves a real certificate and a decoy page to probers, or SOCKS5 — point it at Tor and each session gets its own circuit with onion targets resolved inside the proxy.
Opt-in directory
A standalone relay maps a unique @username to your contact token under an owner key only you hold. Resolving a name still goes through the normal knock/approve flow — the directory holds no queue and sees no content.
The path of a message
Two hops, split knowledge
Your client tunnels to the peer's router through an entry router. The entry sees your IP but not the queue; the destination sees the queue but not you. Content is end-to-end encrypted before the first hop.
Relay roles
Small servers, single purposes
Every relay is the same statically linked binary with a different job — and none of them can read a message.
Router
Holds opaque queues and moves blocks. Entry and destination roles split knowledge of the endpoints — that is the whole trick.
File relay
Stores padded chunks in size buckets with a retention sweeper. Descriptions are end-to-end encrypted; it never sees content.
Directory
Maps @usernames to contact tokens under per-registration owner keys. No queues, no content — resolving still needs your approval.
Push relay
Optional content-free ping over APNs/FCM for deployments that trade a contentless nudge for battery.
Gateway
Terminates camouflage TLS on :443 with a real certificate and splices each secret path to the right local relay. Probers get a static decoy page.
