Zero Accessby Railmandocs

Crypto primitives

Inventory of primitives used in Vault, Elevate, and Chat, plus the evaluation decisions encoded in the packages.

Crypto primitives

Extended reading on which primitives this suite uses and what we evaluated when wiring them. WebAuthn/PRF product framing: WebAuthn and PRF. Design and upstream rationale: Crypto and package rationale. Short glossary table: Background.

Stage

This is a map of what is shipped in the packages — not a third-party audit report and not a claim of production readiness for your threat model.

Browser — vault and wraps

PrimitiveRole in the suiteNotes
WebAuthn + PRFLogin / elevate assertions; PRF → storage KEKFail closed on missing PRF for unlock paths that require it
HKDF-SHA256Domain-separated keys from PRF (and related browser KDFs)Info strings bind purpose + user; purposes are not interchangeable
PBKDF2-SHA256Password and recovery wrapsHigh iteration floor in client helpers; weak user passwords remain a residual risk
AES-GCMSeal product payloads under the MEK; related sealed blobsAAD binds context where the helpers require it
BIP-39Recovery phrase → seed → recovery wrap (and optional account-recovery signing material)Phrase is for reset, not everyday unlock
Ed25519Account-recovery challenge signing (Mode B)Server verifies; phrase never crosses the wire

Most product code should go through @railman/zero-vault and the passkey client helpers. Guides: Vault, Recovery.

Server — sessions, step-up, blind store

PrimitiveRole in the suiteNotes
HMAC (keyed digests)Elevate claims, login-factor stamps, persistent row MACsBound to Better Auth / Railman secrets — authorize on the server, not from client JSON alone
HKDF-SHA256Derive MAC and storage-ID families from one root key authorityApplications do not manage child key rings
Versioned SHA-256 IDsLong-lived E2E row reachability over canonical inputsServer-only identifiers, MAC-bound; not a substitute for encryption

zeroAccess({ secret? }) owns a single root (or captures Better Auth’s secret once). MACs detect field tampering by a DB attacker without the root; they do not detect deletion or rollback of a full valid snapshot. Depth: Security model.

Chat — after vault unlock

PrimitiveRole in the suiteNotes
X25519DH / identity material in @railman/zero-e2eConsumes a Vault-derived identity seed — no WebAuthn inside the crypto library
HKDF-SHA256Session and ratchet KDFs
AES-GCMMessage envelopes and sealed ratchet statePrekey envelopes bind selected wire fields in AAD
X3DH-style init + Double Ratchet1:1 session setup and forward secrecy structureNot a group / multi-device messenger

Product path: hardened passkey → PRF vault unlock → identity seed → zero-e2e. Guide: E2E chat.

Evaluation decisions (shape)

These are the trade-offs the docs and packages encode:

  1. Blind store over server-held MEKs — database dumps should not yield plaintext; residual risk moves to unlocked tabs and client malware (Security model).
  2. PRF-first daily unlock, password optional, recovery separate — recovery stays break-glass (WebAuthn and PRF, Recovery).
  3. Elevate independent of Vault — sudo without “elevated ⇒ decrypt” (Elevate and sudo).
  4. Exact Better Auth peer pins — callback and hook ordering are security-sensitive (Security model).
  5. Chat on Vault identity, not a second passkey stack (E2E chat).
  6. M6 denylist on key-store routes — fail closed if raw secrets appear in request bodies (Plugin contract).

For why we chose these primitives and how we treat upstream packages, see Crypto and package rationale.

On this page