Architecture

Zero-Knowledge Architecture

How LegendPass encrypts your vault, where the keys live, and — just as important — what our encryption does not cover.

Version 1.0 · August 3, 2026

Every claim below was written from the shipping source code, including the parts that are inconvenient. A security document you cannot check is marketing. If something here turns out to be wrong, tell us at support@gammapass.com and we will correct it.

1. What we can and cannot see

Most password managers open a document like this by telling you they can see nothing. That is rarely the whole truth, so here is ours in full, at the top, before the cryptography.

Never leaves your device

  • Your master password. It is never transmitted, in any form.
  • The keys derived from it — except during a browser unlock you approve, where they are wrapped for that browser alone. Section 5.
  • Your face, palm, and gesture templates.
  • Photos, videos, and documents in the Media and Document vault — these are stored locally only and are not synced at all.

Encrypted before it leaves

  • Passwords and secure-note contents.
  • Card numbers and CVVs.
  • Bank account numbers and IBANs.
  • Two-factor (TOTP) secrets and passkey private keys.

Readable on our servers

  • Item labels: service name, username, site URL, note title, issuer.
  • Card holder name, expiry date, brand. Bank name, routing number, SWIFT.
  • Your account email and item timestamps.
  • Your master password hint, if you set one.

The third column is the one that matters. Your secrets are encrypted with a key we do not have. The labels around them — which services you have accounts with, under which usernames — are not. Section 6 lists every field, and section 10 explains what that means for you.

2. Key derivation

Your master password is never used directly as an encryption key, and it is never sent anywhere. It is stretched on your device into two separate 256-bit keys.

master password
      +
account salt  =  [your account ID] ++ [random per-account salt]
      |
      v
PBKDF2-HMAC-SHA256  ×  310,000 iterations
      |
      v
  64 bytes  ->  [ 32-byte AES-256 key ][ 32-byte HMAC-SHA256 key ]
  • 310,000 iterations of PBKDF2-HMAC-SHA256 — the figure NIST SP 800-63B gives for this function.
  • The salt is unique per account, so two people with the same master password derive different keys, and a precomputed table is useless against either of them.
  • Encryption and authentication use separate keys, cut from different halves of the derived output. Reusing one key for both is a classic footgun; we do not.
  • The 64-byte derivation buffer is zeroed in memory immediately after the two keys are split out of it.

To check that a typed master password is correct, the app decrypts a short known value — a canary — that was encrypted during setup. A wrong password fails the authentication check in section 3 and never touches your real data.

3. Vault encryption

Secrets are sealed with AES-256-CBC combined with HMAC-SHA256 in an encrypt-then-MAC construction. Encrypt-then-MAC is the ordering cryptographers recommend: the authentication tag is verified before any decryption happens, so tampered data is rejected rather than parsed.

encrypt:
  IV   = 16 random bytes  (cryptographically secure RNG, fresh every record)
  CT   = AES-256-CBC(plaintext, AES key, IV)
  MAC  = HMAC-SHA256(HMAC key, IV ++ CT)
  out  = "VENC:" ++ base64( IV ++ CT ++ MAC )

decrypt:
  recompute MAC over IV ++ CT
  MAC mismatch  ->  reject, do not decrypt
  MAC match     ->  AES-256-CBC decrypt
  • A fresh random IV per record, so encrypting the same password twice produces different ciphertext.
  • The IV is authenticated along with the ciphertext, not left unprotected.
  • A failed authentication check throws. There is no code path that decrypts unverified data.

4. Where the keys live

After derivation, the two keys are held in memory for the session and stored in the operating system's hardware-backed key store so you are not retyping your master password every time you open the app.

  • Android: encrypted preferences backed by the Android Keystore (AES-256-SIV for entry names, AES-256-GCM for values).
  • iOS: the system Keychain, marked device-only and unavailable until the device has been unlocked at least once after boot. It is never included in an iCloud or iTunes backup.
  • Keys are stored per account and wiped on sign-out. VaultCrypto.clear() also zeroes both keys in memory at that moment.

5. Sync, transport, and the browser extension

Vault items are stored locally on the device and synced through a managed Supabase Postgres database, which also handles accounts and sign-in — including Google and Apple sign-in. Encryption happens on your device before anything is handed to the network layer, so the transport is a second line of defence rather than the only one.

  • All traffic runs over HTTPS — TLS 1.3 where the device and endpoint negotiate it, TLS 1.2 at minimum.
  • Every row is keyed to your account and readable only by your authenticated session, enforced by database row-level security.
  • Crash diagnostics go through Firebase Crashlytics, and unlock notifications through Firebase Cloud Messaging. Crashlytics receives stack traces and device information; the push service receives a device token stored against your account. Neither receives vault contents, keys, or your master password.

Unlocking the browser extension. The extension holds no long-term key, so opening your vault on a desktop requires the keys to reach the browser. They travel wrapped, and the server never sees them in the clear:

browser generates an ephemeral P-256 keypair, publishes its public key
phone shows you the request, you approve it
phone generates its own ephemeral P-256 keypair
shared = ECDH(phone private, browser public)
wrapping key = HKDF-SHA256(shared, "LegendPass Browser Unlock v1")
server stores  AES-256-GCM(wrapping key, { AES key, HMAC key })  + phone public key
browser derives the same shared secret and unwraps
  • Both keypairs are ephemeral and discarded after the exchange, so a later database breach cannot unwrap a past session.
  • AES-GCM is authenticated, so a tampered payload fails to unwrap rather than yielding a wrong key.
  • Nothing happens without your approval on the phone. Denying, or simply not answering, leaves the browser with no key.
What this asks of you. The browser's public key is taken from the pairing request as presented. Approving a request you did not initiate would wrap your keys for whoever made it — so treat an unlock prompt you were not expecting as an attack, and deny it.

6. Field-by-field: what is encrypted and what is not

This is the section other vendors summarise away. Encryption is applied to the secret field of each item, not to the whole record. The labels that surround a secret sync in readable form so they can be listed, searched, and sorted.

Item typeEncrypted on your deviceStored readable (metadata)
Loginpasswordservice name, username, URL, date added
Secure notenote contenttitle, date added
Wi-Finetwork passwordnetwork name, security type, notes, date added
Payment cardcard number, CVVcardholder name, expiry date, card brand, date added
Bank accountaccount number, IBANbank name, account holder, routing number, SWIFT code, account type, notes, date added
Two-factor codeTOTP secretissuer, account name, algorithm, digit count, period, date added
Passkeycredential ID, public key, private keyrelying-party ID and name, user name and display name, notes, dates
Account setuppassword canaryaccount email, per-account salt, master password hint
Read this before you use the Notes field. On Wi-Fi, bank, and passkey entries, the free-text Notes field is metadata — it is not encrypted. The body of a Secure Note is. If you need to store something secret in free text, put it in a Secure Note.

What this means concretely. Anyone with access to our database — us under legal compulsion, or an attacker who breached it — would learn which services you hold accounts with, the usernames on them, which banks you use and their routing numbers, and when you added each item. They would not learn a single password, card number, account number, two-factor secret, or passkey private key. Those are ciphertext, and the key that opens them is derived from a master password we have never held.

Where this is going. Encrypting metadata as well is on our roadmap. It is a larger change than it sounds — search and sort currently run against those readable fields, and existing accounts need a migration — so we are not going to claim it before it ships. This page will be updated on the day it does, and the version number at the top will change with it.

7. Biometrics

LegendPass uses two different biometric mechanisms. They have different security properties and conflating them would be misleading, so here they are separately.

Device biometrics — Face ID, Touch ID, Android fingerprint. Handled entirely by the operating system. The template lives in dedicated security hardware — the Secure Enclave on Apple devices, the equivalent trusted environment on Android. LegendPass never sees it. The app receives a yes or no, nothing more.

LegendPass face, palm, and gesture recognition. These are ours, not the operating system's, and they work differently. The camera frames are processed on your device into a mathematical template. That template is written to the app's private storage — protected by the platform's file-level encryption, iOS Data Protection or Android File-Based Encryption — and never by any other app. To be precise about what it is not: these templates are not stored in the Secure Enclave, because they are not device biometrics.

  • No image of your face or palm is retained once the template is computed.
  • No template is uploaded, to our servers or anywhere else. There is no code path that transmits one.
  • Removing the registration deletes the template files. So does deleting your account or uninstalling the app.
  • All of it is optional. LegendPass works with the master password alone.

8. There is nothing for us to recover

We have no administrative override, no escrowed key, and no password reset that recovers a vault. This is not an operational gap we intend to close — it is the property that makes the rest of this document meaningful. A recovery mechanism we could invoke is a recovery mechanism an attacker could invoke, or a court could compel.

If you forget your master password, the vault cannot be opened. Not by us, not by anyone.

The optional master password hint is stored in readable form, and the app tells you so when you set it. It is a reminder, not a recovery key. Write something meaningful only to you — never the password itself, and never something that narrows it down.

9. Your device is the boundary

Zero-knowledge encryption protects your vault from us and from anyone who reaches our infrastructure. It cannot protect you from your own device once that device is compromised. If malware is running with your privileges while your vault is unlocked, it can read what you can read. No architecture changes that.

  • Keep your operating system updated, and use the device lock.
  • Choose a master password you have never used anywhere else. Length beats complexity.
  • Lock the app when you step away rather than leaving the vault open.

10. Known limitations

A security document that lists only strengths is not worth reading. These are the honest limits of the current implementation.

  • Metadata is not encrypted. Section 6, in full. This is the largest gap and we are not going to describe it as anything else.
  • No independent third-party audit yet. The design is public and checkable, but it has not been reviewed by an external firm. Until it has, treat this document as our claim rather than an audited finding.
  • AES-CBC with HMAC, not a modern AEAD. Encrypt-then-MAC over CBC is a correct construction and remains standard practice, but a dedicated AEAD such as AES-GCM or XChaCha20-Poly1305 leaves less room for implementation error. Migrating is under consideration.
  • Media and documents are local-only. Photos, videos, and documents stay in the app's private storage on one device. They are not synced, which also means they are not backed up. If you lose the device, they are gone.
  • Separation between accounts is enforced by the server, not by cryptography. Your secrets are ciphertext regardless, but the metadata in section 6 is protected by database row-level security — a server-side access-control rule rather than a key you hold. A misconfiguration there is a real risk class, and it is one you cannot verify from outside. An independent audit is how that gets checked.
  • 310,000 PBKDF2 iterations is the current NIST figure, not the strongest option available. A memory-hard function such as Argon2id resists custom-hardware attacks better. We use PBKDF2 today because it is available on every platform we ship; the iteration count is reviewed as guidance changes.

11. Reporting a vulnerability

If you find a flaw, email support@gammapass.com with enough detail to reproduce it. We will acknowledge within five business days. We will not pursue legal action against anyone who reports a genuine finding in good faith and gives us a reasonable window to fix it before publishing.

This document is maintained by GAMMA PASS LLC, Limited Liability Company, State of New Mexico, Entity ID 0008102768. Version 1.0, August 3, 2026.

Zero-knowledge

We never see your master password. Ever.

No admin override, no escrowed key, no reset that recovers a vault. If we could open yours for you, so could anyone who compromised us.

See how the app secures it
Free to start

Your vault, your key. Start free today.

No card required. Upgrade to Premium only when you want the extras.

Get LegendPass free