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:
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.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.