Upgrade password hash from md5 to bcrypt

10,545

Surely it is a good idea to switch to a more secure hash algorithm. There is a function password_hash() you can use for creating a BCrypt hash:

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_DEFAULT);

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

From your answer i guess that you used an unsalted MD5 value, so double hashing can be a good solution here. Just pass the MD5 hash to the password_hash() function, it will generate a safe salt on its own.

// Migrating the old MD5 hashes to MD5-BCrypt
$hashToStoreInDb = password_hash($existingMd5Hash, PASSWORD_DEFAULT);

For verification first check for a double hash, and then verify the password accordingly.

if (checkIfDoubleHash($existingHashFromDb))
{
  $isPasswordCorrect = password_verify(MD5($password), $existingHashFromDb);

  // Update database with pure BCrypt hash
  if ($isPasswordCorrect)
    $hashToStoreInDb = password_hash($password, PASSWORD_DEFAULT);
}
else
{
  $isPasswordCorrect = password_verify($password, $existingHashFromDb)
}

The stored hashes can be recognized by the leading $ or by a separate db field, a BCrypt hash for example always starts with a $ character, an MD5 hash does not.

A salt should not be derrived from other parameters and it should be unique per password. The password_hash() function will take care of this. Since a rainbowtable must be built fore each salt, an attacker would have to build a rainbowtable for each password. For more information you can have a look at my tutorial about secure password storing.

Share:
10,545
merlinbeard
Author by

merlinbeard

meh.

Updated on July 25, 2022

Comments

  • merlinbeard
    merlinbeard almost 2 years

    Its been discussed here before, but there seems to be no conclusion.

    Ideally, don't want to maintain state (upgraded/not upgraded) in the database etc. so, here is what I'm thinking:

    bcrypt the MD5'd password, and use "username + something else" as a salt.

    1. Does this scheme make any sense?
    2. Also, in general is it a good idea to use the username as a part of the salt? I read somewhere that adding a different salt to each hash makes it more secure. Is that correct (especially in context of bcrypt)?
  • merlinbeard
    merlinbeard over 9 years
    This is useful. Thank you!