A former developer used the PHP hash()
function with the SHA256 algorithm to store password hashes. To improve the security of the system, I'd like to start using crypt()
with the Blowfish algorithm (unfortunately we don't have PHP 5.5 and thus password_hash()
is not available).
Since SHA256 is a non-reversible hashing algorithm, is there a way to start using crypt()
with the salted passwords without asking everyone to reset their password?
Id say use a marker field to annotate which users have been previously hashed, then crypt the existing hash. For anyone with a true in the marker field when authenticating it becomes a 2 step process, hash the password then crypt it for a match check.
Whenever they update their password you would set the marker field to false. i.e. phase in and just crypt for a match check.
Another approach you may want to consider is hash chaining: since you can't reverse SHA256, just define your new hash function as
crypt(sha256($passwd))
. Since you presumably already havesha256($passwd)
on file for all your passwords, it's possible tocrypt()
each one of them with an appropriate salt to update your existing hashes (without having to wait for the user to log in).Yes, what you will need to do is add an extra column that stores the
crypt()
output. When a user logs in, and their password successfullyhash()es
to what you have in the database, you can nowcrypt()
that password, and remove the oldhash
from the database.This only works when users log-in, so you will have a period of time where some users are using the old system, and some users are using the new one.
Here's a possible solution:
Add a column to the user table to indicate which hashing method has been used on the user's password. At login time you'll know the user's password since he's just entered it, so once the current hash has been passed, crate a new has from the password and update the flag column
This assumes that you're passing free text passwords across the internet which you shouldn't do unless you're using SSL.
Alternatively, if you're hashing the password on the client before sending it, update the client software to handle two hashing algorithms and send both. Use your flag to identify which to check.
In both cases once all (or the majority of) your users have switched, deleted the old hashes and force the issue for the remaining users.
You should use the compatibility library then. It will make it easier for you when you move to 5.5.
Re-hashing without asking the user for the password... well, you can wait until the next time users log in, and then use the
password
extension'spassword_verify()
function. If it fails then you can fall back on the old SHA256 hash. If the SHA256 hash matches then you can rehash the password usingpassword_hash()
and save it in the old hash's place:It is technically possible to crack a lot of the hashes, but there are too many problems with that (you would not get all of them, it is most likely not feasible, it may not even be legal, etc.).
I'm assuming you never stored the clear-text user account passwords, as this would be truly an awful thing to do. SO therefore you no longer have the data that you need to create the new password digests.
I'm thinking you're going to need everyone to update their passwords.