0

I already know how to use password_verify and password_hash functions, but I don't really understand how they work.

When I use them I do something like that:

$save_hash = password_hash( $password, PASSWORD_DEFAULT );
$check = password_verify( $password, $hash );

How password_verify can know the algorithm used, the salt and the cost? The PHP official documentation say this:

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.

But I don't really understand why all that information is included in the hash, so a possibly attacker will know too. So, if attackers know the salt, why is it secure? They only have to put the salt at the beginning and try a brute force attack the same way they would do without a salt. What am I wrong about?

Diego
  • 3
  • 1

1 Answers1

3

How password_verify can know the algorithm used, the salt and the cost?

$save_hash looks like this:

$2y$10$nmqlFAguURkkWhjgn7LP7.QxLw2fQ9GYSkiaEbypgXg6L4bESC.Mu

Which is a bunch of fields separated by $:

What Means this
2y Type of hash, in this case bcrypt
10 The cost
Salt and password hash The first 22 characters are salt, the remainder is the hash

So, yes, all the information required to mount a brute-force attack on the password is there.

But I don't really understand why all that information is included in the hash, so a possibly attacker will know too. So, if attackers know the salt, why is it secure?

The salt is not designed to be secret; it is designed to be distinct for each user, meaning that an attacker will have to adjust their attack for each user. Without salts, every user with "p@ssw0rd" as their password would have the same exact hashed password, and the attacker would only need to crack it once. With salts, the attacker has to do the work separately for each user/salt.

As an example, let's take 100 users. Without salts, an attacker needs 10 tries to test 10 passwords. With salts, the attacker needs 1000 tries to test 10 passwords. The cost of the attack is multiplied by the number of salts.

See also this question about salt.

gowenfawr
  • 71,975
  • 17
  • 161
  • 198
  • it's still one way, no? Not sure it's right to say "all the information to crack the password is there"? Verify is still a one-way function. (password -> hash) (You'd still need a "rainbow table" with the hash...) – pcalkins Jan 13 '21 at 18:36
  • 1
    @pcalkins still one way, yes. "crack the password" equals "mount a brute-force attack against the password," I wasn't implying reversing it was possible. – gowenfawr Jan 13 '21 at 19:00
  • gotcha... I guess reversing it is possible, but it requires brute-force and nothings secure against that given infinite amount of time. – pcalkins Jan 13 '21 at 19:10
  • +1. @pcalkins see https://security.stackexchange.com/questions/241991/when-could-256-bit-encryption-be-brute-forced#comment500424_241991 for some practical answers as to brute-forcing sha256. Think of bitcoin as a massive bug bounty for sha256. If a bad actor were to find a vulnerability in sha256, they could use it to take over the blockchain, launch a 51% attack, double-spend coins, collect mining fees, etc. At $35,000 USD / bitcoin, these would all be very lucrative. But, to date, nobody has found a bug and claimed the 'bounty'. – mti2935 Jan 13 '21 at 20:39
  • I think you'd find, @mti2935, that in that case Bitcoin would suddenly cease to hold that value. – TRiG Jul 08 '22 at 17:57