THIS EXPLANATION
THE ROOM
CDA·67 Computing, Data & AI 6 MIN · 8 STATIONS

Deliberately slow password checks

A Socratic walk-through of deliberately slow password checks — reasoned out one step at a time, not lectured.

abcdefgh
a

The question we started with

THE QUESTION #

Why would a system be designed to check your password slowly, when speed is what everything else is tuned for?

Everything else on the login path is fought over in milliseconds: the handshake is optimised, the index is tuned, the page is served from an edge node. Then the one comparison that decides whether you are you is made deliberately, measurably slow — a tenth of a second of pure invented work, on every login.

The tempting reading is that this is a cost being tolerated: cryptography is expensive, and we put up with it. Let us question that. What if the slowness is not a side effect of the security but is the security — the product being bought, not the price being paid?

b

Reasoning it through

REASONING #

Start by asking where the fight actually happens. When someone tries your password on your login form, are you helpless? Not at all. You can count attempts, throttle them, lock the account, demand a second factor. An attacker going through your front door is already beaten by simple bookkeeping, and no amount of hashing slowness is what stops them.

So the slow check must be aimed elsewhere. Where? At the case you cannot police: the database has already been stolen. Now the attacker holds the stored records on their own hardware, guesses at whatever rate their silicon allows, and you never see a single attempt. Every defence that depended on watching is gone. What is left?

Only the cost of one guess. And notice the asymmetry in who pays it. You pay it once, when a real person logs in. The attacker pays it once per guess, and intends to make billions of them. The same per-unit price, multiplied by wildly different quantities — that is the entire design.

Put rough numbers on it. A general-purpose hash such as SHA-256 was built to be fast, and commodity graphics hardware computes them at something on the order of a billion per second. Tune a login check instead to about a tenth of a second, and one core manages roughly ten. Dividing those two figures gives a factor of about a hundred million. Both inputs are order-of-magnitude claims about hardware, so treat the ratio the same way — but the shape of it does not depend on the precision.

Now test whether we have the right mechanism. Suppose the real purpose of hashing were simply not storing the password in readable form. SHA-256 achieves that perfectly. Yet it is considered a serious defect to use it here. That tells us secrecy of storage and cost per guess are two different jobs, and only the second explains slowness.

Try to falsify the cost account as well. If per-guess cost were the whole story, per-record salts would be optional decoration — they add no work at all. They are mandatory. Why? Because without them one computed guess is tested against every account in the file simultaneously, and a table of common passwords can be precomputed once and reused against every stolen database forever. Salting destroys that sharing; slowness raises the price of a single guess. Two mechanisms, constantly conflated, neither substituting for the other.

One more attempted falsification, and this one bites. If slowness were only about elapsed time, iterating a fast hash a hundred thousand times would settle it — which is what PBKDF2 does. But the attacker's advantage is not clock speed, it is width: thousands of cores each running that loop independently. Raising the iteration count multiplies your cost and theirs by the same factor and leaves the ratio between one core and ten thousand untouched. Hence the modern designs charge memory: scrypt and Argon2 force each guess to fill and randomly read a sizeable working array, so parallel guessing is bounded by memory and silicon area rather than arithmetic. Argon2 was selected for this in the Password Hashing Competition in 2015.

c

The analogy

THE ANALOGY #
THE FIGURE

Think of an office that will only accept a request written out by hand, in longhand, on its own form. For the one person a day with a genuine appointment, that is a minor irritation absorbed once. For a forger who must submit a million near-identical requests to find the one that is accepted, the same rule is ruinous. The rule was not chosen despite being tedious; it was chosen because tedium is charged per attempt.

WHERE IT BREAKS DOWN

the forger can simply hire a thousand clerks and copy in parallel — which is precisely the attacker's move on a graphics card, and precisely why the better password hashes bill for scarce desk space rather than only for time.

d

Clarifying the model

THE MODEL #

The most common overstatement is that a slow hash makes a weak password safe. It does not. Stretching buys a fixed multiplier, and a multiplier of a hundred million is about twenty-seven bits, since two raised to the twenty-seventh is roughly a hundred million. Twenty-seven bits are added to whatever the password itself carries. A password sitting in the first thousand entries of a guessing list still falls in under two minutes at ten guesses a second. Stretching moves the line; it does not create strength that was never there.

Nor does any of it touch the neighbouring threats. Phishing, a keylogger, a stolen session cookie, or credential stuffing all bypass the cost entirely, because in each case the attacker makes one guess and it is right. Multi-factor authentication and rate limiting cover those; the slow hash covers the stolen file.

And the tradeoff runs both ways: work you impose on an attacker you also impose on your own servers at peak login, which is why the target is a fraction of a second and not ten — a slow hash is a denial-of-service surface pointed at yourself. Hence the cost parameter lives inside the record, as bcrypt's cost factor does, each increment doubling the work: old records verify under their old setting and can be upgraded at the next login. Specific recommended parameters date quickly and are genuinely argued over; storing the parameter is the durable idea.

e

A picture of it

THE PICTURE #
Deliberately slow password checks
Deliberately slow password checks This repurposes the packet diagram, normally used for network headers, to lay out a stored credential field by field -- read left to right as character positions in the one 60-character string kept per user. The algorithm tag and cost factor are stored openly so a future login can verify under the old setting and re-hash under a stronger one. The salt sits in the clear too, which is correct: it is not a secret, and exists only to stop one guess being tested against every account at once. Only the digest depends on the password. {"generator":"[email protected]","source":"../Socrates/.diagram-cache/_src/slow-password-checks.md","sourceIndex":1,"sourceLine":4,"sourceHash":"aa461eb6c27ff3fcdc7402d36ee51bbe60987002d18209ffecae401e30f8c1c6","diagramType":"packet","layoutVariant":"source","repairedDuplicateIds":[],"motion":"entrance-with-reduced-motion-fallback","presentation":"editorial","attempt":1,"viewBox":{"x":0,"y":0,"width":1084,"height":257},"qa":{"passed":true,"findings":[]}} algorithm tag 0 3 cost factor 4 6 salt, in the clear 7 28 digest 29 31 digest 32 59 "A stored bcrypt record, 60 characters"

How to readThis repurposes the packet diagram, normally used for network headers, to lay out a stored credential field by field — read left to right as character positions in the one 60-character string kept per user. The algorithm tag and cost factor are stored openly so a future login can verify under the old setting and re-hash under a stronger one. The salt sits in the clear too, which is correct: it is not a secret, and exists only to stop one guess being tested against every account at once. Only the digest depends on the password.

f

What became clearer

WHAT CLEARED #
WHAT CLEARED

The slowness is not a tax on the login; it is the whole product. Once you accept that the interesting attack happens on stolen data, out of your sight, the only remaining lever is the price of a single guess — and because you pay it once while the attacker pays it billions of times, a cost trivial for you is prohibitive for them. Salting, memory-hardness and a stored cost factor are three separate answers to three separate ways an attacker tries to get that price back down.

g

Where to go next

ONWARD #
  • Why a long random password from a manager makes the whole stretching argument nearly moot for that account.
  • How account lockout creates its own attack: locking out legitimate users on purpose.
h

Key terms

TERMS #
TermWhat it means
Key stretchingdeliberately inflating the work needed to turn a password into its stored form, raising the cost of each guess.
Salta unique per-record value mixed into the hash, defeating precomputed tables and cross-account reuse of a guess.
Memory-hard functionone requiring substantial memory per evaluation, limiting how many copies run in parallel on specialised hardware.

Every term the collection defines is gathered in the glossary.

Nearby on the shelf

4