A site asks for a password with at least one capital, one number and one symbol. You type Summer2026!, it turns green, and you move on. The form is happy. An attacker’s cracking tool is happy too, because that’s one of the first things it tries.
Passkeys and two-factor logins are catching on, but most accounts still hang on a password. This guide covers what actually makes one strong, why some popular ways of generating them are quietly broken, and how to do it properly.
Password entropy explained
Entropy is a measure of how hard a password is to guess, counted in bits. If every character is picked at random, it’s L × log2(N), where N is how many characters you’re choosing from and L is the length.
| Length | Character set | Set size | Entropy |
|---|---|---|---|
| 8 | Lowercase | 26 | 37.6 bits |
| 8 | Letters and digits | 62 | 47.6 bits |
| 12 | Printable ASCII | 95 | 78.8 bits |
| 16 | Printable ASCII | 95 | 105.1 bits |
“Printable ASCII” means every character on a US keyboard: letters, digits, symbols and the space. Each extra bit doubles the number of guesses an attacker needs. 40 bits is about a trillion possibilities. 80 bits is about 1.2 × 1024. 128 bits is about 3.4 × 1038, far beyond what anyone can search.
There’s a catch: the formula assumes the characters really were picked at random. A password you invent has much less entropy than its length suggests, because humans love patterns and attackers know which ones.
How much entropy is enough
It depends on how the attacker gets to guess. In an online attack, they type guesses into a login form, and rate limits or lockouts stop them after a handful of tries. Even 40 bits holds up fine there.
In an offline attack, they’ve stolen a database of password hashes (the scrambled form sites store instead of the password) and can guess as fast as their hardware allows. One modern GPU computes tens of billions of MD5 or SHA-1 hashes per second, enough to work through 50 bits in a few hours. Slow password hashes such as bcrypt and Argon2 are designed to make every guess expensive, and turn those hours into years.
You can’t know how a site stores your password, so plan for the offline case. A common rule of thumb is at least 80 bits for everyday accounts and 128 for anything critical. A random 16-character password from the full printable set clears the first bar comfortably.
Why Math.random() is insecure
Plenty of password generators, online and in real codebases, use JavaScript’s Math.random(). It’s a pseudorandom number generator (PRNG): an algorithm that produces numbers that look random. It was built for speed and even spread in games and simulations. Security was never the job.
Its output can be predicted
V8, the engine inside Chrome and Node.js, implements Math.random() with an algorithm called xorshift128+. Its entire internal state is 128 bits, and that state can be worked out from a small number of outputs. Once someone has it, they can calculate every value the generator produced before and after, including the characters of your password.
It makes no security promises
A cryptographically secure PRNG (CSPRNG) guarantees that seeing any number of its outputs doesn’t help predict the next one. The JavaScript spec makes no such promise for Math.random(), and each engine can use whatever algorithm it likes.
The secure alternative: crypto.getRandomValues()
The Web Crypto API has crypto.getRandomValues(), which fills an array with numbers from a CSPRNG that the operating system seeds from hardware noise. Anything security-related in the browser should use it.
// Do not use this for passwords
function insecurePassword(length) {
const chars =
"abcdefghijklmnopqrstuvwxyz" +
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"0123456789!@#$%^&*";
let password = "";
for (let i = 0; i < length; i++) {
password += chars[Math.floor(Math.random() * chars.length)];
}
return password;
}function securePassword(length) {
const chars =
"abcdefghijklmnopqrstuvwxyz" +
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"0123456789!@#$%^&*";
const randomValues = new Uint32Array(length);
crypto.getRandomValues(randomValues);
let password = "";
for (let i = 0; i < length; i++) {
password += chars[randomValues[i] % chars.length];
}
return password;
}Spot the difference? It’s a couple of lines. But the second version stays unpredictable even to someone who has read the code and seen earlier passwords.
A small footnote for the careful reader: the % step makes a few characters very slightly more likely than others, because 232 doesn’t divide evenly by the set size. With 32-bit values and fewer than 100 characters, the effect is too small to matter.
In Node.js, reach for crypto.randomInt(max) from the built-in node:crypto module, which returns an unbiased integer, or crypto.randomBytes(). Current Node versions also have crypto.getRandomValues() available globally.
How the character set affects strength
| Character set | Size | Bits per character | 16 characters |
|---|---|---|---|
| Digits (0-9) | 10 | 3.32 | 53 bits |
| Lowercase (a-z) | 26 | 4.70 | 75 bits |
| Lowercase and uppercase | 52 | 5.70 | 91 bits |
| Letters and digits | 62 | 5.95 | 95 bits |
| Printable ASCII | 95 | 6.57 | 105 bits |
Symbols help, but they’re a pain on a phone keyboard, and some sites reject certain ones for reasons nobody can explain. Length matters more than variety. A 20-character password of just letters and digits has about 119 bits and never trips over a banned symbol.
Passphrases
A passphrase is a handful of randomly chosen words, like the famous xkcd example “correct horse battery staple”. How strong it is depends on the size of the word list and how many words you use.
The EFF’s dice word list has 7,776 words, so each word adds log2(7776) ≈ 12.9 bits. Six words give about 77 bits and eight give about 103. Both are much easier to remember than xK9#mP2$vL7@nQ4.
The words have to be picked at random, with real dice or a generator. Words you choose yourself drift toward the common and the personal (your dog’s name, your football team), and the real entropy drops sharply.
Password manager tips
Nobody can remember 200 unique random passwords. A password manager doesn’t have to. It generates, stores and fills them for you, which solves most of the problem in one go.
- Use a unique password everywhere. Then a breach at one site exposes only that one account.
- Generate at least 16 characters. The manager does the typing, so there’s no reason to go shorter.
- Pick a strong master password. A random passphrase of six or more words is long and still memorable. It’s the one password you have to keep in your head.
- Turn on two-factor authentication for the manager. A hardware security key or an authenticator app beats SMS.
- Keep an encrypted backup. Export the vault now and then and store it somewhere separate, so losing a device doesn’t mean losing everything.
- Run the security audit. Most managers flag weak, reused and breached passwords. Check the report every few months.
Common password mistakes
Dictionary words
A single word is weak, even dressed up as p@ssw0rd. Cracking tools try every word in many languages along with all the usual letter swaps, and p@ssw0rd is in every list they use.
Personal information
Names, birthdays, pets, street names and phone numbers are all a quick scroll through your social media away. Anyone targeting you will try them first.
Keyboard patterns
qwerty, 123456 and asdfghjkl are some of the most common passwords in the world. Cracking tools try keyboard walks almost immediately.
Simple transformations
Adding 123 or ! to the end, capitalising the first letter, swapping in the current year: cracking tools apply all of these rules automatically. Password1! satisfies most complexity checks and is still one of the first guesses.
Reusing passwords
This is the most dangerous habit of the lot. After a breach, attackers take the leaked email and password pairs and try them on other popular sites. That’s called credential stuffing. If your email password matches the one you used on that forum that got hacked in 2019, your email is exposed too.
Short passwords
Under 12 characters, even a fully random password is within reach of an offline attack when the site uses a fast hash. Every possible 8-character printable ASCII password can be tried in under a day on a single high-end GPU with a tool such as Hashcat.
Password strength checklist
- At least 16 characters, and 20 or more where you can.
- Generated by a cryptographically secure random generator, not made up by a person.
- A mix of uppercase, lowercase, digits and, where allowed, symbols.
- Used for this one account only.
- Stored in a password manager, not on a sticky note or in
passwords.txton your desktop. - Backed by two-factor authentication wherever it’s offered.
Using the PulpMiner password generator
The free password generator uses crypto.getRandomValues() and runs entirely in your browser, so the passwords never leave your device.
- Set the length anywhere from 8 to 128 characters. The default is 16.
- Turn uppercase, lowercase, numbers and symbols on or off. With all four on, it picks from 92 characters.
- Turn on Exclude ambiguous to drop
0 O o I l 1, the characters that look alike when you have to read a password off one screen and type it into another. - Generate up to 10 passwords at once and copy each one.
- A strength meter shows the estimated entropy in bits and how many characters it’s choosing from.
