Password Entropy Explained: How Strong Is Your Password Really?

Password strength is measured in bits of entropy, not symbols. Learn the formula, how long passwords take to crack, and why length beats complexity.

Most sign-up forms judge a password by a checklist: one uppercase letter, one digit, one symbol. Password1! passes every rule and is one of the first guesses any cracking tool tries. The checklist measures what a password looks like. What matters is how many guesses it takes to find it, and that is what entropy measures.

The generator below reports entropy in bits and an estimated crack time for every password it creates. It runs in your browser using crypto.getRandomValues, so the passwords never leave your device.

Password GeneratorGenerate strong random passwords in your browser, with the actual entropy in bits shown rather than a vague strength meter. Nothing is transmitted or stored.

The formula

For a password whose characters are each picked uniformly at random from a set of N characters, with length L:

entropy (bits) = L × log2(N)

Each bit doubles the number of possible passwords. A password with 60 bits of entropy is one of 2^60, about 1.15 quintillion, equally likely options. An attacker who guesses at random finds it, on average, after trying half of them.

The character set sizes that come up most often:

Characters usedSet size NBits per character
Digits only103.32
Lowercase letters264.70
Upper + lower + digits625.95
Upper + lower + digits + 27 symbols896.48
One word from a 7,776-word Diceware list7,77612.92 per word

What the numbers mean in practice

Crack time depends on how fast an attacker can guess. Two scenarios bracket reality:

  • Offline, fast hash. A database leaked and the passwords were stored with MD5, SHA-1 or unsalted SHA-256. A GPU rig can test on the order of 100 billion (10^11) guesses per second.
  • Offline, slow hash. The same leak, but passwords were stored with bcrypt, scrypt or Argon2 at a sensible cost. Throughput drops to something like 10,000 guesses per second.

Average time to find a randomly generated password, at each rate:

PasswordEntropyAt 10^11 guesses/sAt 10^4 guesses/s
6-digit PIN19.9 bitsinstantly49 seconds
8 lowercase letters37.6 bits1 second121 days
8 characters, all 8951.8 bits5.4 hours6,212 years
12 lowercase letters56.4 bits5.5 days150,646 years
12 characters, all 8977.7 bits38,895 years3.9 × 10^11 years
6 Diceware words77.5 bits33,860 years3.4 × 10^11 years
16 characters, all 89103.6 bits2.4 × 10^12 years2.4 × 10^19 years

Two things stand out. First, the hash the server uses changes the outcome by seven orders of magnitude, which is why bcrypt matters and why you cannot rely on it: you do not get to choose how a site stores your password. Second, an 8-character password with every symbol class falls in an afternoon against a fast hash, while 12 plain lowercase letters lasts days and 16 mixed characters is out of reach.

As a rough guide, under 45 bits is weak, 60 to 70 bits holds up against an offline attack on a fast hash for years, and 100 bits or more is beyond brute force for any hardware that exists.

Length beats complexity

Adding a character multiplies the search space by N. Adding a character class only increases N, and the gain is a logarithm:

  • Going from 62 to 89 characters raises each character from 5.95 to 6.48 bits, a gain of about 0.5 bits.
  • Adding one more character to the password adds a full 6.48 bits.

So one extra character is worth more than a dozen characters' worth of symbol requirements. That is the reasoning behind NIST SP 800-63B, which tells services to stop imposing composition rules and forced periodic changes, and to allow long passwords and passphrases instead.

Where entropy goes wrong in generators

A password is only as random as the code that made it. Three common flaws quietly remove bits:

  1. Math.random(). It is a fast, non-cryptographic generator. Its internal state can be recovered from a handful of outputs, after which every "random" password is predictable. Use crypto.getRandomValues in browsers or crypto.randomInt in Node.
  2. Modulo bias. bytes[i] % charset.length is uneven whenever the charset size does not divide the range of the random value. With 89 characters and a random byte, the first 78 characters come up 3 times out of 256 and the last 11 only 2 times. Rejection sampling, which throws away values from the uneven tail and draws again, removes the bias.
  3. Fixed positions for required characters. Generators that satisfy "must include a digit" by always putting the digit last give attackers structure to exploit. Place the required characters, then shuffle the whole password.
// Unbiased random index in [0, n) using rejection sampling
function randomIndex(n) {
  const limit = Math.floor(2 ** 32 / n) * n;
  const buf = new Uint32Array(1);
  do crypto.getRandomValues(buf);
  while (buf[0] >= limit);
  return buf[0] % n;
}

Excluding look-alike characters such as 0, O, l and 1 is fine, as long as the entropy figure uses the smaller set. Dropping 13 ambiguous characters from the 89-character set leaves 76, about 6.25 bits per character, so add a character or two to compensate.

Practical recommendations

  • Passwords stored in a password manager: 16 or more random characters from the full set, around 100 bits. You never type them, so length costs nothing.
  • Passwords you have to type or remember: a passphrase of 6 or more randomly chosen words, around 77 bits, or 7 words if you can manage it.
  • API keys, tokens and secrets: at least 128 bits from a cryptographic source. Generate 32 random bytes and encode them as hex or Base64url.
  • Never reuse a password. Entropy protects you from guessing, not from a site that leaks your password in plain text. A unique password per site limits the damage to that one site.

If you are on the other side, storing passwords, the strength of your users' passwords is only half the story. Hash them with a slow, salted algorithm so that even weak ones resist an offline attack. Hash a common password with SHA-256 below and you get the same digest every time, on every site, which is exactly what precomputed lookup tables exploit:

Hash & HMAC GeneratorType or paste text to see its MD5, SHA-1, SHA-256 and SHA-512 hashes at once, or switch to HMAC to sign it with a secret key. Everything runs in your browser, so neither your text nor your key leaves your device.

For other random values, such as test data, lottery-style draws or picking a sample, the random number generator uses the same unbiased source:

Random Number GeneratorGenerate random numbers in any range, as integers or decimals, with an option for no repeats. Draws come from the browser cryptographic random source rather than Math.random.

Try the tools