001 — Trust Model, Enrollment, and Bootstrap¶
Status: accepted Date: 2026-07-18
Context¶
Zajil is an encrypted communication protocol for a closed, institution-scale network (~10k devices, university setting). Servers ("Barid" nodes) are operated by us and are assumed to be individually compromisable. The design goal is an owned network with accountable identity — explicitly not an anonymity network.
Non-Goals¶
- Anonymity. Every device maps to a physically verified human. This is a deliberate design choice, not a limitation to be fixed later.
- Open enrollment. There is no remote or self-service path onto the network.
- Content inspection. Payloads are end-to-end encrypted. Abuse enforcement operates through attribution and revocation, never through reading traffic. See "Accountability" below.
- Scale beyond ~10k devices per cell group. Larger populations get more cells, not a different architecture.
Decisions¶
1. The root key is the only trust anchor¶
A single Ed25519 root keypair, held offline on operator-controlled devices. Clients ship with the root public key baked in and nothing else — no server addresses, no server certificates, no per-deployment configuration.
Consequence: any Barid node can be destroyed and replaced without touching a single client. A node holds only a short-lived leaf certificate; it has no authority a client relies on.
Root key loss is unrecoverable — without it no manifest can be signed and every client freezes on its last known one. Mitigation: Shamir split across three operator devices, plus a second offline root key pre-authorized in clients from the first release.
2. Servers hold no authoritative state¶
A Barid node's entire state is derivable from the signed roster. No server-generated identifiers, no server-side source of truth. Message queues are ephemeral ciphertext; losing them drops messages but breaks nothing.
Recovery procedure: install binary, feed signed backup bundle, verify root signature, rebuild. The bundle contains the root keypair, the device roster (pubkey → label, cell assignment, status, issued-at), and the current manifest.
3. Server certificates are short-lived¶
Leaf certs expire in 30 days and are re-signed from an operator device. Expiry is the revocation mechanism — no CRL, no distributed revocation state. Urgent removal is handled by a manifest bump (§5).
4. Topology: cells, addresses, and derivation¶
- Cell — a node: one physical machine, running Barid.
- Address — one derived IPv6 endpoint bound by a cell. A cell binds dozens concurrently. Address count per cell is a resilience decision (one address blocked or blackholed must not take the cell down), unrelated to how many cells a client holds.
Endpoints are derived, not announced:
Client and cell compute the same addresses independently. No DNS (a third-party lever, and a public signal of network membership), no static addresses in the binary (enumerable by anyone holding the client).
Two independent dimensions, deliberately named apart:
bucket— the time counter, from the clock (module 2.1).slot— which of the cell's concurrent addresses, from enumeration. One cell secret must fan out into dozens of live addresses;slotis what distinguishes them.
They form a grid. At any instant a cell binds window_size × slot_count
addresses — with skew 1 and 30 slots, 90 bindings. Buckets roll over on the
rotation interval; slots are stable.
domain_tag gives domain separation, so a cell secret can never produce
colliding output if it is ever reused for another purpose.
The credential is the cell_secret, never an address. Two distinct
operations that must not be conflated:
- Unbinding an address — a server-side availability action. The client can still derive it. Not a revocation.
- Rotating the cell secret — real revocation. Invalidates every address that secret ever produced, instantly, and takes the client from N to N−1 cells.
A derived address is a rendezvous point, not a credential. Anyone learning an address may connect to it and will fail the handshake, which authenticates against the root key. Addresses provide scan resistance and unlinkability, not authentication. Therefore: no rate limiting, no single-use enforcement, and learning an address is not a compromise.
bucket granularity is a tunable (§7). Clients MUST accept adjacent buckets
(TOTP-style skew tolerance) or clock drift causes silent connection failures.
IPv6 availability is not a concern: the network runs on operator-controlled infrastructure, not the public internet.
5. The manifest is the only remote reconfiguration channel¶
A root-signed, versioned document listing cells, endpoints, and cert fingerprints. Clients cache the last seen manifest and accept a replacement only if root-signed with a higher version. Distributed opportunistically: served by any node, gossiped between peers.
A compromised node can serve a stale manifest. It cannot forge one.
6. Enrollment is physical, and is the primary path¶
Not a fallback. Enrollment happens in person at staffed checkpoints against institutional ID.
Checkpoints hold no key material. Enrollment tokens are pre-generated offline under the root key, serialized, printed, and handed out in sealed envelopes. A token activates exactly one pre-existing roster slot, once.
Consequences: - Compromising a checkpoint yields paper. Void the serial range, reprint. - The roster stays a single-writer artifact held by the operator. Checkpoints activate slots; they never create them. - Identity binds to a verified human at the moment of enrollment.
Devices that cannot reach a checkpoint are visited in person. There is no remote exception path.
7. Channel depletion, and why N = 10¶
Each device holds N channel secrets. Rotation is random and independent,
not scheduled — the observed spread over weeks is a statistical property, not a
designed stagger. Channels are also torn down on demand: on suspicion of a stolen
key a device can be taken 4 → 3 → 2 within a minute, or to 0 outright if physical
compromise is suspected.
A device is stranded only if all N channels die inside its response window. For
per-channel expiry probability p in that window, the risk is p^N:
| N | p = 0.1 | stranded per 10k devices |
|---|---|---|
| 3 | 1e-3 | ~10 |
| 10 | 1e-10 | ~0 |
| 40 | 1e-40 | never |
N = 10 buys roughly eight orders of magnitude over N = 3 at negligible cost. The "lose all 10 in one day" case is real but vanishingly rare — this is the reason N is 10 and not 2–3.
p^N holds only under independence. See §8 — this is the binding constraint
on deployment, not a footnote.
Refresh is triggered at a low-water threshold (~3). Clients surface remaining channel count so degradation is visible well before disconnection. At N = 10 with a 90-day mean lifetime, refreshes land around a ~63-day cycle:
One continuously staffed checkpoint, versus nine during a synchronized registration week. Arrivals self-distribute because each device's clock starts at its own enrollment.
Deprovisioning is passive. Someone who stops showing up falls off within ~60 days. No offboarding process. Urgent removal uses a manifest bump.
All of these are tunables, carried in the root-signed manifest (§5), not in
client or server configuration: N, rotation rate, time-bucket granularity,
mean lifetime, low-water threshold. Retuning N from 10 to 40, or daily rotation
to hourly, is a manifest signature — no client update, no server redeploy. These
values are expected to change during development; the protocol must not assume
any of them.
8. Independence is structural¶
A client holds N cell secrets, and a cell is one machine — so the N credentials
land on N distinct machines by construction. The p^N argument in §7 holds
without any additional assignment constraint.
This is why the vocabulary matters. Had cells been addresses rather than machines, a client's N credentials could co-locate on one host, a single host compromise would take all N simultaneously, and N = 10 would behave exactly like N = 1. Independence must remain a property of the topology, not something the assignment logic is trusted to preserve.
Addresses-per-cell (resilience against a blocked address) and cells-per-client (redundancy against a compromised machine) are independent dials operating at different layers.
Compartmentalization is counted per cell:
A compromised cell yields metadata only — who talked to whom, when, how much. Not content, and no ability to impersonate, since device identity chains to the root.
9. Operations staff cannot issue identity¶
The ops team deploys, rotates, and burns Barid nodes. The root key never touches server infrastructure, so ops are structurally incapable of enrolling a device or signing a manifest.
This is protective, not adversarial: an engineer who cannot issue identities cannot be coerced or phished into doing so.
Accountability¶
Abuse enforcement operates through attribution and revocation, never content inspection.
Every device maps to a human whose ID was checked in person. There is no anonymous registration, no bulk enrollment, no disposable identity. A report resolves to a named person in one roster lookup; revocation removes them from the network.
Content inspection is rejected because the same capability that would enable it is the capability that makes a compromised Barid node survivable. Attribution delivers enforcement without that trade.
Consequences for the Wire Format¶
Two items move earlier than originally planned, as both are format-shaped and painful to retrofit:
- Root key → certificate chain → device identity must be present in the first handshake design.
- Manifest format and version-gated acceptance must be specified before any server exists.
Open Questions¶
- Authenticated time source (pinned). Public NTP is spoofable, and since time is the shared state behind address derivation, clock control is denial of service with no cryptography broken. Direction: an operator-run time service whose responses are root-signed, so clock spoofing requires the root key. Note the security comes from the signature, not from obscuring the epoch — alternate calendars or offsets are obfuscation, not defense, and lunar calendars in particular have no single canonical algorithm. Interim mitigation: a persisted monotonic floor rejecting backward clock jumps.
- Bucket duration (§7 tunable) — candidate default 1 hour, unsettled.
- Cross-cell routing: cell-to-cell relay (preferred) vs. client multi-homing.
- Default tunable values for §7 — to be set empirically, not decided up front.
- Underlying network isolation is provided by a separate operator-built tool; Zajil assumes but does not implement it.