Advanced Password Security
Understanding the technical foundations of password security helps you make better decisions about protecting your accounts. This guide covers encryption, hashing, salting, zero-knowledge architecture, and modern authentication methods.
Encryption vs Hashing
#### Encryption (Two-Way)
Encryption is reversible — data can be encrypted and then decrypted back to the original.
// Symmetric encryption example
const plaintext = "MyPassword123";
const encrypted = AES.encrypt(plaintext, key); // "U2FsdGVkX1..."
const decrypted = AES.decrypt(encrypted, key); // "MyPassword123"
Use case: Password managers encrypt your vault so you can retrieve passwords.
#### Hashing (One-Way)
Hashing is irreversible — you can hash data but cannot "un-hash" it back to the original.
// Hashing example
const password = "MyPassword123";
const hash = SHA256(password); // "ef92b3d..."
// Cannot reverse the hash to get "MyPassword123"
Use case: Websites hash passwords so even if their database is stolen, the passwords can't be read directly.
Password Hashing Algorithms
| Algorithm | Year | Status | Speed | Use Case |
| MD5 | 1992 | Broken | Fast | Don't use for passwords |
| SHA-1 | 1995 | Broken | Fast | Don't use for passwords |
| SHA-256 | 2001 | Secure | Fast | General purpose |
| bcrypt | 1999 | Secure | Slow | Password hashing ✅ |
| scrypt | 2009 | Secure | Slow | Password hashing ✅ |
| Argon2 | 2015 | Secure | Slow | Password hashing ✅ |
Salting: Why and How
A salt is random data added to a password before hashing to ensure identical passwords produce different hashes.
#### Without Salt
password: "password123"
hash: "ef92b3d7..." (same for everyone with this password)
#### With Salt
password: "password123"
salt: "x7K9mP2"
hash: bcrypt("password123" + "x7K9mP2") → "a8f3b2c..."
another user with same password:
salt: "q3W8nL5"
hash: bcrypt("password123" + "q3W8nL5") → "k9d4e7f..."
Benefits of salting:
- Same password → different hashes
- Prevents rainbow table attacks
- Makes bulk cracking much harder
Zero-Knowledge Architecture
Modern password managers use zero-knowledge architecture, meaning the server never sees your unencrypted data.
#### How It Works
- Master password → stretched into an encryption key using KDF
- Vault data → encrypted on client side before sending to server
- Server → stores only encrypted data, never sees plaintext
- Decryption → happens only on your device
// Simplified zero-knowledge flow
// 1. User enters master password
const masterPassword = "correct-horse-battery-staple";
// 2. Derive encryption key (slow, intentionally)
const encryptionKey = await deriveKey(masterPassword, {
algorithm: 'Argon2id',
iterations: 3,
memory: 65536, // 64 MB
salt: userSpecificSalt,
});
// 3. Encrypt vault locally
const encryptedVault = await AES.encrypt(vaultData, encryptionKey);
// 4. Send only encrypted data to server
await api.sync(encryptedVault);
// Server NEVER has the encryption key
Key Derivation Functions (KDF)
KDFs turn a human password into a cryptographically strong key:
| KDF | Algorithm | Memory-Hard | Recommendation |
| PBKDF2 | HMAC-based | No | Acceptable |
| bcrypt | Blowfish-based | No | Good |
| scrypt | PBKDF2-based | Yes | Better |
| Argon2id | Hybrid | Yes | Best (recommended) |
// Argon2id key derivation
const crypto = require('crypto');
const { argon2id } = crypto;
const key = argon2id({
password: 'user-master-password',
salt: Buffer.from('unique-salt-per-user'),
hashLength: 32,
time: 3, // iterations
memory: 65536, // 64 MB
parallelism: 4, // threads
});
Modern Authentication Methods
#### Passkeys (WebAuthn/FIDO2)
The future of authentication — no passwords needed:
- Public-private key pair generated per device
- Private key never leaves the device
- Uses biometric or PIN for local authentication
- Immune to phishing (domain-bound)
// WebAuthn registration
const credential = await navigator.credentials.create({
publicKey: {
challenge: new Uint8Array(32),
rp: { name: "Example App" },
user: {
id: new Uint8Array(16),
name: "user@example.com",
displayName: "User",
},
pubKeyCredParams: [{ type: "public-key", alg: -7 }],
authenticatorSelection: {
authenticatorAttachment: "platform",
userVerification: "required",
},
},
});
#### Time-based One-Time Passwords (TOTP)
// TOTP generation (what authenticator apps do)
function generateTOTP(secret, time = Date.now()) {
const counter = Math.floor(time / 30000);
const hmac = crypto.createHmac('sha1', base32Decode(secret));
hmac.update(Buffer.alloc(8));
hmac.digest().writeUInt32BE(counter);
const code = truncate(hmac.digest());
return (code % 1000000).toString().padStart(6, '0');
}
Password Security Best Practices for Developers
- Never store plaintext passwords — Always hash with bcrypt/Argon2
- Always use unique salts — One per password
- Use slow hashing — bcrypt (cost 12+) or Argon2id
- Implement rate limiting — Slow down brute-force attempts
- Support 2FA/MFA — Offer TOTP at minimum
- Check against breach databases — Use Have I Been Pwned API
- Use HTTPS everywhere — Never transmit passwords unencrypted
- Log failed attempts — Monitor for attacks
- Support passkeys — Future-proof your auth system
Using Our Tool
While implementing these security measures is for developers, everyone needs strong passwords. Our Password Generator uses the Web Crypto API for cryptographically secure random generation — the same standard used in security-critical applications.
Conclusion
Advanced password security involves multiple layers: strong passwords, proper hashing with salts, zero-knowledge architecture, and modern authentication like passkeys. By understanding these concepts, you can make informed decisions about your security. Generate cryptographically secure passwords with our Password Generator today.