How to Generate a Truly Strong Password (and Why Most Aren't)
Why Your "Strong" Password Probably Isn't
Most password strength meters are theater. They count whether you used an uppercase letter, a digit, and a symbol, give you a green bar, and call it a day. `P@ssw0rd!` clears every box and shows up in the top 100 of every leaked password list ever published. `Summer2024!` does too. So does `Liverpool#1`. The meter is measuring **structure**, not **randomness** — and structure is exactly what attackers exploit.
Real password strength has one and only one definition: **entropy**, measured in bits. Entropy is the log₂ of the total number of passwords your generation process could have produced. If your process could have produced a million different passwords, that's about 20 bits of entropy. If it could have produced a quintillion, that's about 60. The higher the number, the longer an attacker has to guess.
How Attacks Actually Work
Forget the movie image of someone typing guesses into a login screen. Real attacks happen **after** a database breach, against the stolen password hashes, offline, in parallel, at terrifying speed. A modern GPU rig can test:
The attacker doesn't try random strings — they try every leaked password from every prior breach first, then dictionary words, then dictionary words with common substitutions (`a → @`, `o → 0`), then short combinations, *then* brute-force. A password like `Summer2024!` is in the first few million guesses. A truly random 16-character password from a 94-symbol set has ~104 bits of entropy — about 20 quintillion times more candidates than the entire combined attacker-known dictionary.
The Entropy Cheat Sheet
Rough guidance for entropy in bits:
For a fully random password from a mixed character pool, entropy is roughly **length × log₂(charset size)**:
| Length | lower+upper+digit (62) | + symbols (94) |
|---|---|---|
| 8 | ~48 bits | ~52 bits |
| 12 | ~71 bits | ~79 bits |
| 16 | ~95 bits | ~104 bits |
| 20 | ~119 bits | ~131 bits |
That's only true if the password is *actually* random. `Aaaaaaaa` and `R7%kQ2pXz9!` are both 8 and 12 characters but have wildly different entropies.
The Source of Randomness Matters
`Math.random()` is not a cryptographic source. Neither is any function that calls it. They're deterministic pseudo-random generators designed for graphics and games, predictable enough that two browsers can produce the same sequence. Using them to generate passwords is a critical vulnerability — and far more web tools do it than admit it.
The right source is a **CSPRNG** (cryptographically secure pseudo-random number generator):
Our [password generator](/password-generator) uses `crypto.getRandomValues()` exclusively, with unbiased rejection sampling so each character has exactly equal probability (naïve `% n` mapping introduces tiny but real bias). Everything runs in your browser — open the network tab and watch.
Passwords vs Passphrases
For passwords that live in a password manager, **random character strings** are optimal — shortest possible string for the most entropy per character. 20 characters of mixed alphanumerics and symbols is overkill for almost any service and easy to autofill.
For passwords you have to **type by hand** or **read aloud** — disk encryption, master passwords, Wi-Fi codes, root passwords, password-manager master keys — random strings are miserable. A 20-character symbol soup is nearly impossible to type without errors and impossible to dictate over a phone call. **EFF-style passphrases** are the answer: 5–7 common words separated by a delimiter (`coral-cabin-anchor-pixel-fennel`). They land at 60–90 bits of entropy with the right number of words, are dramatically easier to remember, and survive phone calls and handwritten sticky notes intact.
The Pitfalls of Filters
Many systems still impose maximum lengths (12, 16, 32), forbid certain symbols, require certain symbols, or silently truncate long passwords on storage but not on login (an entire category of bugs). Our generator gives you toggles for the common requirements: minimum one character from each chosen set, exclusion of visually similar characters (`i` / `l` / `1`, `o` / `0` / `O`), exclusion of ambiguous shell-special symbols. Use them when needed, but understand each filter costs a small number of bits of entropy. At lengths of 16+, it barely matters.
Practical Recipe
When to Regenerate
Conclusion
A strong password is a random password from a cryptographic source, long enough to put it beyond any plausible attack. Everything else — character classes, special characters, leetspeak substitutions — is theater. Use a [password generator](/password-generator) that runs locally with `crypto.getRandomValues()`, store the result in a manager, layer TOTP or WebAuthn on top, and stop spending mental energy on remembering character sequences. Spend it on the one passphrase you actually have to remember: the master key.