How best to upgrade to password_* functions from hash('sha512','salt')

StackOverflow https://stackoverflow.com/questions/20841766

  •  22-09-2022
  •  | 
  •  

سؤال

I am keen to migrate my code to the new password_* functions provided natively by PHP.

The existing hashes in the database have been generated as follows:

hash ('sha512', '<A constant defined earlier>' . $email . $password);

I'd like to move these to be hashes created by the now-recommended:

password_hash ($password, PASSWORD_DEFAULT);

Obviously, when a user logs in, I can take the opportunity to create the new hash from the password they just provided, and save that in the database.

However, I'd like to avoid having to have two fields in the database, namely one for the deprecated hash and one for the modern password_hash one. Instead, I'd rather just replace the old ones as each user logs in.

Therefore, is it possible to keep a single database field, and have the userland code determine whether the hash is old, i.e. determine which check to use?

(I'm assuming that the hash('sha512') hashes cannot be automatically upgraded to crypt() ones?)

هل كانت مفيدة؟

المحلول

Hashes created with password_hash will have a very distinctive $2y$ string at the beginning (or similar $..$, as long as you're operating with the current default Blowfish cypher), while SHA256 will simply be all hex values. Therefore, you can simply test whether a value is a legacy hash value or a password_hash value:

function isLegacyHash($hash) {
    return !preg_match('/^\$\w{2}\$/', $hash);
}

Using this, you can keep both types of hashes in a single field and upgrade them when the user logs in. Alternatively, you could simply set a flag in a column like hash_version.

نصائح أخرى

You will have to rehash when a user logs in. But there is a function to check already, see password_needs_rehash.

So when a user logs in, run the check and change the password hash if it needs a rehash.

It will be a little more tricky if you decide to completely migrate to bcrypt at some point. Then you will need to think about what to do with the users who have not had a new hash created.

The following code will return true so you know you need to rehash.

$password = 'test';
$oldHash = hash('sha512',); // get old Hash from DB
if (password_needs_rehash($oldHash, PASSWORD_BCRYPT)) {
    $newHash = password_hash($password , PASSWORD_BCRYPT);
    // save new Hash to DB (IMPORTANT: only if log in was successful...)
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top