Skip to main content
For zero-knowledge profiles, all cryptographic operations happen client-side — the browser, the CLI daemon, or any other approved local runtime. The server stores only ciphertext, wrapped keys, salts, and KDF parameters.

Algorithms

Key hierarchy

KDF parameters

Default Argon2id parameters (client-side only):
Memory is in KiB (65536 KiB = 64 MiB), per RFC 9106’s second recommendation for memory-constrained environments. The salt is 16 random bytes, stored alongside the wrapped root key.

Wire formats

All binary data is unpadded base64 (RFC 4648 §5, URL-safe alphabet) for storage and transport.

Profile record

wrapped_root_key and recovery_wrapped_root_key carry their 24-byte XChaCha20-Poly1305 nonce as the first 24 bytes; the decrypt side splits on the known nonce length.

ZK item record

ZK item plaintext envelope

The envelope is serialized to UTF-8 bytes, then encrypted with the item DEK.

Server-managed item record

The plaintext envelope is the same JSON shape as ZK items.

Recovery key format

256-bit random key encoded as base32 (RFC 4648), grouped in fives:
52 base32 characters = 260 bits (padded from 256). The recovery key wraps the root key with the same XChaCha20-Poly1305 scheme as the KEK wrap.

Password change flow

The root key never changes during a password change; only its wrap.

Root key rotation flow

Partial payloads (missing some items) return ROTATE_KEY_INCOMPLETE with the missing IDs in meta.missingItemIds.

Version fields

Personal API key format

  • Prefix: abu_ (personal API key, bound to a user + org)
  • Random portion: 32 bytes, base64url-encoded
  • Server stores: SHA-256 hash + first 8 chars as lookup prefix
  • Authentication: constant-time hash comparison
  • Resolves to a session identity (management surface only); never reaches access.*