The One Place Slowness Is the Feature
Last timeTwo People, One Hash
Once the attackers work is per account, the cost of one guess becomes the whole defence. Here is how to choose that cost from a measurement rather than from a number somebody posted.
Why the asymmetry works
The previous lesson removed the attacker's ability to share work across
accounts. That matters because it makes the next question meaningful: what
does one guess cost?
Count the computations on each side. You compute the stored value once,
when somebody logs in successfully. The attacker computes it once per
candidate password, per account, and from the second lesson the candidate
count runs into the thousands of millions.
So a cost you add is multiplied by an enormous number on their side and by
roughly your login rate on yours. That ratio is the entire mechanism, and
it is the only place in engineering where making something slower is the
correct answer rather than a bug.
Put real figures on it. A fast one-way value takes about a tenth of a
microsecond, so a rented card manages around ten thousand million a
second. Set the cost so that one computation takes a quarter of a second
and the same card manages four. That is a factor of two and a half
thousand million, and the price is a quarter of a second added to a login
that already involves a network round trip.
- processor seconds required per second, which is effectively a core count
- logins per second at the peak you intend to survive
- time one verification takes, which is the setting you are choosing
Cost is a setting
The slowness is not a property of the function. It is a number you pass to
it, and the whole design exists so that the number can be raised later
without anybody changing their password.
Three shapes of setting are in use. A repetition count, which says apply
the inner function this many times. A cost factor, which is a power of two
giving the repetitions. And a time-and-memory pair, where the second
number is the subject of the next lesson.
In every case the setting is stored alongside each stored password, in the
same row, next to the random value from the previous lesson. That is what
makes the scheme adaptable: rows written in different years hold different
settings, each row is verifiable with its own, and nothing breaks when you
raise the number for new rows.
field | value | secret
---------------|------------------------------|-------
scheme | the function and version | no
cost setting | repetitions, or time and room | no
random value | 16 bytes, fresh per account | no
stored value | the output of the function | yes, in the sense that it must not be reversible
written out, one row is a single string:
scheme, then cost, then random value, then stored value,
separated so that each field can be read back
on verification, read the scheme and cost from the row,
not from configuration, or old rows stop verifyingReading the setting from the row rather than from your configuration is
the detail people get wrong, and it fails in the most inconvenient way:
everything works until the day you raise the number, after which every
account created before that day cannot log in.
The lesson stops here
3 more paragraphs to go
You have read the opening. The rest of the argument, the problems that check whether it landed, and the lines worth keeping at the end all come with a plan.
The first lesson of every course in the library reads the whole way through, free, so you can see exactly what the rest of them are.
See the planThe contentsThis is the reading half
Starting the course gives you your own copy of it. Every idea on every page has problems standing under it, marked with a reason rather than a tick, and any sentence you do not believe can be opened and argued with. None of that can happen on a page nobody owns.
The contents