Skip to content
Get early access

Key hierarchy

Key hierarchy

Five levels. Your master password and your Secret Key combine through Argon2id to produce the Master Unlock Key, which never leaves the device. That decrypts your key pair's private half, which is stored server-side encrypted. That unwraps one key per environment, which is stored wrapped separately for each member. That key encrypts that environment's secrets, which the server stores as ciphertext.

Your master password is never stored anywhere — not by us, not hashed, not encrypted. It is combined with a Secret Key, 32 bytes generated on your device by the operating system’s CSPRNG, through Argon2id in its keyed mode, to derive the Master Unlock Key.

The Secret Key is what defends a weak password. Without it, everything server-side would be only as strong as your password against an offline attack. With it, an attacker holding the entire database is missing 32 bytes they have never seen and cannot obtain from us.

The Master Unlock Key is consumed by unlock and is not resident while the vault is open. It is not sitting in memory waiting to be found.

Each account has one X25519 key pair. The public half is shared freely; the private half is stored on our server encrypted under your Master Unlock Key, which is what lets you unlock on a new device with your password and Secret Key.

Unlock does not simply decrypt and proceed. It derives and compares: the public key is recomputed from the decrypted private key and checked against the key your device expects. A mismatch is a hard failure with its own distinct error — deliberately not blended into “wrong password”, because the two demand opposite responses from you. A wrong password means retype it. A key mismatch means stop and verify what the server just handed you.

Each environment has its own symmetric key. It is never stored unwrapped.

Granting access = wrapping that key to a member’s public key and storing the result. The stored blob is opaque to the server — it cannot verify what is inside, which is precisely why the fingerprint ceremony exists and is mandatory.

Revoking = deleting that blob, then rotating the key so the revocation is real rather than nominal. See rotation.

A key that comes back from unwrapping is not usable yet. It is a distinct type that no encryption or wrapping function will accept, and it becomes a usable key only by successfully decrypting an authentic payload bound — through the encryption’s associated data — to the exact environment, epoch, and version the client expected.

This closes the write path, not just the read path. A client can never encrypt new secrets under, or re-grant onward, a key the server substituted, because such a key never survives verification.

It is also why creating an environment always writes a first payload in the same step: a verification target must always exist. A key with nothing to check it against would be a key you have to trust on faith.

Every rotation of an environment’s key increments that environment’s key epoch. Payloads and grants carry the epoch they belong to, so a client holding a stale cached key detects it rather than producing garbage.

Rotation is atomic server-side: one transaction replaces the payload and the entire grant set.

Payload history from before a rotation becomes unreadable to anyone who did not retain the old key. That is the accepted cost of revocation being real.

Thing Where
Master password Nowhere. Typed, used, discarded
Secret Key Your Recovery Kit, and your local vault file
Master Unlock Key Memory, during unlock only
Private key Server, encrypted under the Master Unlock Key
Public key Server, plainly. It is public
Environment keys Server, wrapped once per member. Opaque
Secrets Server, as ciphertext
Recovery backup Server as ciphertext, plus a copy in your local file

The exact construction for each of these is on Cryptography.