I'm currently an engineer on a project in development phase. One 'module' on this project gives the ability for user authentication/authorization. However it's come to our concern that the password hashing algorithm may not be up to cop (aka not BCrypt). (The terrible thing is not quite sure what it is and where it came from!).

This obviously has to change and the patch is being scheduled. We have to naturally update all our test users because their passwords will be using the old hashing method, not much of a problem, all our demo users are automated on build so it's updating the script. But the next question is what if this is a production system with active and stale users, of all amounts. What would be best practice.


Automatically force a password reset on every user? This will notify every user that their password has been changed and may cause question/confusion and may cause suspicion that there's been a security breach. More questions may be asked which may not necessarily be able to be answered by website stakeholders.
Update the DB to flag whether it's the new or old method, then once a user has been authenticated update their password in the DB using. Requires a bit of logic in the service and transition will be seemless to any existing user. The problem being if there was a breach then it may be evident that there are two methods going on here and if the less secure one is found to be that insecure it could obviously be broken.
Reset all passwords, using a BCrypted version of the existing hash. Flag it as the old style, so on successful authentication it just keeps a hash of the password rather than a hash of a hash.


Your option 1. is a bad idea: in addition to the User-Experience / Public-Relations reasons you state, you're also giving attackers a window to intercept the password reset tokens and compromise every account on your server. It also doesn't solve your problem if you have even one user who's too lazy to log in / update their password.

At first glance, both 2. and 3. seem fine to me. Your #2 is no less secure than what you're doing now, but 2. would mean you have to continue supporting the current weak login forever (or do something like "After X months we're wiping your password and forcing you to do a recovery" which breaks the nice user-transparency you want, so let's ignore that).

Let's consider the case where you have users in the DB who will never log in again. With both 2. and 3. you have to continue to support the current hashing alg in your code-base forever just in case they do log in, but at least 3. has the advantage that they (or rather, you) are protected against offline brute-force attacks if your DB is ever stolen.

Since you'll have to keep the "old style flag" column around forever, do yourself a favour and make it an int not a bool so that if you ever have to update your password hashing alg again, you can record which old style they are on.



UPDATE: A very similar question was asked here and built on the discussion from this thread.
