How does password_hash php work?
Why does this example from the PHP manual give different results every time it runs? echo password_hash("rasmus lerdorf", PASSWORD_DEFAULT); And then, password_verify() knows that ALL those hashes match "rasmus lerdorf"! It is like magic to me even the doc stated clearly:
Note that password_hash() returns the algorithm, cost and salt as part of the returned hash. Therefore, all information that's needed to verify the hash is included in it. This allows the verify function to verify the hash without needing separate storage for the salt or algorithm information.
This function is safe against timing attacks.
echo password_verify ( 'rasmus lerdorf' , '$2y$10$EMawXU7qNS4GzU2Do8bByeb7sSQZxecvmZ6mBrToxsOaY7RMAIGua' ); //=>true
echo password_verify ( 'rasmus lerdorf' , '$2y$10$0vMA2k7LxTBstI/J7clkkuZZ/XtuS1fklVuoM6sl4Fc/aj1avQa5u' ); //=>true
echo password_verify ( 'rasmus lerdorf' , '$2y$10$iuE2EzHMNONAWFKh/4Wyl.dcBxgFaNzAh32va0/gyE4ScqnNr/Uc.' ); //=>true
What is going on? How does password_verify() know some crazy string match 'rasmus lerdorf' but hackers don't?
The password_hash php function, internally, carries out these steps:
It picks a fresh random salt each time you call it. It applies a costly hash function that takes as input the random salt, the password, and other algorithm parameters (e.g., cost factors). It combines the algorithm parameters, random salt and hash output into an output string that can be parsed to recover them individually. The random choice in #1 is the reason why it produces different output each time even though you supply the same input. The formatted output from step #3 is what allows password_verify to know the random salt that was chosen by password_hash.