Introduction
In a zero-knowledge password manager, there is exactly one secret that truly matters: the master password.
Every security guarantee, cryptographic operation, and trust assumption ultimately depends on how a single secret is treated. If the master password is weak, mishandled, or misunderstood, the entire systems collapses.
This chapter explains why the master password is different from all other passwords and how is becomes the root of trust for the entire system.
Not Just Another Password
It is tempting to think of the master password as:
- A login password
- A user authentication credential
- A normal secret stored somewhere securely
This mental model is wrong.
The master password is not used to log in to a server. It is not verified directly. It is never stored.
Instead, it is raw cryptographic material.
Root of Trust Explained
A root of trust is a minimal set of elements that must be trusted absolutely because everything else depends on them.
In this system:
- If the master password is compromised -> everything is compromised
- If it is forgotten -> everything is permanently lost
- If it is weak -> brute-force becomes possible
There is no higher authority that can fix a broken root of trust.
Why the Master Password Must Never Leave the Client
Sending the master password to a server would immediately violate zero-knowledge guarantees.
If transmitted:
- It could be logged
- It could be intercepted
- It could be reused by insiders
Even hashing it on the server is unacceptable.
The master password must exist only in user-controlled memory, and only long enough to derive keys.
Key Derivation, Not Storage
The master password is never stored or compared.
Instead, it is used as input to a key derivation function (KDF) that produces:
- Encryption keys
- Authentication material
Key properties of this process:
- Deterministic: same input -> same output
- Slow: resistant to brute-force attacks
- Salted: unique per user
Once keys are derived, the master password should be discarded from memory.
Why Traditional Authentication Fails Here
In a conventional system:
- User sends password to server
- Server hashes and compares it
- Access is granted if hashes match
This model fails in a zero-knowledge system because:
- The password must never leave the client
- The serve must not gain material usable for decryption
- A database breach must not enable offline attacks
We need a different approach.
The Role of Deterministic Proofs
The server needs a way to verify that the client:
- Knows the correct master password
- Without learning the password itself
This is achieved through deterministic, derived proofs.
High-Level Idea
- Client derives an authentication key from the master password
- A verifier derived from that key is stored on the server
- On login, the client recomputes the verifier
- The server compares values – nothing more
The server verifies knowledge, not content.
What the Server Stores
In a correct design, the server stores only non-sensitive, derived data.
Typically:
- A unique salt per user
- An authentication verifier (derived value)
- An encrypted vault blob
Crucially, none of these allow:
- Decrypting the vault
- Reconstructing the master password
A server breach reveals data – but not secrets.
What Happens During Signup
On your device
- You choose master password
- Device generates random salt
- Device derives auth key
- Device derives vault key
- Device encrypts empty vault
Sent to server:
- Salt
- Auth verifier (derived value)
- Encrypted vault
Never sent:
- Master password
- Vault key
- Decrypted data
SIGNUP (Happens only once)
Input:
User enters their master password.
Master Password = "correct horse battery staple"
Step-by-step on the Client (browser / app)
Step 1: Generate a random salt
salt = random(16-32 bytes)Example:
salt = "A9F3C82D..."
Salt is NOT secret.
Step 2: Derive an AUTH KEY (slow function)
authKey = KDF (masterPassword, salt)Think:
“Run password through a slow grinder”
Example:
authKey = "9c71fa..."
Step 3: Create a VERIFIER
verifier = HASH(authKey)Example:
verifier = "b4e2d9..."
This is what the server will store.
Server CANNOT reverse this.
Step 4: Send data to SERVER
SEND → { email, salt, verifier }
What the server stores:
| Stored | Why |
|---|---|
| identify account | |
| salt | allow recomputation |
| verifier | authenticate later |
LOGIN (Happens every time)
Step 1: User enters password again
Input: "correct horse battery staple"
Step 2: Server sends SALT back
SERVER → salt = "A9F3C82D..."
Server does this because:
Without salt, client cannot recompute anything
Step 3: Client recomputes AUTH KEY
authKey = KDF(masterPassword, salt)
Important:
- Same password
- Same salt
- Same KDF
- Same authKey
Step 4: Client recomputes VERIFIER
verifier = HASH(authKey)
This verifier will be identical to signup time.
Step 5: Client sends verifier
SEND → verifier
Step 6: Server compares
if (verifier == storedVerifier):
login success
else:
reject
- Server never knew the password
- Server only checks equality
Leave a comment
Your email address will not be published. Required fields are marked *
