Generating Secure Passwords
Published · 9 min read
“Use a strong password” is the kind of advice that everyone repeats and almost nobody defines. This guide is the definition. We will look at what actually makes a password hard to crack — it is almost entirely about entropy, not about sprinkling in symbols — why machines beat humans at picking random strings, the subtle bug that weakens naive password generators, and what current standards bodies recommend. By the end you should be able to look at any password and judge it on sound principles rather than a green strength meter.
Entropy: the only number that matters
Password strength is measured in bits of entropy. One bit of entropy means an attacker who knows your strategy still faces a 50/50 guess. N bits means 2N equally likely possibilities. A fair coin flip is 1 bit. A single decimal digit is about 3.32 bits (log2 10). A lower-case letter chosen uniformly at random is log2(26) ≈ 4.7 bits.
The catch is that word uniformly. Entropy only counts if every symbol is equally likely. A human-picked “random” letter is not uniform — people over-use the middle of the keyboard and avoid letters that feel awkward — so its real entropy is well below 4.7 bits. This is the core reason computer-generated passwords are stronger than human ones at the same length: the machine actually hits the theoretical entropy, while a human does not.
To convert entropy into time-to-crack, multiply by the attacker’s guess rate. A modern GPU rig can try roughly 1010 to 1011 hashes per second on a fast algorithm. At that speed, a 40-bit password (about 8 random lower-case letters) falls in well under a minute. A 60-bit password takes years. An 80-bit password is comfortably out of reach of anything short of a nation-state. The rule of thumb: aim for at least 70–80 bits of real entropy for anything you care about.
Length beats complexity
Old password advice told you to add symbols and mixed case. That raises the alphabet size, which raises per-character entropy, but it comes at a usability cost: the password gets harder to type and harder to remember. The more important lever is length, because entropy scales linearly with length but only logarithmically with alphabet size.
Compare two passwords with roughly the same entropy:
12 chars, full ASCII set (~6.6 bits/char) ≈ 79 bits → "k9$Qv2#rLm!7"
16 chars, lower-case only (~4.7 bits/char) ≈ 75 bits → "tmvbkzplhqyrnfwx"
Both are strong. The second is easier to type and easier to select with a password manager. Doubling the alphabet size adds only one bit per character; doubling the length roughly doubles the total entropy. This is why modern guidance de-emphasizes mandatory symbols and instead asks for minimum length.
Why humans are bad at this
When you ask someone for a “random” 8-character password, you almost never get 8 uniformly
random characters. You get a dictionary word with a digit at the end, or a name with leetspeak
substitutions (“a” → “@”). Attackers know this and run
dictionaries, not brute force. A wordlist attack tries billions of the most common patterns
first — Password1!, qwerty123, names plus birth years — and cracks
an enormous fraction of real-world passwords in seconds, even though those passwords technically
satisfy “8+ chars, upper, lower, digit, symbol.”
The defense is simple: do not let humans choose. Use a generator that picks each character from a
cryptographic random source, or use a passphrase built from words chosen by such a source. The
password generator on this site uses the browser’s
Crypto.getRandomValues and runs entirely locally — the output never touches a server.
The random source: CSPRNG or nothing
Math.random() in JavaScript is not cryptographically secure. It is a fast pseudo-random
generator with a predictable internal state; if an attacker can observe a few outputs, they can
reconstruct the state and predict every future — and past — output. For passwords you must
use a CSPRNG (cryptographically secure pseudo-random number generator).
- Browser:
crypto.getRandomValues()for integers,crypto.subtlefor key material. - Node.js:
crypto.randomBytes()orcrypto.webcrypto.getRandomValues. - Python:
secretsmodule (notrandom, which is also predictable). - Go / Rust / Java:
crypto/rand,rand::rngs::OsRng,java.security.SecureRandom.
Modulo bias: the silent strength-killer
Here is a bug that has shipped in real password generators. You have a CSPRNG and you want a random
index into an alphabet of, say, 62 characters. The tempting shortcut is
index = randomByte % 62. The problem is that 256 (the number of values a byte can take) is
not evenly divisible by 62. The first 8 indices (256 mod 62 = 8 remainder) are each hit by one extra
byte value, so they are about 1.6% more likely than the rest. The bias is small but real, and it
accumulates: across a 16-character password the first few alphabet characters appear noticeably more
often, slightly reducing the real entropy below the theoretical value.
The correct approach rejects values that would introduce bias:
// Rejection sampling — no modulo bias
function unbiasedIndex(alphabetLength) {
const limit = 256 - (256 % alphabetLength); // largest multiple of N
const buf = new Uint8Array(1);
let x;
do {
crypto.getRandomValues(buf);
x = buf[0];
} while (x >= limit); // reject the biased tail
return x % alphabetLength;
}
Or, more simply, use crypto.getRandomValues to fill a buffer of 32-bit integers and reject
any value above the largest multiple of the alphabet length. The point is to never reduce a random range
with modulo when the range is not a clean divisor.
Passphrases: long, memorable, strong
A passphrase is four to seven random words strung together: correct-horse-battery-staple.
From a wordlist of 7,776 words (the EFF Diceware list),
each word contributes log2(7776) ≈ 12.9 bits of entropy. Four words give ~52 bits
(good for most consumer accounts), five give ~64, six give ~77. Passphrases are easier to type on a
phone, easier to remember briefly while you set up a password manager, and they survive being read over
the phone — none of which is true of k9$Qv2#rLm!7.
The trade-off is length: a six-word passphrase is 25–35 characters. Some legacy systems cap
password length absurdly low, which rules them out. And passphrases are only as strong as the wordlist
is random — a phrase you invented (
A unique, random, 80-bit password per site is not something a human can memorize at scale. The honest
answer is a password manager: one strong master password (a passphrase is ideal here) protecting a
vault of generated credentials. Every major manager — Bitwarden, 1Password, KeePassXC, Apple
Passwords, Chrome’s built-in manager — can generate and fill long random passwords for you.
The benefit is not just strength; it is uniqueness. When one site you use gets breached, the attackers
walk away with a hash of your password and try the same password on email, banking, and GitHub. If you
reuse passwords, one breach cascades. A manager makes reuse unnecessary, which is arguably a bigger
security win than the raw entropy.
NIST Special Publication 800-63B
(current revision) overturned much of the old “complexity rules” advice. The key
recommendations:
Note what is not on the list: there is no requirement for symbols, no maximum length cutoff,
no security questions (those are being phased out as they are guessable), and no forced expiry. If a
service you use still enforces 1990s-style rules, that is a signal its password policy has not been
updated.
The strength of a password only matters relative to how it is stored. A site that stores passwords in
plain text will leak your password no matter how strong it is. Responsible services never store the
password; they store a slow, salted hash (bcrypt, scrypt, argon2). A slow hash turns a 1011/s
GPU rig into a 104/s crawl, which is why a 60-bit password hashed with argon2 is still safe
years later while the same password hashed with unsalted MD5 is dead in minutes. You can experiment
with how hashing works (and see why MD5 is obsolete) using the
hash generator.
Strong passwords are not magic. They are the predictable result of using a real random source, picking
enough bits, and letting a machine do the choosing. Get those three things right and you are already
ahead of the vast majority of accounts on the internet.
Use a password manager
What NIST actually says now
Summer2024! → Autumn2024!). Rotate only on suspected compromise.Password1! instantly.Hashing, briefly
A practical checklist
Math.random.Related tools