Generate secure customized passwords and evaluate cryptographic entropy.
How password strength is actually calculated, why the random source matters, and which practices NIST retired.
For a password drawn at random from an alphabet of N symbols with length L, entropy is H = L × log2(N) bits. Across the 94 printable ASCII characters, log2(94) ≈ 6.55 bits per character: 12 characters yield 78 bits and 16 characters yield 105 bits. Shrink the alphabet to lowercase letters and digits (N = 36, 5.17 bits per character) and you need 21 characters to reach the same 105 bits. The formula only holds when every character is drawn independently and uniformly: "Summer2024!" is 11 characters long, yet its effective entropy sits near 20 bits because it follows a pattern hashcat rules reproduce in seconds.
Math.random() in V8 uses xorshift128+, a generator with 128 bits of state built for speed. It returns 52-bit doubles, and its internal state can be reconstructed from a handful of consecutive outputs, letting an attacker predict the sequence in both directions. The correct primitive is crypto.getRandomValues(), fed by the operating system CSPRNG. One classic mistake survives even then: bytes[i] % alphabet.length introduces modulo bias whenever 256 is not a multiple of the alphabet length. With 94 characters, 256 = 2 × 94 + 68, so the first 68 symbols appear with probability 3/256 and the remaining 26 with 2/256, a third less often. The fix is to reject bytes above the largest clean multiple and resample.
The NIST SP 800-63B revision dropped three inherited habits: mandatory composition rules (at least one uppercase, one digit and one symbol), scheduled expiry without evidence of compromise, and knowledge-based security questions. Instead it requires accepting 8 to at least 64 characters, allowing all printable ASCII plus Unicode, never truncating the input, and screening every new password against breached-credential lists. For storage it demands a salted key derivation function with a tunable cost factor — PBKDF2, bcrypt, scrypt or Argon2id — never bare SHA-256, plus rate limiting on failed attempts. Forced rotation is reserved for cases where a breach is actually suspected.
It depends on how the hash is stored. A modern GPU tries on the order of 10^11 candidates per second against unsalted MD5 or SHA-1, but only a few thousand per second against bcrypt at cost factor 12. Below 50 bits a password falls within days against a fast hash; 80 bits rules out any realistic offline attack, and 128 bits is the usual margin for master passwords and signing secrets.
The same formula compares them. Six words drawn at random from the 7776-entry Diceware list give 6 × log2(7776) ≈ 77.5 bits, essentially matching 12 random full-ASCII characters (78 bits). The passphrase takes about 28 characters to type but is memorable; the short string is preferable when a password manager holds it. What matters is that the words come from a CSPRNG rather than from human choice.
Growing the alphabet from 62 to 94 characters adds log2(94/62) ≈ 0.6 bits per character: on a 12-character password that is roughly 7 bits, the same as appending one more character. Substitutions such as "a" to "@" or "o" to "0" add nothing measurable, because dictionary attacks apply exactly those mutation rules before falling back to brute force. Extra length always beats extra complexity.