EXERCISE 2 — How salt helps, and why salt alone isn't enough ============================================================= SETUP: two users, Alice and Bob, both choose the password "hunter2". WITHOUT SALT (plain hash): hash("hunter2") = 3f8a... (the SAME digest for both) Stored: alice -> 3f8a... bob -> 3f8a... Problems: 1. RAINBOW TABLES work: an attacker has a precomputed table mapping hash("hunter2") -> "hunter2". They look up 3f8a... and instantly know the password. No computation needed. 2. IDENTICAL PASSWORDS LEAK: alice and bob have the same digest, so the breach reveals they share a password — crack one, crack both, and you can see which accounts reuse popular passwords. WITH A UNIQUE PER-USER SALT: salt_alice = "x7Qp..." salt_bob = "k2Lm..." (random, 16+ bytes, stored) alice -> hash("x7Qp..." + "hunter2") = 9c11... : x7Qp... bob -> hash("k2Lm..." + "hunter2") = 4e7d... : k2Lm... HOW IT DEFEATS RAINBOW TABLES: - The precomputed table would have to be built for THIS exact salt. With a unique random salt per user, the attacker would need a separate rainbow table for every salt — astronomically infeasible. Precomputation is dead; they must attack each hash individually, online-cost per guess. HOW IT HIDES IDENTICAL PASSWORDS: - alice's 9c11... and bob's 4e7d... are DIFFERENT even though both chose "hunter2". The breach no longer reveals shared/common passwords, and cracking one tells you nothing about the other. (The salt is NOT secret — it's stored next to the hash. Its job is uniqueness/precomputation-defeat, not secrecy.) WHY SALT ALONE IS NOT ENOUGH — STILL NEED A SLOW/COST FACTOR: - Salt stops PRECOMPUTATION (rainbow tables) and identical-password leakage. It does NOT make each individual guess expensive. - If you salt but use a FAST hash (salted SHA-256), the attacker simply does an ONLINE brute force per user: for alice, try hash(salt_alice + guess) for every dictionary word — still billions/sec on a GPU. Weak passwords fall fast; the salt only forced them to target one account at a time, not to slow down per guess. - A SLOW hash (bcrypt/scrypt/Argon2) with a tunable COST makes each single guess take, say, ~250 ms instead of nanoseconds. That turns "billions per second" into "a few per second," making large-scale cracking infeasible. Memory-hardness (scrypt/Argon2) additionally defeats GPU parallelism. CONCLUSION: Salt and slowness solve DIFFERENT problems and you need BOTH: salt -> defeats precomputation + hides identical passwords (per-guess cost unchanged) slow -> makes every individual guess expensive (defeats fast brute force) Modern password hashes give you both at once (auto-salt + tunable cost).