DevToolbox
All articles

How to Generate and Manage Strong Passwords

· 6 min read

Most developers know that "password123" is terrible. Fewer understand why length beats complexity, how a password generator actually produces randomness, or what "bits of entropy" means in practical terms. This guide answers all of that — and shows you how to store passwords safely whether you're building a login system or just managing your own accounts.

What Makes a Password Strong?

A strong password has four properties:

  1. Length. At minimum 16 characters for personal accounts; 20+ for anything sensitive. Length is the single biggest factor in resistance to brute force.
  2. Character variety. Mix lowercase letters, uppercase letters, digits, and symbols. This expands the "search space" an attacker must cover.
  3. Randomness. Generated by a machine using a cryptographically secure source, not chosen by a human. Humans are predictable — we gravitate toward words, dates, keyboard patterns, and substitutions.
  4. Uniqueness. A different password for every account. If one site is breached and attackers obtain your password hash, credential stuffing attacks try that exact password against every other site you use.

Entropy: Why Longer Is Exponentially Better

Entropy is measured in bits. Each bit doubles the number of possible passwords an attacker must try. A password drawn randomly from a 64-character alphabet has log₂(64) = 6 bits of entropy per character.

  • 8 characters × 6 bits = 48 bits → roughly 281 trillion combinations
  • 12 characters × 6 bits = 72 bits → roughly 4.7 × 10²¹ combinations
  • 16 characters × 6 bits = 96 bits → roughly 7.9 × 10²⁸ combinations

Going from 8 to 16 characters doesn't double the difficulty — it squares it, then squares it again. Modern hardware can test billions of hashed passwords per second against a leaked database. 48 bits falls in hours; 96 bits is effectively uncrackable for the foreseeable future.

Practical takeaway: 16+ random characters beats any clever 8-character pattern, regardless of how many symbols you pack in.

Passphrase vs. Random Password

A random string like kT9#mPqL!2vZxN$8 is strong but impossible to memorize. A passphrase strings together several random words: correct-horse-battery-staple. This concept was popularized by the XKCD comic #936 and remains sound advice.

Why passphrases work:

  • Four random common words drawn from a 7,776-word list (a standard dice-word list) give log₂(7776⁴) ≈ 51 bits of entropy — comparable to a strong random password.
  • Five words push that to ~64 bits; six words to ~77 bits.
  • They're typeable on a phone keyboard without switching character sets constantly.
  • They're memorable enough that you can actually recall the two or three passphrases you need to type regularly (disk encryption, password manager master password).

The critical requirement is that the words must be truly random — not a phrase that means something to you, not the first four words that come to mind. Use a passphrase generator that selects from a large word list using a CSPRNG.

How Password Generators Work

A secure password generator has one job: call a cryptographically secure pseudo-random number generator (CSPRNG) to select characters or words, then assemble them.

In a browser, the CSPRNG is crypto.getRandomValues(). It draws entropy from the operating system's randomness pool (hardware events, interrupt timing, and similar sources). The key property of a CSPRNG is that its output is statistically indistinguishable from true randomness and cannot be predicted even if an attacker knows previous outputs.

The wrong approach — one you should never use in security-sensitive code — is Math.random(). It is a pseudo-random number generator seeded from a predictable value and is explicitly not suitable for cryptographic purposes.

// Correct: cryptographically secure
function randomIndex(max) {
  const array = new Uint32Array(1);
  crypto.getRandomValues(array);
  return array[0] % max;
}

// Wrong: not cryptographically secure
function badRandomIndex(max) {
  return Math.floor(Math.random() * max); // never do this for passwords
}

Character Sets: Why All Four Matter

Many sites enforce a minimum complexity policy requiring lowercase, uppercase, digits, and symbols. This isn't just bureaucracy — it matters when someone sets a password manually rather than using a generator.

  • Lowercase only (26 chars): ~4.7 bits per character.
  • Lowercase + uppercase (52 chars): ~5.7 bits per character.
  • Lowercase + uppercase + digits (62 chars): ~5.95 bits per character.
  • All four sets, ~94 printable ASCII chars: ~6.55 bits per character.

The gain from adding symbols is real but modest — less than one bit per character. That's why length matters far more than insisting on a symbol. A 20-character lowercase-only password generated randomly is stronger than a 10-character mixed-case-plus-symbols password.

Patterns to Avoid

Even with good length and character variety, certain patterns dramatically reduce the effective entropy:

  • Dictionary words. Attackers run dictionary attacks before brute-force attacks. A single common word is cracked instantly regardless of length.
  • Leet-speak substitutions. p@ssw0rd, S3cur1ty!, H3ll0W0rld — these substitutions are well-known and included in every serious wordlist. They add almost no entropy.
  • Personal information. Name, birthdate, pet name, employer, or any data an attacker could find on social media. Targeted attacks try these first.
  • Keyboard patterns. qwerty, 123456, zxcvbn, !QAZ2wsx — all in standard cracking lists.
  • Password reuse. When any service is breached (and they will be breached), every account sharing that password is compromised. There are no exceptions.

How to Store Passwords Safely

As a user: use a password manager. It generates unique strong passwords for every site, stores them encrypted behind a single strong master password (ideally a long passphrase), and fills them in automatically. You never need to see or remember the individual passwords. Popular options include Bitwarden (open source), 1Password, and KeePassXC (local-only).

Never store passwords in a plaintext file, a notes app, a spreadsheet, or your browser's built-in save prompt if you're on a shared machine. And never email yourself passwords.

As a developer building a login system: never store passwords directly. Use a purpose-built password hashing algorithm:

  • Argon2id — the current recommended choice. Winner of the Password Hashing Competition (2015). Configurable memory and CPU cost.
  • bcrypt — widely supported, battle-tested, still fine for most applications. Use a work factor of 12 or higher.
  • scrypt — memory-hard like Argon2, available in most standard libraries.

These algorithms are deliberately slow and memory-intensive. They're designed to make bulk offline cracking expensive even if an attacker obtains your database. Never use MD5, SHA-1, or unsalted SHA-256 for passwords — they're fast by design, which is exactly wrong for this purpose.

# Python example using argon2-cffi
from argon2 import PasswordHasher

ph = PasswordHasher()
hashed = ph.hash("correct-horse-battery-staple")
# Store 'hashed' in your database

# On login:
ph.verify(hashed, supplied_password)  # raises exception if wrong

Two-Factor Authentication

Even the strongest password can be phished or leaked in a breach. Two-factor authentication (2FA) adds a second requirement — typically a time-based one-time code from an authenticator app — so that a stolen password alone isn't enough to access an account.

Think of it this way: a strong password is your first line of defence; 2FA is the backup that protects you when the first line fails. Enable 2FA on every account that supports it, prioritising email, banking, and any account with access to other accounts (your password manager, your domain registrar, your cloud hosting provider).

Summary

Strong passwords are long (16+ characters), randomly generated, unique per site, and never predictable. Passphrases offer a usable middle ground for credentials you actually need to type. Use a CSPRNG — not Math.random() — in any generator you build. Store passwords in a password manager as a user; hash them with Argon2id or bcrypt as a developer. And enable 2FA everywhere you can.

Try it free
Password Generator
100% client-side · no signup · no upload
Open tool →