Security · Reviewed June 2, 2026

How Vardra keeps your vault private

Vardra is zero-knowledge: your vault is encrypted on your device with a key only you can derive. We never receive your master password, your vault key, or any plaintext item. Sync moves sealed ciphertext — nothing we can read.

This page describes the cryptography that ships in the Vardra clients. The same primitives are implemented in the open vardra-core Rust crate. For the full treatment — threat model, key hierarchy, and breach analysis — read the technical whitepaper.

Zero-knowledge architecture

Encryption and decryption happen entirely on your device. The account service exists to authenticate you, distribute release builds, handle billing, and shuttle encrypted payloads between your devices. It is structurally blind to your secrets: the key that unlocks your vault is derived from your master password and never transmitted.

What the server can and cannot see

Server can see

  • Your email address and account identifiers
  • Subscription status, plan, and billing state (via Stripe)
  • Device labels and the public sync metadata needed to route updates
  • A salted, server-side Argon2id hash of your login proof (auth_hash)
  • Encrypted vault payloads — opaque ciphertext and their nonces

Server can never see

  • Your master password — it never leaves your device
  • Your vault key (K_vault) — derived locally, never transmitted
  • Plaintext passwords, cards, notes, or any item field
  • Your Secret Key (used only for new-device bootstrap and reset)
  • Your BIP-39 recovery phrase or any key that could decrypt the vault

Key derivation: Argon2id

Your master password is never used directly as a key. It is stretched with Argon2id (the memory-hard, side-channel-resistant variant; Argon2 version 1.3), which makes each guess deliberately expensive in both CPU time and memory. This is the primary defense against offline brute-force.

The login (account-auth) profile that produces your master key uses:

Algorithm
Argon2id
Memory
64 MiB
Iterations
3
Parallelism
4 lanes

The Argon2id salt is not your raw email. It is HKDF-SHA256(normalized_email, "vardra-auth-salt-v4"), producing a uniform 32-byte salt that is identical on every device of the same account — which is how your master key is reproducible from email + password alone, with no extra server-held state.

Local vaults persist their own Argon2id parameters in a sidecar at creation time. New local vaults default to a heavier profile (128 MiB, 3 iterations, 4 lanes — the OWASP-2025 recommended floor) because a stored vault file is a richer offline target than a single login.

The auth_hash / vault_key split

A single Argon2id call over your password and email salt produces a 256-bit master key, K_master. That key is never used directly. It is split with HKDF-SHA256 into two outputs that are mathematically independent — knowing one tells an attacker nothing about the other, because each uses a distinct domain-separation label:

// One expensive Argon2id call per login
K_master  = argon2id(password, hkdf(email, "vardra-auth-salt-v4"))

// Two independent HKDF outputs of K_master
auth_hash = hkdf(K_master, "vardra-auth-hash-v4")  // 32 bytes -> sent to relay
K_vault   = hkdf(K_master, "vardra-vault-key-v4")  // 32 bytes -> never leaves device

// Only auth_hash crosses the network.

auth_hash is the only login material that touches the network, and it is not stored as-is: the server stretches it again with its own server-side Argon2id and salt and stores only that. An attacker who exfiltrates the account database still has to reverse Argon2id over an unknown 256-bit input — infeasible. And because auth_hash and K_vault are non-correlated HKDF outputs, capturing the auth side never yields the vault side.

Item encryption: XChaCha20-Poly1305

Every secret field is sealed with XChaCha20-Poly1305, an authenticated encryption cipher with a 256-bit key and a 192-bit (24-byte) random nonce generated fresh for each encryption. The extended nonce size means random nonces stay collision-safe across effectively unbounded writes — no nonce counter to corrupt, no reuse risk.

Item keys are not the vault key directly. A random 256-bit Data Encryption Key (DEK) is minted once at vault creation and never rotated. Domain-specific keys (item encryption, database encryption, verification) are derived from the DEK via HKDF-SHA256, so a single compromised sub-key never exposes the others.

Each field's ciphertext carries length-prefixed Additional Authenticated Data binding it to its item ID, field label, and scheme version. The Poly1305 tag therefore fails if anyone tampers with the ciphertext or tries to move a sealed value from one field to another — integrity and authenticity, not just confidentiality.

Device wrap and key escrow

Changing your password should not re-encrypt your entire vault. Vardra solves this with key wrapping: the long-lived DEK is encrypted ("wrapped") under three independent keys, so any one of them can recover the DEK. A password change rotates the wrap, never the DEK.

  • Password wrap — DEK wrapped under K_vault, stored only in the OS keychain of the device that minted it. It never enters the synced sidecar and never leaves the device. This is the fast daily-unlock path.
  • Secret Key wrap — DEK wrapped under a key derived from your Secret Key alone. Lives in the synced sidecar and is used to bootstrap a new device or reset a forgotten password.
  • Recovery wrap — DEK wrapped under a key derived from your BIP-39 recovery seed. The last-resort path if both password and Secret Key are lost.

Every wrap is itself an XChaCha20-Poly1305 seal whose AAD is bound to the wrap's purpose, the vault UUID, and the scheme version — so a wrap produced for one slot, vault, or scheme cannot be replayed into another.

Your Secret Key is a 34-character value (Crockford base32, ambiguous letters removed) carrying ~165 bits of entropy. It is generated on-device, printed on your Emergency Kit, and acts as a second factor in key derivation: even an attacker who captures your vault file and guesses a weak password cannot derive the key without it.

Recovery model

Zero-knowledge means we cannot reset your password for you — there is no server-side copy of any key that opens your vault. Recovery is therefore something you hold, not something we grant. Vardra gives you two independent recovery paths and a clear honest trade-off.

  • Secret Key — bootstraps a new device and resets a forgotten password by unwrapping the DEK.
  • Recovery phrase — a 24-word BIP-39 mnemonic encoding 256 bits of entropy. Its built-in checksum catches transcription errors, and it can reconstruct the DEK (and, in v3 vaults, the Secret Key itself) when everything else is lost.

If you lose your master password and all recovery material, your vault is permanently unrecoverable. That is the cost of a design where no one but you can ever read your data. Keep your Emergency Kit and recovery phrase somewhere safe and offline.

Implementation hygiene

The cryptographic core is written in Rust. Secret material is held in zeroizing buffers that scrub memory on drop, key fingerprints and authentication tags are compared in constant time to avoid timing leaks, and all randomness comes from the operating system CSPRNG. HKDF and HMAC use SHA-256 throughout.

Responsible disclosure

Reporting a vulnerability

We welcome reports from security researchers and we will not pursue legal action against good-faith research conducted under this policy. If you believe you have found a vulnerability in Vardra, please email [email protected] before disclosing it publicly.

In scope

The current and planned Vardra clients, the account service at api.vardra.dev, the sync relay at relay.vardra.dev, and this website.

Please do

Test only against your own account, report promptly, give us a reasonable window to remediate, and avoid privacy violations, data destruction, or service degradation.

Please don't

Access or modify other users' data, run denial-of-service or spam tests, or publicly disclose before we have shipped a fix or 90 days have elapsed.

A machine-readable version of this policy is published at /.well-known/security.txt per RFC 9116. We aim to acknowledge reports within three business days.

Honest answers

If your servers are breached, what does the attacker get?

Ciphertext. Vault items are sealed with XChaCha20-Poly1305 under a key derived on your device. The relay only ever holds encrypted payloads, their nonces, and account metadata. Without your master password (and, for a new device, your Secret Key), the encrypted blobs are computationally infeasible to open.

Can Vardra reset my password for me?

No. We never receive your master password and we cannot derive your vault key without it. Recovery is only possible with material you control: your Secret Key or your 24-word recovery phrase. If you lose all recovery material, your vault is unrecoverable — by design.

Why send anything to the server at all?

To prove you know your password without revealing it. The client sends auth_hash — an HKDF split of your master key that is mathematically independent from your vault key. The server stretches it again with Argon2id before storing, so even a stolen database cannot be reversed into a usable credential.