Two interactive diagrams show where every key lives and what happens to a single password between the moment you type it and the moment you read it back. The jargon is not hidden: hover or tap any box or arrow for the plain-language version.
The phone (Safe) creates the Account Key and its own device keys. Each AP creates its own device keys, and the editing device creates the fileKey for a new entry. Secret keys are not generated by the server or uploaded in plaintext.
The body of an entry is sealed on the device, and so are fields like the title and the URL. What travels is already an unopenable blob — nothing is encrypted "after arrival".
The macOS app and Chrome extension cannot approve another device or service or expand their own scope. Your phone seals content keys into envelopes only that device can open; revocation stops future access but does not erase keys or plaintext it already obtained.
This is a holdings map, not a timeline: it answers where things sit and which key wraps which. Click any box or arrow for the full story; press Esc to close.
The same system as a timeline: from your keystrokes, through two layers of encryption and the cloud, to a second device reading it back.
What follows is the actual implementation, not an illustration. Algorithm names, lengths, and field names match the code.
| Item | Specification |
|---|---|
| Symmetric encryption | secretbox — XSalsa20-Poly1305 |
| Asymmetric encryption (envelopes) | box — Curve25519 (X25519) + XSalsa20-Poly1305 |
| Signatures | Ed25519 (the seal on every KPS frame) |
| Account Key (AK) | 32 bytes, one per account, generated on the phone. |
| fileKey | One independent key per entry, used only to seal that entry's body. |
| Content format | data_encrypted = [24B nonce] || secretbox(plaintext, fileKey, nonce) |
| Nonce rule | A fresh random 24-byte nonce on every single write, never reused. It rides in the clear at the front — a nonce is not a secret. |
| Integrity tag | Poly1305, 16 bytes. Alter one byte and verification fails; the data is rejected, not silently accepted. |
| Reading older entries | Ciphertext shorter than 40 bytes is never treated as the current format. On read, the current format is tried first and the older one only after the tag fails — a trial-decrypt, with no flag trusted. |
| Lightly encrypted fields | The title, URL, 2FA label, and tags live in data_plain, encrypted with the Account Key. The field name is historical — the contents are not plaintext. The server passes them through opaquely. |
| Per-device envelope | data_filekey = box(fileKey, apEncPk, safeEncSk) + nonceForKey |
| Account key for a device | account_key_for_ap = box(AK, apEncPk, safeEncSk) |
| Self-recovery | recovery_meta.account_key = secretbox(AK, encSk) — the server cannot open it. |
| Binding uniqueness | (safe_id, app_tag, sign_pk) |
| Versioning and concurrent writes | Every entry carries a ver counter. A write via app_set_data supplies the expected ver as a CAS check; if it changed meanwhile the server answers file_ver_conflict instead of overwriting. |
| Backups | Automatic backups are kept for 7 days and hold exactly the same ciphertext — still sealed with the Account Key and the fileKeys. |
Every claim below maps to a line in the specification table above. None of it is marketing language.
What an attacker gets: AK-encrypted metadata, fileKey-encrypted content, box envelopes, and public keys.
No master password exists on the server, and no private key capable of opening vault data is stored there. The backups hold the same ciphertext.
Frames on the wire are already ciphertext, wrapped in an Ed25519 signature. Change one byte and both the signature and the Poly1305 tag fail.
The point is not that TLS exists; it is that stripping TLS still leaves content that cannot be read or altered.
A binding is unique on (safe_id, app_tag, sign_pk), capabilities are limited to sso, app_data, and ap, and the phone approves each one.
An app without the matching envelope cannot open the ciphertext even if it holds it. Details on the SSO page.
secretbox |
One shared key both locks and unlocks, with a tamper-detecting tag attached. |
box |
An envelope addressed to one public key: only the device holding the matching private key can open it. |
| nonce | A number used exactly once. Reusing one with the same key makes both messages readable, which is why a fresh one is drawn per write. |
| Account Key (AK) | The account-wide key. It covers metadata and the recovery blob. |
fileKey |
A content key belonging to a single entry and shared with no other. |
| Safe | Your phone. The Account Key and the Safe's own keys are created here, and device authorizations are approved here. |
| AP (Access Point) | A consumer such as the macOS app or the Chrome extension. The phone grants its access and the phone takes it back. |
| KPS | KeyLockr Protocol Suite — the frame format devices speak, always signed on the outside. |