Security basics every engineer needs path · Identity · Topic 3 of 16

Passwords done right: hash, never encrypt

Not started

Store passwords so that even a full copy of your database doesn't reveal them. That means a **password hash**: a one-way function that is salted per user and deliberately slow, so checking one login costs milliseconds but testing billions of guesses costs years. Never store passwords in plain text, never encrypt them, and never use a fast hash like SHA-256 on its own.

Why it matters: Password databases leak. Whether that leak exposes your users' passwords, which they reuse elsewhere, depends almost entirely on how you stored them.

  1. 1Hash, don't encrypt

    Encryption can be reversed by whoever holds the key. A password hash can only be checked, by hashing the guess and comparing.

  2. 2Salted and slow

    A unique random salt per password stops precomputed tables and identical hashes. A deliberately slow algorithm makes each guess expensive.

  3. 3Argon2id first

    OWASP recommends Argon2id (at least 19 MiB of memory, 2 iterations, parallelism 1), then scrypt; bcrypt for legacy systems; PBKDF2 where FIPS-140 is required.

  4. 4Humane rules

    NIST SP 800-63B: at least 15 characters for passwords used alone (8 with MFA), no composition rules, no forced periodic changes, and check against known-breached lists.

1

How it works

The explanation, with examples you can run.

Why "hash" and why "slow"

To check a login you don't need the password back; you hash the attempt and compare. So there is no reason to keep anything reversible. Encryption would mean a key the server must hold, and a breach that takes the key takes every password.

General-purpose hashes such as SHA-256 are built to be fast: a GPU computes billions per second, so a stolen table of SHA-256 password hashes falls quickly. Password hashing algorithms are tuned to be expensive, and the memory-hard ones (Argon2id, scrypt) also need lots of memory per guess, which is what makes GPUs and custom hardware struggle.

Salt

A salt is a random value generated for each password and stored next to the hash. It means the same password gives different hashes for different users, and an attacker can't use a precomputed table (a "rainbow table") or crack everyone at once. This toy shows the idea, with a deliberately weak hash:

⌘/Ctrl + Enter
OutputNot run yet

Press Run to see what your code prints, in order.

Runs in this browser, in an isolated frame with no access to this page. console.log, info, warn and error are shown; code runs as a classic script, so use an async function for await.

With no salt, both users' hashes are identical, so cracking one cracks both. With salts they differ.

Which algorithm and settings

OWASP's Password Storage Cheat Sheet currently recommends:

  • Argon2id with at least 19 MiB of memory, 2 iterations and parallelism 1 (or an equivalent trade-off from its table).
  • If Argon2id isn't available, scrypt (N = 2^17, r = 8, p = 1).
  • For legacy systems, bcrypt with a work factor of 10 or more. bcrypt only uses the first 72 bytes of input, so limit length or pre-hash carefully.
  • Where FIPS-140 compliance is required, PBKDF2-HMAC-SHA-256 with 600,000 iterations or more.

Use your platform's well-maintained library; it stores the algorithm, parameters and salt in the hash string, so you can raise the cost later and rehash on the user's next login.

Rules for users

NIST SP 800-63B revision 4 reflects what breach data shows: require at least 15 characters when the password is the only factor (8 if it's part of MFA), allow at least 64, accept spaces and Unicode, don't impose composition rules (one digit, one symbol), don't force periodic changes, and do reject passwords found on blocklists of common or breached passwords. Rate-limit login attempts, and allow paste so password managers work.

2

Check yourself

3 questions. Get them all right to finish this topic.

  1. 1.Why is encrypting passwords with AES worse than hashing them with Argon2id?
  2. 2.Two users have the password "correct horse". With per-user salts, what do their stored hashes look like?
  3. 3.According to NIST SP 800-63B (revision 4), what should a verifier do about periodic password changes?

0 of 3 right so far. Get all three to finish this topic.