Password Generator & Strength Analyzer
Generate strong passwords and analyze entropy, strength, and estimated crack time
What is a Secure Password?
A secure password is a string of characters generated with sufficient randomness (entropy) to resist brute-force attacks, dictionary attacks, and credential-stuffing attempts. The strength of a password is measured in bits of entropy — the higher the entropy, the more guesses an attacker needs to crack it. NIST SP 800-63B recommends a minimum of 8 characters for user-chosen passwords, but for generated passwords, 16 or more characters drawn from a large character set provide significantly stronger protection. This tool generates cryptographically secure passwords using the Web Crypto API, ensuring that every character is selected with true randomness from a cryptographically secure pseudo-random number generator (CSPRNG).
Password Entropy Explained
Entropy quantifies the unpredictability of a password. It is calculated as
E = L × log₂(N), where L is the password length and N
is the size of the character set (the number of possible symbols for each position). A password
of 12 characters drawn from 94 printable ASCII characters has approximately 78.7 bits of entropy
(12 × log₂(94) ≈ 78.7). Each additional bit of entropy doubles the number of possible combinations
an attacker must try.
For context, a 128-bit entropy password would require 2128 guesses in a brute-force attack — roughly 3.4 × 1038 attempts. Even at one trillion guesses per second, this would take over 1019 years. Modern security recommendations suggest a minimum of 64 bits of entropy for passwords protecting non-critical accounts and 80+ bits for sensitive systems like banking, server administration, or encryption keys.
The key insight is that entropy depends on both length and character set size. A 20-character password using only lowercase letters (26 symbols) yields about 94 bits of entropy, while a 12-character password using the full 94-character printable ASCII set yields about 79 bits. Choosing the right balance between length and complexity depends on the system constraints and usability requirements.
Cryptographic Randomness with Web Crypto API
Password security depends entirely on the quality of the random number generator. JavaScript's
Math.random() is a pseudo-random number generator (PRNG) that is not
cryptographically secure — its output can be predicted if an attacker observes enough values. The
Web Crypto API provides crypto.getRandomValues(), which draws from the operating
system's CSPRNG (e.g., /dev/urandom on Linux, CryptGenRandom on Windows,
SecRandomCopyBytes on macOS). This guarantees that generated values are
computationally indistinguishable from true random numbers.
This tool uses crypto.getRandomValues() to fill a Uint32Array with
random 32-bit integers, then maps each integer to a character in the selected character set using
rejection sampling. Rejection sampling avoids modulo bias — a subtle vulnerability where
randomValue % charsetLength produces a non-uniform distribution when the charset
length does not evenly divide 232. By discarding values that fall outside the largest
multiple of the charset length, every character has an exactly equal probability of being selected.
All password generation happens entirely in your browser. No passwords are transmitted over the network or stored on any server. This client-side approach eliminates the risk of interception during transit and ensures that your generated credentials remain private by design.
Character Set Selection and Its Impact on Strength
The character set you choose directly determines the entropy per character. Here are the common character pools and their per-character entropy:
- Digits only (0-9): 10 symbols → 3.32 bits per character. A 16-digit PIN has ~53 bits of entropy.
- Lowercase (a-z): 26 symbols → 4.70 bits per character. Useful when systems restrict to letters only.
- Lowercase + Uppercase (a-z, A-Z): 52 symbols → 5.70 bits per character. Good balance for case-sensitive systems.
- Alphanumeric (a-z, A-Z, 0-9): 62 symbols → 5.95 bits per character. The most common default for password generators.
- Full printable ASCII (including symbols): 94 symbols → 6.55 bits per character. Maximum entropy density for a given length.
When special characters are included (!@#$%^&*()-_=+[]{}|;:',.<>?/~`), the character
pool jumps to 94 symbols. This means a 16-character password with full ASCII yields approximately
104.9 bits of entropy — well above the 80-bit threshold recommended for high-security applications.
However, some systems impose character restrictions. This tool lets you toggle character classes
individually so you can match the target system's requirements while maximizing entropy within
those constraints.
Password Storage Best Practices
A strong generated password is only as secure as its storage. Never store passwords in plaintext — not in databases, not in configuration files, not in spreadsheets. For application developers, passwords must be hashed using a memory-hard key derivation function before storage. The current recommended algorithms are:
- Argon2id: Winner of the Password Hashing Competition (2015). Memory-hard and resistant to GPU/ASIC attacks. Recommended by OWASP as the primary choice.
- bcrypt: Widely supported, time-tested. Limited to 72 bytes of input. Still acceptable where Argon2 is unavailable.
- scrypt: Memory-hard alternative. More complex to tune correctly than Argon2, but acceptable when properly configured.
For end users, generated passwords should be stored in a dedicated password manager (1Password, Bitwarden, KeePass) rather than memorized or written down. Password managers encrypt your vault with a single master password, letting you use unique, high-entropy passwords for every account without the cognitive burden of remembering them. Combined with multi-factor authentication (MFA), this approach provides defense-in-depth against credential theft.
Code Examples
Generating a secure password with Web Crypto API
// Cryptographically secure password generation using Web Crypto API
function generatePassword(length = 16, charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*') {
const charsetLength = charset.length;
const maxValid = Math.floor(0x100000000 / charsetLength) * charsetLength;
const randomValues = new Uint32Array(length * 2); // Extra values for rejection sampling
crypto.getRandomValues(randomValues);
let password = '';
let i = 0;
while (password.length < length) {
if (i >= randomValues.length) {
// Refill if we exhausted values due to rejections
crypto.getRandomValues(randomValues);
i = 0;
}
const value = randomValues[i++];
if (value < maxValid) {
password += charset[value % charsetLength];
}
}
return password;
}
// Generate a 20-character password with full ASCII symbols
const password = generatePassword(20);
// → "kQ7#mP2!xR9&nL4@wB5$" (example output)
// Calculate entropy: 20 × log2(70) ≈ 122.5 bits
const entropy = 20 * Math.log2(70);
console.log(`Entropy: ${entropy.toFixed(1)} bits`);Standards & Specifications
- Web Crypto API — W3C specification for cryptographic operations in browsers, including getRandomValues() for secure random generation
- NIST SP 800-63B — Digital Identity Guidelines — Authentication and Lifecycle Management, including password strength recommendations
- OWASP Password Storage Cheat Sheet — Best practices for hashing and storing passwords securely in applications
FAQ
Is generated output deterministic?
No, generated passwords use cryptographically secure random values.