Have a good look at the values you're dealing with. The random salt generated will be, say:
abcdefg...
What is fed into crypt
looks like this:
crypt($password, '$2y$10$abcdefg...')
| | |
| | +- the salt
| +- the cost parameter
+- the algorithm type
The result looks like:
$2y$10$abcdefg...123456789...
| | | |
| | | +- the password hash
| | +- the salt
| +- the cost parameter
+- the algorithm type
In other words, the first part of the resulting hash is the same as the original input into the crypt
function; it contains the algorithm type and parameters, the random salt and the hash result.
Input: $password + $2y$10$abcdefg...
Output: $2y$10$abcdefg...123456789...
^^^^^^^^^^^^^^^^^
first part identical
When you confirm a password, you need the same, original salt again. Only with the same salt will the same password hash to the same hash. And it's still there in the hash, in a format that can be passed to crypt
as is to repeat the same operation as when the hash was generated. That's why you need to feed both the password and hash into the validation function:
crypt($passwordToCheck, '$2y$10$abcdefg...123456789...')
crypt
takes the first defined number of characters, up to and including abcdefg...
and throws the rest away (that's why the salt needs to be a fixed number of characters). Therefore it equals the same operation as before:
crypt($passwordToCheck, '$2y$10$abcdefg...')
And will generate the same hash, if and only if $passwordToCheck
is the same.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…