Entropy: the real measure of password strength
Forget the colored progress bars that websites use to tell you your password is "weak", "fair", or "strong". Those indicators are often misleading, based on superficial heuristics rather than cryptography. The real measure of password strength is called entropy, and it can be calculated exactly.
The mathematical formula
Password entropy is defined as:
H = log₂(N^L)
Where N is the charset size (the set of possible characters) and L is the password length. The result H is expressed in bits. The higher the bit count, the harder the password is to guess by brute force.
This formula simplifies to:
H = L × log₂(N)
Which means entropy grows linearly with length and logarithmically with charset size. That's where the counter-intuitive truth that most people miss is hiding: length increases entropy far faster than complexity does.
Concrete worked examples
Here are common configurations with their calculated entropy:
| Configuration | Charset (N) | Length (L) | Entropy (bits) |
|---|---|---|---|
| 8 lowercase letters | 26 | 8 | 37.6 bits |
| 8 alphanumeric chars | 62 | 8 | 47.6 bits |
| 8 chars, full printable ASCII | 95 | 8 | 52.6 bits |
| 12 alphanumeric chars | 62 | 12 | 71.5 bits |
| 16 lowercase chars only | 26 | 16 | 75.2 bits |
| 16 chars, full printable ASCII | 95 | 16 | 105.1 bits |
| 20 chars, full printable ASCII | 95 | 20 | 131.4 bits |
The striking lesson: 16 random lowercase letters (75 bits) beat 8 characters with symbols (52 bits). More pointedly: adding uppercase letters and symbols to an 8-character password adds only 5 extra bits, while adding one character of length (8 to 9 chars) adds 6.6 bits with the same charset. The math is unforgiving. Here is how to implement this calculation in JavaScript:
function passwordEntropy(length, charsetSize) {
// H = L * log2(N)
return length * Math.log2(charsetSize);
}
// Examples
console.log(passwordEntropy(8, 26).toFixed(1)); // 37.6 bits (lowercase)
console.log(passwordEntropy(8, 95).toFixed(1)); // 52.6 bits (all types)
console.log(passwordEntropy(16, 95).toFixed(1)); // 105.1 bits (recommended)
console.log(passwordEntropy(20, 95).toFixed(1)); // 131.4 bits (very strong)
This formula assumes the password is generated randomly by a cryptographically secure random number generator (CSPRNG). Our password generator uses window.crypto.getRandomValues() for exactly this purpose. If you're curious about what makes cryptographic randomness fundamentally different from Math.random(), our random number generator article covers why CSPRNG matters.
Attacks in practice
Understanding entropy is necessary but not sufficient. You also need to understand how attackers actually crack passwords — because most real-world attacks don't start with pure brute force.
Brute-force attack
The most naive method: systematically try every possible combination. For a charset of 95 characters and length 8, that's 95⁸ = 6,634,204,312,890,625 combinations (~6.6 quadrillion). On a modern cluster of RTX 5090s attacking an MD5 hash, you get roughly 300 billion attempts per second. 6.6 quadrillion / 300 billion = ~22,000 seconds, about 6 hours. That's already feasible for a motivated attacker in 2026.
But this speed collapses with length. For 12 characters: 95¹² ≈ 5.4 × 10²³ combinations. Even at 300 billion/sec, it would take 57 million years. Pure brute force is therefore impractical beyond roughly 10-11 characters against a weak hash — which is why attackers use far smarter methods.
Dictionary attack
Most real passwords are not truly random. They derive from common words, names, and dates. Attackers know this. The RockYou list, from a 2009 breach, contains 14 million real passwords people actually used at the time. By 2026, aggregated dictionary databases exceed 10 billion entries.
A tool like Hashcat or John the Ripper loads this list and attempts each entry against the target hash. If your password is password123, iloveyou, letmein, or any word in these lists, it falls in seconds — regardless of its apparent "complexity".
Hybrid attacks and Hashcat rules
The hybrid attack combines dictionary and brute force: take a dictionary word and append numeric suffixes or special characters. Password becomes Password1, Password123, Password!, P@ssword.
Hashcat goes further with its transformation rule system. A simple rule can transform every dictionary entry using common patterns: summer → Summer! (capitalize + exclamation), football → f00tb@ll (leetspeak substitution), or reverse a word and append the current year. Rule packs like best64.rule or OneRuleToRuleThemAll apply thousands of transformations in parallel, covering virtually every "memorization trick" people use. If you've replaced "e" with "3" and "a" with "@", Hashcat already knows.
Rainbow tables (and why salting makes them useless)
Before GPUs became ubiquitous, attackers used rainbow tables: precomputed structures of millions of (password → hash) pairs. If the hash of a password appeared in the table, the lookup was near-instantaneous. An MD5 table for passwords up to 8 alphanumeric characters could fit on a hard drive and crack passwords in seconds.
The countermeasure is called salting: a unique random value, generated when the account is created, concatenated to the password before hashing. The stored hash becomes hash(salt + password). Each account has a different salt, making any precomputed table useless — you'd need a separate table for each unique salt, which is infeasible. Salt must be at least 128 bits, generated by a CSPRNG. Today, every correctly implemented system uses salting. If you see a breach where passwords are unsalted MD5 hashes, that service was negligently insecure.
How long does a password hold? 2026 truth table
The figures below are based on a Hashcat attack on a high-performance GPU cluster (4x RTX 5090, ~300 billion hashes/sec for MD5, much slower for memory-hard algorithms). These speeds represent the worst case for the victim: a well-resourced attacker but not a nation-state.
| Password | Entropy | MD5 / SHA-1 | SHA-256 | bcrypt (cost 12) | Argon2id |
|---|---|---|---|---|---|
password |
~0 (dictionary) | < 1 second | < 1 second | < 1 second | < 1 second |
| 8 random chars, lowercase | 37.6 bits | ~2 minutes | ~15 minutes | ~6 months | Years |
| 8 random chars, full ASCII | 52.6 bits | ~5 hours | ~2 days | Centuries | Millennia |
| 12 random chars, alphanum. | 71.5 bits | ~1,500 years | ~25,000 years | Astronomical | Astronomical |
| 16 random chars, full ASCII | 105.1 bits | Impossible | Impossible | Impossible | Impossible |
| 6-word EFF passphrase | 77.5 bits | Millions of years | Practically impossible | Impossible | Impossible |
The essential message of this table: the hashing algorithm on the server side matters as much as your password. An 8-character password with symbols holds for about 5 hours against MD5 — notoriously insufficient in 2026. The same password against properly configured Argon2id holds for millennia. You don't control which algorithm the sites you use have chosen; this is why per-site uniqueness is non-negotiable.
The weak hash crisis
MD5 and SHA-1 are not "weak" in the sense of being cryptographically broken for all applications — but they are completely unsuitable for password hashing. The reason is simple: they were designed to be fast. A fast hash is exactly what an attacker needs.
The evolution of password hashing functions
The timeline of this speed war:
- Pre-2000: MD5 and SHA-1 used naively. Web databases store
MD5(password). Rainbow tables crack them in minutes once GPUs become accessible. - PBKDF2 (Password-Based Key Derivation Function 2): introduced in PKCS#5 in 2000, standardized in RFC 8018. Applies a hash (HMAC-SHA1/256) thousands of times iteratively, making each attempt more expensive. NIST SP 800-63B recommends at least 600,000 iterations with PBKDF2-SHA256 as of 2023. Weakness: still massively parallelizable on GPU.
- bcrypt (1999): designed by Niels Provos and David Mazières specifically for passwords. Uses an adjustable cost factor. Resistant to GPUs by design, optimized for slow-memory processors. Capped at 72 bytes of useful input.
- scrypt (2009): adds memory as a costly resource in addition to CPU time. ASICs and GPUs do not easily have access to large amounts of fast memory.
- Argon2 (2015): winner of the Password Hashing Competition. Three variants: Argon2d (GPU-resistant), Argon2i (side-channel attack resistant), Argon2id (recommended hybrid). Configurable parameters: memory, parallelism, iterations.
OWASP-recommended parameters for 2026
The OWASP Password Storage Cheat Sheet (updated 2025) recommends Argon2id as the first choice with these minimum parameters:
Argon2id
Memory : 64 MB (65,536 KiB)
Iterations (time cost) : 3
Parallelism : 4
Output length : 32 bytes
If Argon2id is not available in your stack, the OWASP preference order is: Argon2id > scrypt > bcrypt > PBKDF2. MD5 and SHA-1 alone are unacceptable in any context. SHA-256 alone is too — "SHA" on its own does not constitute secure password storage.
Charset: why symbols don't do everything
Traditional password policies insist: "at least one uppercase, one digit, one symbol." Let's take the math seriously.
Compare these two configurations:
| Configuration | N | L | Entropy |
|---|---|---|---|
| 12 alphanumeric chars (a-z, A-Z, 0-9) | 62 | 12 | 71.5 bits |
| 16 lowercase chars only (a-z) | 26 | 16 | 75.2 bits |
Sixteen random lowercase letters are stronger than twelve alphanumeric characters. Yet most websites would validate the second and ask users to add "at least one digit" to the first. That policy is not security — it's security theater.
The actual formula that should drive password policies: log₂(charset_size) = bits_per_character. For lowercase: 4.7 bits/char. For full printable ASCII (95 chars): 6.57 bits/char. The difference per character is less than 2 bits. Length, on the other hand, adds that same delta with every character added.
Diceware passphrases
In 1995, Arnold Reinhold described the Diceware method: choosing random words from a numbered list by rolling physical dice. Each word is selected by a 5-digit code (from 11111 to 66666 in the space of a 6-sided die), corresponding to one of 7,776 list entries (6⁵ = 7,776).
Entropy of EFF Diceware passphrases
The Electronic Frontier Foundation (EFF) published in 2016 its own list of 7,776 English words, carefully chosen to be memorable and unambiguous. The entropy calculation:
Entropy per word = log₂(7776) ≈ 12.9 bits
4 words: 4 × 12.9 ≈ 51.7 bits
5 words: 5 × 12.9 ≈ 64.6 bits
6 words: 6 × 12.9 ≈ 77.5 bits
The XKCD #936 argument ("correct horse battery staple") popularized this idea: four random words create a password with roughly 44 bits of entropy (assuming a 2,048-word dictionary) — hard to guess, easy to remember. The official EFF list, larger at 7,776 words, provides 51.7 bits for 4 words.
The critical distinction: the words must be truly random. "Dog house car sky" — four associative words you chose yourself — does not have 51 bits of entropy, because your brain is not a random number generator. Physical dice, or a CSPRNG, are. Our password generator uses window.crypto.getRandomValues() to guarantee this property.
When to use a passphrase vs. a random password
A 6-word EFF passphrase (77 bits) is ideal for your password manager master password: you must type it regularly, remember it without help, and it must be very strong. For website passwords, a 16+ character random password generated by your manager is preferable — you don't need to memorize it.
The "stupid requirements" trap
The problems with traditional enterprise password policies are well documented. They typically mandate: at least one uppercase, one digit, one symbol — but cap passwords at 16 characters maximum. They also require forced renewal every 90 days. The predictable result: users create passwords like Spring2026!, Summer2026!, Fall2026!.
These passwords satisfy all the "requirements" and are catastrophically predictable. An attacker who knows the pattern (and patterns are often guessable from previous breaches) can crack them with a Hashcat rule in seconds.
What NIST SP 800-63B says
NIST Special Publication 800-63B, published in 2017 and updated in 2024, is the US reference document on digital authentication. It says, in black and white:
- Minimum length of 8 characters for user-chosen passwords. At least 64 characters must be accepted.
- No mandatory complexity rules. "1 uppercase, 1 digit, 1 symbol" policies are not recommended as they do not significantly improve security and push users toward predictable patterns.
- No mandatory periodic rotation, except in the event of confirmed compromise. Forced 90-day renewal reduces security in practice.
- Check against compromised password lists. Services should verify chosen passwords against databases of leaked passwords (such as HaveIBeenPwned).
OWASP's Authentication Cheat Sheet echoes these guidelines and adds that password strength meters should be based on entropy calculations (tools like zxcvbn, the open-source strength estimator from Dropbox) rather than arbitrary character class requirements. Here is a minimal zxcvbn integration example:
// zxcvbn: https://github.com/dropbox/zxcvbn
import zxcvbn from 'zxcvbn';
const result = zxcvbn('correcthorsebatterystaple');
console.log(result.score); // 3 (0-4 scale)
console.log(result.guesses_log10); // ~19 (10^19 guesses)
console.log(result.crack_times_display.offline_fast_hashing_1e10_per_second);
// "centuries"
Pwned passwords: NEVER use an already-leaked password
Troy Hunt launched HaveIBeenPwned in 2013. The Pwned Passwords database contains, as of 2026, more than 13 billion passwords from real breaches. A password that appears in this list — even if it seems "strong" by conventional heuristics — is compromised by definition, because attackers have it in their wordlists.
The k-anonymity API: check without exposing
The Pwned Passwords API guarantees confidentiality through the k-anonymity protocol:
1. Compute SHA-1(your_password) → e.g. "5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8"
2. Send only the first 5 chars to the API: "5BAA6"
3. API returns a list of ~500 matching suffixes
4. Check locally whether the full suffix ("1E4C9B93F3F0682250B6CF8331B7EE68FD8")
appears in the list
5. Your plaintext password never left your device
This protocol is elegant: even the API cannot know which password you're checking — it receives only a prefix from among 2²⁰ possible prefixes. You can integrate this check with a simple fetch() call. The rule is simple: if your password appears in this database, regenerate a new one immediately, regardless of theoretical entropy.
Password spraying and credential stuffing attacks
Two attacks deserve special mention because they have nothing to do with hash cracking and bypass the entire entropy discussion.
Credential stuffing
When Disney+ launched in 2019, tens of thousands of accounts were compromised within hours of the launch. The attack was not technical: attackers simply tested email/password pairs from other breaches (LinkedIn 2012, Adobe 2013, Dropbox 2012) against the new Disney+ service. Users who had reused the same password on those services and Disney+ were immediately exposed.
This is credential stuffing: using leaked credentials from service A to attack service B. Tools like Sentry MBA and OpenBullet automate these attempts at scale, distributing requests through proxies to evade rate limits. According to Cloudflare, over 20% of all login traffic on the internet was credential stuffing in 2024.
Password spraying
The inverse variant: instead of trying many passwords on one account (which triggers lockout systems), try a small number of very common passwords against a large number of accounts. Testing Summer2026! against 10,000 accounts at a company keeps the attacker below per-account detection thresholds while statistically compromising several users.
The only effective defense against both attacks: a unique password per service. If every account has a different randomly generated password, neither credential stuffing nor password spraying can capitalize on a pre-existing breach. This is the fundamental reason why a password manager — covered in detail in our complementary password manager guide — is not a luxury but a necessity.
Special cases: PIN, master password, recovery codes
Not all "passwords" are created equal. The usage context determines the required entropy level.
The 4-digit PIN
A 4-digit PIN has only log₂(10⁴) ≈ 13.3 bits of entropy. That sounds ridiculously weak — and it is, if an attacker can try billions of combinations per second. But a PIN on a phone or bank card is protected by a hardware attempt counter: after 3 to 10 incorrect attempts, the system locks or self-destructs. With only 10 allowed attempts, even a 4-digit PIN is statistically secure (probability of guessing = 10 / 10,000 = 0.1%). Security does not come from entropy alone but from the complete threat model.
The password manager master password
This is your single point of failure. Without the benefit of an attempt counter (if an attacker obtains your encrypted vault, they can try offline), entropy must be maximized. Recommendation: minimum 6-word EFF passphrase (77 bits), more if you can. It's memorable and practically uncrackable. Avoid any pattern: no famous quote, no song lyrics, no words related to your life.
Recovery codes
Most 2FA services offer single-use recovery codes. These codes are randomly generated by the service and typically have very high entropy (100+ bits for 16+ hexadecimal character codes). They serve as last resort if you lose your second factor. The rule: print them, store them physically in a safe place (safe, trusted family member), and never store them digitally in plaintext.
The passwordless future: passkeys (WebAuthn / FIDO2)
The promise of a passwordless world is no longer theoretical. In 2026, Apple, Google, and Microsoft have all adopted passkeys as the primary authentication method on their platforms.
How passkeys work
A passkey relies on asymmetric cryptography:
- Creation: your device generates a key pair (public + private). The public key is sent to the website and stored. The private key never leaves your device — it is protected by the secure enclave of your phone or computer (Secure Enclave on Apple, TPM on Windows, Titan on Android).
- Authentication: the site sends a random challenge. Your device signs it with your private key, after verifying your presence (biometrics or PIN). The site verifies the signature with your public key. If it matches, you are authenticated.
- What's absent: no password in transit, no secret to steal server-side, no possibility of phishing (the signature is bound to the exact domain).
The underlying standard is WebAuthn (W3C) combined with the FIDO2 protocol from the FIDO Alliance. Biometrics (fingerprint, Face ID) never leave the device — they only serve to unlock the private key locally.
Adoption status in 2026
In 2026, passkeys are supported by: Apple (iOS, macOS, iCloud Keychain), Google (Android, Chrome, Google Account), Microsoft (Windows Hello, Microsoft accounts), and a growing number of third-party services (GitHub, PayPal, Adobe, Uber, X/Twitter). The transition is underway but not complete: many legacy services have not yet migrated, and some enterprise systems (Active Directory, legacy SAML) will remain on passwords for several more years.
The realistic transition: a mostly passkey world by 2028-2030, with passwords persisting as fallback on legacy systems. Until then, the best practices in this guide apply in full.
Conclusion: the golden rules synthesized
Applied cryptography gives concrete, measurable rules about passwords — not vague advice:
- Entropy first: target at least 80 bits for everyday passwords, 100+ for master passwords. Use our password generator, which calculates entropy in real time.
- Length before complexity: 16 alphanumeric characters > 8 characters with every symbol. Always.
- Truly random means CSPRNG: your brain is not a random number generator.
- Unique per service: one leaked password must not compromise any other account. Non-negotiable.
- Check against breach databases: HaveIBeenPwned, via the k-anonymity API, before adopting any new password.
- Server-side hashing: you don't control it, but you can flee services that store passwords in plaintext or as bare MD5 hashes (the visible sign: a "forgot password" email that sends your password back in cleartext).
- Passphrase for the master password: 6 EFF words minimum.
If remembering all these unique passwords sounds impossible, that's because it is — and that's precisely why a password manager is the missing piece of the puzzle. To learn everything about how to choose and adopt one (Proton Pass, Bitwarden, Dashlane, NordPass), read our complete password manager guide.