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.
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.
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.
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?
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).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With