Security model

This page describes what Rempar protects, how, and what it does not protect. The reference document is protocol v1, whose strings are frozen.

Goal

A complete compromise of the server, its backups and its administrator must reveal no secret: not the master password, not the content, not even the name of an item.

Key derivation (device only)

password     = NFKC(input)
master_key   = Argon2id(password, kdf_salt, m=65536 KiB, t=3, p=4, 32 bytes)
auth_key     = HKDF-SHA256(master_key, info="rempart/auth/v1")
wrap_key     = HKDF-SHA256(master_key, info="rempart/wrap/v1")
  • kdf_salt: 16 random bytes, created with the account or the local vault.
  • auth_key is sent to the server as the account password. It cannot be used to derive anything else.
  • wrap_key never leaves the device. It seals the vault key.
  • Clients refuse Argon2id parameters weaker than m=19456, t=2, p=1, even if the server offers them.

Sealing format

seal(key, plaintext, aad) = base64( 0x01 || nonce(24) || XChaCha20-Poly1305(key, nonce, plaintext, aad) )

Each use has its own frozen AAD string: rempart/vaultkey/v1, rempart/itemkey/v1|<item_id>, rempart/item/v1|<item_id>, rempart/export/v1, etc. A blob cannot be replayed in another context or attached to another item.

Vault and items

  • vault_key: 32 random bytes, created once per vault.
  • Each item has its own 32-byte item_key. The stored blob is { k: seal(vault_key, item_key), c: seal(item_key, content) }.
  • The list is displayed from a local sealed index. Opening an item only decrypts that item.
  • Item identifiers are UUID v4, bound in both AADs.

Recovery kit

32 random bytes, shown once only in Crockford base32. recovery_wrap = HKDF(recovery_key, "rempart/recovery-wrap/v1") seals a copy of the vault key; recovery_auth = HKDF(recovery_key, "rempart/recovery-auth/v1") authenticates a restoration with the server.

Account and tokens

  • Anti-enumeration pre-login: a deterministic dummy salt is returned for unknown e-mail addresses.
  • Per-device access token (60 min) and rotating refresh token (30 days). A second use of a rotated refresh token revokes the device (token_reused).
  • Optional TOTP 2FA, recommended. Mandatory for administrators.
  • All sensitive routes are rate-limited.

On the device

  • Secrets hidden behind 12 fixed dots, hidden again after 30 s.
  • Clipboard cleared after 30 s (adjustable from 10 s to 2 min). Recovery phrases are never copied as a whole.
  • Lock after 5 min, on sleep and on close; the vault key is zeroed in memory.
  • Progressive delays after failure: 30 s, 1 min, 5 min. Never any silent wipe.
  • Android: FLAG_SECURE prevents screenshots. iOS and macOS: privacy veil in the app switcher.
  • Biometrics: the vault key is entrusted to the system keychain protected by Touch ID, Face ID or fingerprint, never to a file.

What the model does not cover

  • A device compromised while the vault is open (spyware, keylogger).
  • A weak master password: Argon2id slows the attack down, it does not make it impossible.
  • The simultaneous loss of the master password and the recovery kit.
  • Account metadata: e-mail address, number of items, blob sizes, device dates and platforms.

Reporting a vulnerability

Write to security@rempar.org. We acknowledge receipt within 48 hours and publish a fix before any disclosure.


A question not answered here? support@rempar.org