Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upgrade password hash from md5 to bcrypt [closed]

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)?
like image 393
merlinbeard Avatar asked Sep 30 '14 03:09

merlinbeard


People also ask

Is bcrypt better than MD5?

With MD5, assuming the servers can handle it, a user could very rapidly attempt to brute-force passwords just by trying lots of passwords in quick succession. bcrypt's slowness guarantees that such an attempt will be much slower. Second, a key security concept in computing is defense in depth.

Can you reverse bcrypt?

You can't "reverse" password hashes. You can't "unhash" or "dehash" passwords. You can't "reverse" or "invert" MD5, SHA256, bcrypt, SHA1, or similar hashes, salted or unsalted. You (usually) can't "decode" passwords, "decrypt" password hashes or "reverse" or "unscramble" password hashes at all.

Do people still use bcrypt?

Yes, bcrypt has many savvy supporters, though of course you want to tune the number of iterations with performance and tune other defenses with DoS attacks in mind. See also How to securely hash passwords? - IT Security and Password Hashing add salt + pepper or is salt enough?

Is bcrypt cracked?

bcrypt is a very hard to crack hashing type, because of the design of this slow hash type that makes it memory hard and GPU-unfriendly (especially with high cost factors).


1 Answers

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.

like image 70
martinstoeckli Avatar answered Nov 16 '22 01:11

martinstoeckli