A password manager is security-critical software. Every design decision either exposes user secrets or protects them. The central architectural constraint is zero-knowledge: the server must never see plaintext passwords or vault contents.
Zero-Knowledge Architecture
Zero-knowledge means all encryption and decryption happens on the client. The server stores only ciphertext it cannot read. Even if the server is fully compromised, user passwords remain safe. Authentication to the server is handled separately from vault decryption — knowing your account credentials does not give the server the key to your vault.
Master Password and Key Derivation
The master password is never stored anywhere. Instead it is passed through a key derivation function (KDF) to produce the encryption key. Use PBKDF2-SHA256 or Argon2id. Argon2id is preferred for new systems — it is memory-hard, which makes GPU-based brute-force expensive.
Key derivation inputs: master password + user-specific salt (stored on server, not secret). Output: a 256-bit symmetric key used to encrypt the vault. The salt prevents precomputed rainbow table attacks across accounts.
For server authentication, derive a separate authentication key from the master password using a different salt or domain separation string. Never reuse the encryption key for authentication.
Vault Encryption
Vault items are encrypted with AES-256-GCM. GCM provides both confidentiality and integrity — tampering with ciphertext produces an authentication failure on decryption, not corrupted data.
Each item gets a unique IV (initialization vector). Never reuse an IV with the same key. Generate IVs with a cryptographically secure random number generator.
Item Storage Schema
Server-side table for vault items:
vault_items
id UUID, primary key
user_id UUID, foreign key
type ENUM('login','note','card','identity')
encrypted_payload BLOB -- AES-256-GCM ciphertext
iv BINARY(12)
updated_at TIMESTAMP
deleted BOOLEAN
The server sees only the type enum and timestamps. The payload — URL, username, password, notes — is opaque ciphertext. Soft deletes (deleted flag) allow sync to propagate removals without losing history.
Sync Protocol
Sync is client-initiated. On connect, the client sends its last-sync timestamp. The server returns all items with updated_at greater than that timestamp. The client decrypts each item locally and merges into its local store using last-write-wins on updated_at.
Conflict resolution: if two devices edit the same item offline, the one with the later updated_at wins. For safety, keep the losing version as a revision so the user can recover it. All merge logic runs on the client against encrypted blobs — the server just stores and serves them.
Autofill Browser Extension
The browser extension communicates with a local companion app (native messaging) that holds the unlocked vault in memory. The extension reads the current page origin, queries the companion for matching login items, and injects credentials into form fields.
Match logic: normalize the page URL to its eTLD+1 (e.g., accounts.google.com → google.com) and compare against stored URL patterns. Substring matching on domain, not full URL, to handle login subdomains.
Breach Detection via k-Anonymity
To check whether a stored password appears in known breach dumps, use the HaveIBeenPwned Pwned Passwords API with k-anonymity. The client hashes the password with SHA-1, sends the first 5 hex characters to the API, and receives back all hashes that share that prefix. The client then checks locally whether its full hash is in the response. The server never learns the full hash of any password.
Sharing Between Users
Sharing a vault item with another user requires asymmetric encryption. Each user has an RSA or EC key pair; the public key is stored on the server. To share an item, the sender re-encrypts the item symmetric key with the recipient public key and sends the wrapped key to the server along with the ciphertext. The recipient decrypts the wrapped key with their private key, then decrypts the item. The server never has access to either key.
Key Points
- Zero-knowledge: all encryption client-side, server stores only ciphertext
- Master password → Argon2id → AES-256-GCM vault key, never stored
- Unique IV per item, stored alongside ciphertext
- Sync: last-write-wins on updated_at, client-side merge
- Breach check: k-anonymity prefix query, no full hash sent to server
- Sharing: asymmetric key wrapping, recipient decrypts with private key
FAQ: Password Manager
What is a zero-knowledge password manager architecture?
A zero-knowledge architecture means the server never has access to unencrypted user data. All encryption and decryption happens client-side using a key derived from the master password. The server stores only ciphertext and cannot read vault contents even if compromised. The service provider has zero knowledge of the plaintext passwords stored by users.
How does master password-based encryption work (PBKDF2/Argon2)?
The master password is never stored directly. Instead, a key derivation function (KDF) such as PBKDF2 or Argon2 stretches the master password into a strong cryptographic key using a salt. PBKDF2 applies HMAC-SHA256 many thousands of times to increase brute-force cost. Argon2 is memory-hard, making GPU attacks expensive. The derived key encrypts the vault with AES-256. A separate authentication hash is sent to the server for login verification, keeping the encryption key entirely client-side.
How do you sync vault data across devices without the server seeing plaintext?
The vault is encrypted on the client before being uploaded. Each device downloads the ciphertext and decrypts it locally using the master-password-derived key. Sync conflicts are resolved using timestamps or vector clocks on encrypted blobs. The server acts as a dumb storage layer — it stores, versions, and serves opaque encrypted payloads without any ability to inspect their contents.
How does breach detection work using k-anonymity?
To check whether a password appears in a breach database without revealing it to the server, the client hashes the password with SHA-1, sends only the first 5 characters of the hash to the API, and receives back all hashes sharing that prefix. The client then checks locally whether the full hash is in the returned list. This k-anonymity model means the server never learns which specific password was queried, preserving user privacy while enabling breach detection.
See also: Atlassian Interview Guide
See also: Scale AI Interview Guide 2026: Data Infrastructure, RLHF Pipelines, and ML Engineering