Understand the mathematics of password entropy, why passphrases are both more secure and more memorable than random character passwords, and how to implement them correctly.
Security policies that mandate "at least 8 characters with uppercase, lowercase, number, and symbol" produce predictable patterns: Password1!, Welcome@2024, Company#123. These satisfy the rules but are trivially guessable.
Meanwhile, four random dictionary words — correct-horse-battery-staple — are both more secure and easier to remember. Here's the math.
Password strength is measured in bits of entropy — the base-2 logarithm of the number of possible combinations.
Entropy = log₂(alphabet_size ^ length)
| Password Type | Alphabet | Length | Entropy |
|---|---|---|---|
| All lowercase | 26 | 8 | 37.6 bits |
| Mixed case + digits + symbols | 95 | 8 | 52.6 bits |
| 4 random words (common 2,048-word list) | 2,048 | 4 words | 44 bits |
| 4 random words (Diceware 7,776-word list) | 7,776 | 4 words | 51.7 bits |
| 6 random words (Diceware) | 7,776 | 6 words | 77.5 bits |
Six Diceware words have more entropy than a 12-character mixed-character password, and are dramatically easier to remember.
Diceware is the gold standard for passphrase generation. It uses physical dice (or a CSPRNG) to index into a published word list:
3451234512 in the Diceware list → horsehorse blanket fiddle mirror stone lemonThe security comes from the randomness of the selection, not the words themselves. An attacker knows you used Diceware — they still have 7,776^6 ≈ 2.2 × 10²³ combinations to try.
The critical mistake: choosing words that "go together" (sunny beach vacation) instead of random ones.
# ❌ NOT a passphrase (predictable theme)
sunny beach vacation trip
# ✅ Correct passphrase (random words)
furnace pebble yacht democracy
If you choose words that make a story, you've reduced the search space to "phrases that make sense" — far smaller than the full word list raised to the power of the number of words.
// Using Web Crypto API (browser) or crypto module (Node.js)
async function generatePassphrase(wordCount = 5) {
const wordList = await fetch("/wordlist.txt").then(r => r.text())
const words = wordList.split("\n").filter(Boolean)
const indices = new Uint32Array(wordCount)
crypto.getRandomValues(indices)
return Array.from(indices)
.map(i => words[i % words.length])
.join("-")
}
// Never use Math.random() for security
// Math.random() is NOT cryptographically secure
const bad = Math.random() // ❌
const good = crypto.getRandomValues(new Uint32Array(1))[0] // ✅
NIST's 2017 password guidelines (updated 2024) recommend:
| Use Case | Recommendation |
|---|---|
| Human login passwords | Passphrase (memorable + strong) |
| API keys | Random base64 (32+ bytes) — humans don't type these |
| Encryption keys | Random bits directly — never human-readable |
| Master password (password manager) | Long passphrase (6+ words) |
| Temporary passwords | Random mixed-character (short-lived anyway) |
Generate a secure random passphrase instantly with HeoLab's Passphrase Generator — uses the Web Crypto API for true randomness.
Four random Diceware words provide ~50 bits of entropy — roughly equivalent to a 9-character random mixed-character password — but are far more memorable. Six words (~77 bits) is effectively uncrackable with any foreseeable computing power. Drop the complexity rules, embrace passphrases, and teach your users that length is the real security property.