2
votes

I have an old web application with a few users registered that is using the unsecure hash("sha256", trim($_POST["password"])) to store the hashed password in MySQL database. Now I want to update the web application to use the more secure BCRYPT password_hash() however I don't want to email all registered users alerting them to change their password. So I was thinking on implementing BCRYPT on the sha256() hashed password this way:

To save the password I will sha256() hash the user's password:

$hashed_password = password_hash(hash("sha256", trim($_POST["password"])), PASSWORD_BCRYPT);

Then I will save the BCRYPT hashed password in the database.

And to verify the user's password I would simply do this:

$hashed_password = "select hashed_password from users where email = '[email protected]'";

if(password_verify(hash("sha256", trim($_POST["password"])), $hashed_password))
{
    echo "Welcome";
}
else
{
    echo "Wrong Password!";
}

This way I will just update the user's password in the MYSQL database by looping each registered user, then I will retrieve the sha256() hashed password, and finally I will just re-save it after it has been BCRYPTed with password_hash():

$new_password = password_hash($old_sha256_hashed_password, PASSWORD_BCRYPT);

$mysql->save_user_password($new_password, $user_id);

So users will still be able to login with their old password.

What do you think about this solution?

Is it still safe even if I sha256() hash the password before BCRYPT it?

1
If you do not have user's password you can't rehash it. You would only know the password when the user logs in, and then you can rehash it.Dharman
@Dharman I know that and it is why I sha256() hash the user's password before BCRYPT it, so the old saved passwords that were sha256() hashed will stll work for old users. I tested this right now and all works perfectly, old sha256() hashed password once converted to BCRYPT work fine. I just need to know if it is still secure and safe since I sha256() hash the user's password before BCRYPT it.user2972081
Let me rephrase: It would be a good idea to rehash the user's passwords completely to a new system. Every time a user logs in using the old method rehash his password. I see no point keeping this double system indefinitely, but temporarily could be a good idea. If you do not want to force users to change passwords you could at least rehash it for them on the next login.Dharman
Ah I got it now thanks, yes that is a good suggestion, I will implement it.user2972081

1 Answers

1
votes

Since your current hashing system (unsalted SHA256) is indeed very unsecure, you could give immediate protection to the passwords with double hashing. As soon as possible, when the user logs in the next time, I would switch to the new algorithm and remove double hashing.

Make old hashes more secure:

$doubleHashToStoreInDb = password_hash($oldUnsaltedSha256HashFromDb, PASSWORD_DEFAULT);

Doing this for each row will protect the otherwise unsecurely stored passwords. Note the PASSWORD_DEFAULT parameter, it should be prefered over a specific algorithm, because it is future proof. And mark the double hashes, so you can distinguish between double hashes and already converted hashes, see why.

Handle new user registrations:

$hashToStoreInDb = password_hash($_POST['password'], PASSWORD_DEFAULT);

Just use the new algorithm without double hashing.

Verify logins:

if (checkIfDoubleHash($storedHash))
{
  $correctPassword = password_verify(oldPasswordHash($_POST["password"]), $storedHash);
  if ($correctPassword)
    storeConvertedHash(password_hash($_POST['password'], PASSWORD_DEFAULT));
}
else
{
  $correctPassword = password_verify($_POST['password'], $storedHash);
}

// Hashes the user password with a deprecated hashing scheme
function oldPasswordHash($password)
{
  return hash("sha256", trim($password));
}

Double hashes will be converted to the new password hash function, this is possible because we have the original user password at this moment. New hashes are verified with password_verify() which is a future proof and backwards compatible function.

Adapting the password algorithm to future hardware is not a one-time task, it will be necessary as soon as new hardware will become faster. PHP offers the function password_needs_rehash() to find out whether a rehashing is necessary, then you can also calculate a new hash and store it.