3 ms·
On your `User` table you have a column such as `hashing_scheme`. If you don't have one of these columns already, create it with the default value of your curren
by saulr 11y ago
On your `User` table you have a column such as `hashing_scheme`. If you don't have one of these columns already, create it with the default value of your current scheme (e.g., `bcrypt`)
When a user attempts to log in, you hash the password they submitted with whatever's in that user's `hashing_scheme`. If the password was incorrect, fail early.
If the password was correct, and this user's `hashing_scheme` value is different to the application's `current_hashing_scheme`, you rehash the user's password (that you got via the POST request or otherwise) with the new scheme, update the `password_hash` and `hashing_scheme` value in the database.
This is just one way to do it, which is how Django performs hashing scheme migrations IIRC.
- artursapek 11y agoAlternatively, you can update the entire user db at once by hashing their existing password hashes. You'll end up using a double-hash: new_hashing_scheme(old_hashing_scheme(password)) Not as elegant, but the benefit is you can immediately move everyone to a new scheme if you need to for some reason.
- esnard 11y agoIf you were already using bcrypt (or any "slow hash algorithm"), double-hashing may be very slow.
- msbarnett 11y agoYou only have to do it when you in-place upgrade the entire table, and once when the user initially logs in after that. Once the user has logged in successfully, you can replace new_hash(old_hash(password)) with simply new_hash(password). This is less useful for optimistic upgrades like bcrypt->argon2i, but is absolutely critical if you find yourself taking over responsibility for a database that has a password column full of, say, MD5s. Waiting for each and every user to log in to upgrade those vulnerable hashes is suicidal.