I am looking at migrating the hashing algorithm used for all passwords in a database and looking for proof of concept.
I was reading up on a concept that would be very user friendly and not force anyone to change their password here that essentially allows to migrate all passwords in the database at once by hashing the hash:
The idea is basically to hash the hash. Rather than waiting for users provide their existing password (p) upon next login, you immediately use the new hashing algorithm (H2) on the existing hash already produced by the old algorithm (H1):
hash = H2(hash) # where hash was previously equal to H1(p)
After doing that conversion, you are still perfectly able to perform password verification; you just need to compute H2(H1(p')) instead of the previous H1(p') whenever user tries to log in with password p'.
So essentially I would:
- Using the new algorithm, re-hash all of the passwords currently stored in the database with the old hash algorithm.
- When users try to authenticate, wrap the old algorithm with the new one to verify the password.
Let's say I am migrating from SHA1
to BCRYPT
, I run the following test with a password of 11111111
:
// 1. Old hash algorithm used to store the password in the database and authenticate the login
hash('SHA1', '11111111')
// result: a642a77abd7d4f51bf9226ceaf891fcbb5b299b8
// 2. This would be run to update the hashed values in the database to the new algorithm
password_hash('a642a77abd7d4f51bf9226ceaf891fcbb5b299b8', PASSWORD_BCRYPT)
//result: $2y$10$zetRoEVYvjug73Ee8k/cSOSLxFBLs0fNYGJDrdqFkyqGoe41baJ46
// 3. This would be run to authenticate a user after the database passwords have been updated to the new algorithm
password_hash(hash('SHA1', '11111111'), PASSWORD_BCRYPT)
// result: $2y$10$xANTOzHQaKxfKKqzTn9lVeJIgHH3YQok/eOegIeRmrHHUTJkx7pDS
Theoretically the result of 2. and 3. above should be the same, and would need to be for this to work - but they are not.
Is there something I am missing?