Imagine you are happily programming away one day, when your boss comes over and says “Hey, remember when we sent the results of our security audit to that big potential partner, XYZ Corp?” “Of course” you say, “If we partnered with them it would be huge. Whatever happened with that?” Well, he says, “They came back to us with some security upgrades they’d like us to implement before they can integrate with us. Apparently they don’t like something called M D 5 … do you know what that is?” You knowingly nod, “Yeah, it’s the encryption algorithm we use to store passwords in our database. It was popular in 1995 when the first code for our legacy product (the fart app) was written, but it’s now known to be pretty weak.” He responds, “Well we need to upgrade that to something more secure. Can you make that happen?” “Sure”, you say, “There are some algorithms that are stronger, like SHA-512 and BCrypt. I’ll give some thought to the actual migration strategy before choosing the new algorithm.”
You don’t store passwords in your database in plain text so you don’t actually have access to the original password. How can you re-encrypt your passwords if you don’t have the original to re-encrypt?
Some Possible Solutions
You could clear all the passwords and require users to re-register.
PRO: this is easiest for the developer/code/database, and you only ever has to ever worry about a single encryption algorithm at a time
CON: this is very invasive and will probably piss off a lot of people.
Re-Encrypt All Passwords At Once
You could add more protection immediately by encrypting the already-weakly-encrypted passwords using the new algorithm, so they are doubly-encrypted.
PRO: immediately have more protection for all passwords, transparent to users
CON: every login requires more hash calculation, this strategy complicates the code, the conversion cost for 100K users with BCrypt at 500ms each is 13 hours (single threaded) which may exceed your maintenance window
Re-Encrypt Passwords Incrementally
When the user logs in, you do briefly have access to the plain text password. You could test incoming passwords with multiple algorithms one at a time, once you find a match you can overwrite old encryptions with new as necessary as users log in.
PRO: transparent to users
CON: potentially need to calculate the hash multiple times, need to support multiple algorithms in perpetuity
Store Extra Encryption Information
Finally, you could store information about the encryption algorithm on a per-password basis in its own column, and use the appropriate algorithm for login. You can migrate passwords incrementally (as described above) as users log in.
PRO: shows conversion rate, can later reset just select users, only single hash is ever required
CON: more complexity in code, requires database schema update
The solution you use might depend on your specific scenario and requirements. But that said, which approach would you use? Is there another approach not listed here that you would use?