Upgrading Something You Cannot Read
Last timeEverywhere Else It Appears
You decided on better settings and a better function. The rows you already have were written with the old one, you cannot read any of them, and nobody is going to reset forty thousand passwords.
Why a batch job cannot do it
You have read the course and decided on a memory-hard function with
settings measured on your own hardware. Now look at the forty thousand
rows you already have, written years ago with a fast function and a
default repetition count.
The instinct is a batch job: read each row, compute the new value, write
it back. It does not work, and the reason is the entire point of the
first lesson. The new stored value is a function of the password. You do
not have the password. You have a one-way value derived from it, and that
is all you will ever have.
So the upgrade has to happen at the one moment the plain password passes
through your system, which is a successful login. Everything in this
lesson follows from that single constraint.
- rows converted to the new scheme
- accounts in the table
- share of accounts that log in during the period, which is well under one
The one moment you have it
The path is short. A login arrives. Read the scheme, the cost setting and
the random value from the row, as the fourth lesson insisted, and verify
with those. If verification fails, nothing happens.
If it succeeds, you are holding the plain password and you have just
proved it is correct. Compute a new stored value with the current scheme,
a fresh random value and the current settings, write the row, and carry on
serving the login.
account | scheme | cost | state
-------------|------------|-----------------|---------------------
a.okafor | argon2id | m=64MB t=3 p=1 | current, converted
t.bergstrom | pbkdf2 | 10000 rounds | old, awaiting a login
m.whitfield | argon2id | m=64MB t=3 p=1 | current, new account
the rule for each login:
read the scheme from the row, never from configuration
verify with what the row says
on success, if the scheme is not current, rewrite the row
write scheme, cost, random value and stored value as one unit
the rule for each new account:
always the current scheme, never the old oneThree mistakes are worth naming because each is common. Upgrading on a
failed login, which writes a row from an unverified password. Writing the
new stored value while leaving the old random value or cost in place,
which produces a row that cannot verify. And creating new accounts under
the old scheme because the account creation path was never changed, which
means the migration never finishes.
The lesson stops here
5 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