Etoki

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.

Apps & FFI

Android app (Kotlin/Compose) and bots drive the Rust core through etoki-ffi — one UniFFI surface for invitations, sessions, groups, files and the directory.

Agent — sessions

etoki-agent owns conversations: PQ-hybrid handshakes, the double ratchet, MLS groups (etoki-group), reconnect and rekey policy.

Client — transport

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.

Relays

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.

You
sender
encrypted
Entry
sees your IP, not the peer
encrypted
Destination
sees the peer, not you
encrypted
Peer
recipient
No single router sees both endpoints. Content is end-to-end encrypted the whole way.

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.