Project 29, Security and auth
Client-side Password Manager
Keep logins in a vault that only your master password can open. Everything is encrypted in this tab before it is saved, so the stored data is unreadable on its own.
- Encryption
- AES-GCM 256
- Key from
- PBKDF2, 600k rounds
- Dependencies
- None
- Your browser
- Checking
Unlock your vault
Vault
Password generator
How it works
- Stretch the passwordYour master password and a random salt go through PBKDF2 600,000 times to make a 256-bit key.
- Encrypt the vaultThe whole list is turned into JSON and encrypted with AES-GCM and a fresh random IV on every save.
- UnlockOnly the salt, IV and ciphertext are stored. A wrong password fails the AES-GCM integrity check, so nothing is shown.
const salt = crypto.getRandomValues(new Uint8Array(16));
const base = await crypto.subtle.importKey("raw", new TextEncoder().encode(master), "PBKDF2", false, ["deriveKey"]);
const key = await crypto.subtle.deriveKey(
{ name: "PBKDF2", salt, iterations: 600_000, hash: "SHA-256" },
base, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
const iv = crypto.getRandomValues(new Uint8Array(12)); // new IV every save
const data = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key,
new TextEncoder().encode(JSON.stringify(vault)));
// Store salt + iv + data. A wrong password makes decrypt() throw.