Why slow hashes win
When a password database is stolen, how it was stored decides how many passwords leak. Attack one yourself, with real hashing on your own device, and watch a salt and a slow hash change the outcome.
Plan for the day your database is stolen. It happens to careful teams too, and when it does, the attacker has your users table: every email address, and whatever you stored in place of each password. What you chose to store is the difference between “we were breached” and “your passwords were leaked”.
Never store the password itself. Store a hash: a one-way function of it. When someone logs in you hash what they typed and compare. Nobody can run a hash backwards.
They don’t need to. An attacker with a hash just guesses: hash 123456, compare, hash password, compare, and so on down a list of passwords real people have used before. A hash only protects anyone if guessing is too slow to finish.
- Signing up: the server picks a random salt for this user and runs the password through a deliberately slow hash.
- Only the salt and the result are stored. The password itself is never written down.
- The database leaks. The attacker has the salt too - salts are not secret - and a long list of likely passwords.
- Each guess must go through the same slow hash, with this user's salt, before it can be compared. Slow times a long list times every user is the whole defence.
Attack it yourself
Everything below uses your browser’s built-in cryptography, the same SHA-256 and PBKDF2 a server would use. The numbers are your device’s real speed. The passwords are samples: never type a real password into a page that offers to “test” it.
Start with SHA-256, no salt and run the attack. SHA-256 is an excellent hash for checking files, and a bad one for passwords, for the same reason: it’s fast. OWASP says it outright: fast hashes like SHA-256 “are not suitable for password storage” because they let attackers make huge numbers of guesses quickly.
Then try the lookup table. Nobody has to guess at all: the attacker hashed their word list once, years ago, and every unsalted database ever stolen is just a lookup.
Two users both chose 'sunshine'. Their passwords are stored as plain SHA-256. What can the attacker tell?
The same input always gives the same hash. Identical rows give away shared passwords, and a precomputed table turns each one back into the word.
Salt: one table per user
A salt is a random value made for each user and stored next to their hash. It’s mixed in before hashing, so sunshine with salt a3f9 and sunshine with salt 71bc produce unrelated hashes. NIST requires a salt of at least 32 bits.
Switch the lab to SHA-256 with a salt and try the table again: useless. The table holds hashes of bare words, and none of them had this user’s salt mixed in. The attacker has to start from scratch for this user, then again for the next. The salt isn’t secret, and doesn’t need to be. Its job is to make every user a separate problem.
But run the dictionary attack: a salted SHA-256 still falls in an instant. A salt stops shortcuts. It doesn’t slow down honest guessing.
Slow: make every guess cost
Now choose PBKDF2. It runs the hash over and over: the “rounds”. At 600,000 rounds each guess does 600,000 times the work, for the attacker and for your login page alike. A login checks one password, so a fraction of a second is fine. An attacker wants to check millions per user.
Press Measure this device and compare the “a billion guesses” column. Same machine, same browser: only the storage changed.
Your app uses PBKDF2 at 600,000 rounds with a per-user salt. What does that buy you if the database leaks?
Slow hashing doesn't make cracking impossible. It makes it expensive. Common passwords near the top of an attacker's list can still fall, which is why the next defence is not letting people choose them.
The other half: stop weak passwords at the door
The lab’s last sample, correct horse battery staple, survives every attack here because it isn’t on the list. Real lists are vastly longer, built from past breaches, and add rules like “word + year”. NIST requires services to check new passwords against “values known to be commonly-used, expected, or compromised”, including passwords from previous breaches, and reject them.
For you as a user, the habits that follow: a password manager, a different password for every site, and multi-factor sign-in wherever it’s offered. One leaked site then stays one leaked site.
Which choice does the most for users if your password table is stolen?
Slow, salted hashing makes every guess expensive, and refusing known-breached passwords removes the guesses that would succeed first. Base64 is an encoding, not protection at all.
Sources
Missions and quizzes above earn their own XP. This marks the lesson done.