Saw Tools

Password anatomy: entropy, attacks, and the math behind a secure password

Brute force, dictionary attacks, rainbow tables, Hashcat, Argon2, diceware, and passkeys — what cryptography actually says about password strength.

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:

  1. 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).
  2. 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.
  3. 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.

Frequently asked questions

How long does it take to crack a 12-character password in 2026?

It depends entirely on the hash algorithm and whether the password is truly random. Against MD5 on a cluster of RTX 5090s (~300 billion hashes/sec), a truly random 12-character alphanumeric password (71.5 bits of entropy) would take thousands of years. But if the password is in a dictionary or follows a predictable pattern, it can fall in seconds. Against properly configured Argon2id (64 MB memory, 3 iterations), even an 8-character random password is extremely costly to crack — which is why the server-side hashing algorithm matters as much as password strength itself.

Is a password with a symbol stronger than one without?

Slightly, but far less than most people believe. Expanding from 62 characters (alphanumeric) to 94 (with common symbols) adds roughly 0.6 bits of entropy per character — about 5 bits total for an 8-character password. Adding just one extra character of length (8 to 9 chars) adds 6 bits with the same charset. Length beats complexity, mathematically and always. A 16-character password using only lowercase letters (75 bits) is stronger than a 12-character password with all character types (71.5 bits) — and far stronger than a "complex" 8-character one (52 bits).

Is a 5-word passphrase really equivalent to a 16-character random password?

No — it is weaker in raw entropy terms, but still very strong. With the EFF word list of 7,776 words, 5 words yield log₂(7776⁵) ≈ 64.6 bits, versus 105 bits for 16 characters from the full 95-character ASCII printable set. The passphrase is far more memorable and remains very secure for most use cases. For a password manager master password, aim for 6 EFF words (77.5 bits) or more. For website passwords, let your manager generate random 16+ character strings you don't need to remember.

How do I check whether my password is in a data breach?

Use the k-anonymity API at HaveIBeenPwned (haveibeenpwned.com/passwords). Your client computes the SHA-1 hash of your password, sends only the first 5 hexadecimal characters to the API, receives roughly 500 matching suffixes, and checks locally. Your plaintext password never leaves your device. The database holds over 13 billion leaked passwords as of 2026. If your password appears there, change it immediately — its presence in attacker wordlists nullifies any theoretical entropy advantage.

Will passkeys really replace passwords?

Yes, gradually and inevitably. Passkeys (WebAuthn / FIDO2) are superior to passwords on every dimension: impossible to phish (the signature is bound to the exact domain), nothing to guess (256-bit private key generated on-device), nothing to leak server-side (only the public key is stored). Apple, Google, and Microsoft have been actively deploying passkeys since 2023. In 2026, major services support them. Full transition will take another 3 to 5 years as legacy systems migrate. Until then, a good password manager remains the best protection available to most users.