I am using Laravel's bcrypt
function for hashing passwords. When I do,
bcrypt('secret')
I get
=> "$2y$10$mnPgYt2xm9pxb/c2I.SH.uuhgrOj4WajDQTJYssUbTjmPOcgQybcu"
But if I run it again, I get
=> "$2y$10$J8h.Xmf6muivJ4bDweUlcu/BaNzI2wlBiAcop30PbPoKa0kDaf9xi"
and so on...
So, won't the password matching process fail if I get different values every time?
This is how bcrypt
is supposed to work. See wikipedia.
Bcrypt generates a random 128-bit salt during hashing. This salt becomes part of the hash, hence we always get a different hash value for the same input string. The random salt is actually used to deter brute-force attacks.
The password matching process won't fail due to different values of hashes.
Try the following in tinker
$hash1 = bcrypt('secret')
$hash2 = bcrypt('secret')
Hash::check('secret', $hash1)
Hash::check('secret', $hash2)
You should get true
in both the cases of Hash::check
.
So even if the hash values are different, the password matching won't fail.
Bcrypt uses a 128-bit salt and encrypts a 192-bit magic value. It takes advantage of the expensive key setup in eksblowfish.
The bcrypt algorithm runs in two phases, sketched in Figure 3. In the first phase, EksBlowfishSetup is called with the cost, the salt, and the password, to initialize eksblowfish's state. Most of bcrypt's time is spent in the expensive key schedule. Following that, the 192-bit value ``OrpheanBeholderScryDoubt'' is encrypted 64 times using eksblowfish in ECB mode with the state from the previous phase. The output is the cost and 128-bit salt concatenated with the result of the encryption loop.
How it works in laravel :
if (! function_exists('bcrypt')) {
/**
* Hash the given value against the bcrypt algorithm.
*
* @param string $value
* @param array $options
* @return string
*/
function bcrypt($value, $options = [])
{
return app('hash')->driver('bcrypt')->make($value, $options);
}
}
Supported options for PASSWORD_BCRYPT:
salt (string) - to manually provide a salt to use when hashing the password. Note that this will override and prevent a salt from being automatically generated.
If omitted, a random salt will be generated by password_hash() for each password hashed. This is the intended mode of operation.
Warning The salt option has been deprecated as of PHP 7.0.0. It is now
preferred to simply use the salt that is generated by default.
cost (integer) - which denotes the algorithmic cost that should be used. Examples of these values can be found on the crypt() page.
If omitted, a default value of 10 will be used. This is a good baseline cost, but you may want to consider increasing it depending on your hardware.
How Bcrypt encryption and decryption works:
Internally bcrypt() use uses PHP's built-in password_hash() function. password_hash() returns different values each time because it appends a random string (a "salt") to the password. The salt is actually contained in the output hash.
If the same password is hashed with the same salt, you will always get the same output. Therefore password_verify() looks at the stored hash, extracts the salt, and then hashes the given password with that same salt.