Skip to content
← Blog

Password Security Best Practices for Developers

7 min readSecurity

Passwords remain the most common authentication mechanism on the internet. Despite decades of alternatives — biometrics, hardware keys, passkeys — most systems still rely on passwords as their primary or fallback authentication method. Getting password security right protects your users; getting it wrong makes headlines.

This guide covers password generation, storage, and validation from a developer's perspective.

Password Entropy

Entropy measures how unpredictable a password is. Higher entropy means more guesses required to crack it. Entropy is measured in bits:

Entropy = log2(possible_characters ^ length)
Password typeCharactersLengthEntropy
4-digit PIN10413 bits
8 lowercase letters26838 bits
8 mixed case + digits62848 bits
12 mixed + symbols951279 bits
16 mixed + symbols9516105 bits
4 random words (diceware)7,776451 bits
6 random words (diceware)7,776678 bits

Minimum recommendation: 72+ bits of entropy for important accounts. This means at least 12 characters with mixed case, digits, and symbols — or 6 random words.

Generating Strong Passwords

What makes a password strong?

  1. Length — the single most important factor. Each additional character multiplies the search space
  2. Randomness — must be generated by a cryptographic random source, not chosen by a human
  3. Uniqueness — one password per service, never reused

Why humans are bad at passwords

Humans choose predictable patterns: dictionary words, dates, keyboard patterns (qwerty), substitutions (p@ssw0rd). These patterns are in every password cracker's dictionary. A "clever" human-chosen password like Tr0ub4dor&3 has about 28 bits of entropy — far less than a random 12-character string.

Cryptographic randomness

Password generators must use a cryptographic random number generator (CSPRNG):

  • Browser: crypto.getRandomValues()
  • Node.js: crypto.randomBytes()
  • Python: secrets.token_hex()
  • Linux: /dev/urandom

Never use Math.random() or language-level pseudo-random generators — they are predictable.

Storing Passwords (Server-Side)

Never store plaintext passwords

This should be obvious, but breaches at major companies prove it is not. Never store passwords in plaintext, Base64, or reversible encryption.

Use a password hashing function

Password hashing functions are designed to be slow — they take 100ms+ per hash, making brute-force attacks impractical:

AlgorithmRecommended?Notes
Argon2idBest choiceWinner of the Password Hashing Competition. Memory-hard, resistant to GPU and ASIC attacks
bcryptGoodWidely available, CPU-hard. 72-byte input limit
scryptGoodMemory-hard and CPU-hard
PBKDF2AcceptableAvailable everywhere but GPU-parallelizable. Use with SHA-256 and high iteration count
MD5NeverFast hash, trivially cracked
SHA-256NeverFast hash, not designed for passwords

Always salt passwords

A salt is a random value added to each password before hashing:

hash = argon2id(password + salt)
store: salt + hash

Salting prevents:

  • Rainbow tables — precomputed hash lookups
  • Identical hashes — two users with the same password get different hashes

Most password hashing libraries handle salting automatically (bcrypt, Argon2id include the salt in the output).

Configuration recommendations

Argon2id: memory=64MB, iterations=3, parallelism=1 (adjust based on your server's resources)

bcrypt: cost factor=12 (adjust upward as hardware improves)

PBKDF2: iterations=600,000+ with SHA-256

Password Validation Rules

Do

  • Require a minimum length (12+ characters recommended by NIST SP 800-63B)
  • Check against a list of known breached passwords (the Have I Been Pwned API provides this)
  • Allow all printable Unicode characters, including spaces
  • Allow passwords up to at least 128 characters

Do not

  • Require specific character classes (uppercase, digit, symbol) — NIST recommends against this
  • Impose a maximum length under 64 characters
  • Force periodic password changes — NIST found this leads to weaker passwords
  • Use password hints or security questions — these leak information

NIST's research shows that composition rules (must include uppercase, digit, symbol) lead to predictable patterns like Password1!. Length and randomness are more effective than complexity rules.

Common Mistakes

  1. Logging passwords — never log request bodies that contain passwords, even in error logs
  2. Comparing with == — use constant-time comparison to prevent timing attacks
  3. Rolling your own crypto — use established libraries (bcrypt, Argon2id) rather than implementing hashing yourself
  4. Rate limiting failures — without rate limiting, an attacker can brute-force the login endpoint
  5. Password in URL — query parameters appear in server logs, browser history, and referrer headers

Generate Passwords

StackCache Password Generator creates strong passwords with cryptographic browser randomness. Configure length, character classes, and exclusion rules — everything runs locally with no server.

Try it yourself

Open the tool mentioned in this guide — it runs locally in your browser, no account needed.

Open tool