A password database stores SHA-256 of the password with no salt. An attacker steals it. Quantify the attack for a 10 million row database, then explain what a per-user salt changes and what a slow hash with a work factor changes, keeping the two effects separate.

A password database stores SHA-256 of the password with no salt. An attacker steals it. Quantify the attack for a 10 million row database, then explain what a per-user salt changes and what a slow hash with a work factor changes, keeping the two effects separate.

Approach: Price a hash evaluation on commodity hardware, then treat the salt and the work factor as attacking two different parts of the cost formula.

A GPU computes billions of SHA-256 evaluations per second, so an unsalted database falls in hours and the two defences are independent: the salt removes the attacker's ability to amortise work across users, and the work factor raises the cost of each single guess. Without a salt, identical passwords produce identical digests, so the attacker sorts the file, sees which digests repeat, and cracks the whole database with one dictionary pass because a guess is tested against every row simultaneously. Precomputation is worse still: a table built once is reused against every database ever stolen. A per-user random salt of 16 bytes makes each row a separate problem, so the attacker's work multiplies by the number of rows, and a precomputed table is useless because it would have to be built per salt. The salt is not secret and does not need to be, since its only job is uniqueness. The work factor is orthogonal. A slow key derivation function such as scrypt or Argon2 with a tuned cost turns a 10 nanosecond evaluation into a 100 millisecond one, a factor of 10^7, so an offline guessing rate of 10^9 per second falls to about 10 per second per core. Memory hardness matters as well, since it denies the attacker the advantage of a GPU or an ASIC by forcing each guess to occupy megabytes.

Follow-up: You must migrate 10 million unsalted SHA-256 rows to Argon2 without asking every user to reset. What do you store during the transition?

Key concepts: salt, work factor, precomputation, password hashing.