WWeHelpDevs
SecurityAugust 17, 2026·8 min read

How to Generate a Secure Password (And Why Yours Are Probably Weak)

Learn what makes a password secure, how password crackers work, and how to generate strong random passwords using browser tools, code, or a password manager.

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, secrets module in Python
  • 12+ characters with mixed charset for regular accounts; 20+ for critical access
  • Never use Math.random() or random module for security-sensitive code
  • Use a password manager for personal credentials; secrets manager for application secrets

References & Credits

← All articles

Enjoyed this article?

Get new tutorials and guides in your inbox every week. Free, no spam.

Subscribe to WeHelpDevs →