Security model
What we cannot see, we cannot lose.
Rempar is designed so that a full server compromise reveals no secret. Here is how, without detours.
Key derivation
The master password is normalized (NFKC) then derived with Argon2id. Two sub-keys come out through HKDF: one to authenticate, one to wrap the vault key. Neither can ever recover the other.
master_key = Argon2id(password, salt, m=65536 KiB, t=3, p=4) auth_key = HKDF(master_key, "rempart/auth/v1") wrap_key = HKDF(master_key, "rempart/wrap/v1")
Per-item key
Each item has a random 32-byte key sealed by the vault key. Content is encrypted with XChaCha20-Poly1305 and the item id is bound into the authenticated data.
blob = { k: seal(vault_key, item_key), c: seal(item_key, content) } Zero knowledge
The server stores the hash of auth_key, the public KDF parameters and opaque blobs. It knows no password, no key, no item name. Pre-login returns a deterministic fake salt for unknown e-mails: no account enumeration.
Account and devices
Per-device access token, rotating refresh token. A replayed token revokes the device. TOTP 2FA (Google Authenticator) protects login. You revoke a lost device from any other.
Recovery kit
32 random bytes shown once in Crockford base32. A copy of the vault key is sealed with it. Without master password and without kit, nothing is recoverable, by anyone.
Security gestures
Secrets hidden by default, re-hidden after 30 s. Clipboard cleared after 30 s. Lock after 5 min, on sleep and on close, with the key wiped from memory. Progressive delays after failures: 30 s, 1 min, 5 min. No silent wipe.
What the server never sees
- Your master password
- The master key, the wrap key and the vault key
- The content or name of any item
- Your recovery kit
- More than 5 hash characters during a breach check