Most developers know passwords should be "strong." Fewer understand exactly what that means, why it matters, or how to programmatically generate passwords that actually hold up. This guide covers all three.
What Makes a Password Weak?
Password crackers don't try every possible combination randomly. They use strategy:
Dictionary attacks — Try every word in a dictionary, plus common substitutions (p@ssw0rd, P4ssword!). This cracks most "clever" passwords instantly.
Credential stuffing — Use leaked username/password pairs from previous data breaches. If you reuse passwords, attackers already have yours.
Brute force — Try every combination. This is only feasible for short passwords.
A password like Tr0ub4dor&3 seems complex but cracks in hours against a modern GPU because it follows predictable patterns. A password like rH7!kQm2#nP9xV is far harder — it has no pattern.
Password Entropy: The Real Measure of Strength
Entropy measures how unpredictable a password is. It's calculated as:
entropy = log2(charset_size ^ password_length)
= password_length × log2(charset_size)
| Charset | Size | Example characters | |---------|------|-------------------| | Lowercase only | 26 | a-z | | Lower + Upper | 52 | a-z, A-Z | | Lower + Upper + Numbers | 62 | a-z, A-Z, 0-9 | | All printable ASCII | 95 | a-z, A-Z, 0-9, symbols |
A 12-character password using all printable ASCII has:
12 × log2(95) = 12 × 6.57 = 78.9 bits of entropy
Rough guidelines:
- < 40 bits: Very weak (crackable instantly)
- 40–60 bits: Weak (crackable in hours/days)
- 60–80 bits: Strong (years on current hardware)
- 80+ bits: Very strong (impractical to crack)
For most accounts: 12+ characters, mixed charset = good. For root passwords, API keys, and encryption keys: 20+ characters.
Generating Secure Passwords in Code
The critical rule: use a cryptographically secure random number generator (CSPRNG), not Math.random(). Math.random() is seeded predictably and is not suitable for security.
JavaScript / Node.js
function generatePassword(length = 16, options = {}) {
const {
uppercase = true,
lowercase = true,
numbers = true,
symbols = true,
} = options
let charset = ''
if (lowercase) charset += 'abcdefghijklmnopqrstuvwxyz'
if (uppercase) charset += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
if (numbers) charset += '0123456789'
if (symbols) charset += '!@#$%^&*()_+-=[]{}|;:,.<>?'
// Use Web Crypto API (browser) or crypto module (Node.js)
const array = new Uint32Array(length)
crypto.getRandomValues(array) // works in both browser and Node.js 19+
return Array.from(array)
.map(n => charset[n % charset.length])
.join('')
}
console.log(generatePassword(16))
// e.g.: "kR7!mQ2#nP9xV4@w"
Note: the modulo bias in n % charset.length is negligible for charsets of typical size and lengths used in passwords.
Python
import secrets
import string
def generate_password(length=16, use_symbols=True):
alphabet = string.ascii_letters + string.digits
if use_symbols:
alphabet += string.punctuation
# secrets module uses OS-level CSPRNG
return ''.join(secrets.choice(alphabet) for _ in range(length))
print(generate_password(16))
# e.g.: "kR7!mQ2#nP9xV4@w"
The secrets module was added in Python 3.6 specifically for generating cryptographically strong random values. Always use secrets instead of random for security-sensitive code.
Bash / Terminal
# Using /dev/urandom (Linux/macOS)
LC_ALL=C tr -dc 'A-Za-z0-9!@#$%^&*' < /dev/urandom | head -c 16; echo
# Using openssl
openssl rand -base64 24 | tr -d '=+/' | head -c 16; echo
# Using pwgen (install with: brew install pwgen)
pwgen -s -y 16 1
What to Avoid
Don't use Math.random() in JavaScript for passwords:
// WRONG — Math.random() is not cryptographically secure
const bad = Array.from({length: 16}, () => charset[Math.floor(Math.random() * charset.length)]).join('')
Don't build your own "complex" pattern:
// WRONG — predictable pattern, low entropy
const bad = word.replace('a', '@').replace('o', '0') + year + '!'
Don't use personal information:
Birthdays, pet names, sports teams, and keyboard walks (qwerty123) are all in attacker wordlists.
Password Managers
For personal use, a password manager is the right solution. It generates, stores, and auto-fills strong unique passwords for every site:
- Bitwarden — open source, free tier, self-hostable
- 1Password — polished UX, team features
- KeePassXC — fully offline, no cloud
For developers storing secrets in code: use environment variables + a secrets manager (AWS Secrets Manager, HashiCorp Vault, Doppler), never hardcode passwords.
Checking Password Strength
OWASP recommends checking passwords against a list of known-breached passwords. The Have I Been Pwned Passwords API lets you check without sending the actual password (using k-anonymity with SHA-1 prefix matching).
async function isPasswordBreached(password) {
const hash = await crypto.subtle.digest('SHA-1', new TextEncoder().encode(password))
const hex = Array.from(new Uint8Array(hash)).map(b => b.toString(16).padStart(2, '0')).join('').toUpperCase()
const prefix = hex.slice(0, 5)
const suffix = hex.slice(5)
const res = await fetch(`https://api.pwnedpasswords.com/range/${prefix}`)
const text = await res.text()
return text.split('\n').some(line => line.startsWith(suffix))
}
Try Our Free Password Generator
Use our Password Generator to create secure random passwords in your browser. It uses the Web Crypto API — no passwords are sent to any server.
Summary
- Entropy, not complexity, is what makes passwords strong — length matters most
- Use a CSPRNG:
crypto.getRandomValues()in JS,secretsmodule in Python - 12+ characters with mixed charset for regular accounts; 20+ for critical access
- Never use
Math.random()orrandommodule for security-sensitive code - Use a password manager for personal credentials; secrets manager for application secrets
References & Credits
- NIST SP 800-63B — Digital Identity Guidelines — National Institute of Standards and Technology, the definitive US standard for password and authentication policy
- OWASP Authentication Cheat Sheet — OWASP Foundation
- MDN Web Docs: Crypto.getRandomValues() — Mozilla Developer Network
- Python docs: secrets module — Python Software Foundation
- Have I Been Pwned — Pwned Passwords — Troy Hunt
- How Password Cracking Works — Bruce Schneier's Security Blog
- zxcvbn: Password Strength Estimator — Dropbox, open-source realistic password strength estimation