How is crypt($pass, '$2y$09$salt') === crypt($pass, crypt($pass, '$2y$09$salt')) in PHP?
Asked Answered
R

2

6

I'm ok really confused on the crypt() PHP function.

How does the following two crypt functions give the same output when the second crypt is clearly using an different 2nd argument? Diff salt means diff hash right?

echo crypt("password", '$2y$09$anexamplestringforsalt$')."\n<br>";
echo crypt("password", crypt("password", '$2y$09$anexamplestringforsalt$'))."\n<br>";

output:

$2y$09$anexamplestringforsale/.K.VdgECUVEd9N4ja3u1WtgPi5BXZq 
Roundup answered 26/3, 2014 at 17:34 Comment(0)
D
12

The reason is because the salt is part of the output of the hash that crypt provides.

$2y$09$anexamplestringforsale/.K.VdgECUVEd9N4ja3u1WtgPi5BXZq 

That is broken into several components:

  • 2y - algorithm identifier (bcrypt)
  • 09 - the cost parameter
  • anexamplestringforsale - the salt
  • /.K.VdgECUVEd9N4ja3u1WtgPi5BXZq - the hash

This results in the nice property of just being able to use the result hash directly as the salt in the verification call.

$hash = crypt($password, $salt);

if ($hash === crypt($password, $hash)) {

Now you don't need to store the algorithm, cost or salt separately. Just store them in the hash result directly. Simple.

Also, I'd highly suggest you use the simplified password hashing API, which was designed to specifically mitigate these issues: password_hash().

Droop answered 26/3, 2014 at 17:42 Comment(2)
Appreciate it! that helps. So basically the crypt functions breaks down the $hash string and uses the substring (salt portion) for the actual salt?Roundup
Correct. It actually uses all the pieces except the hash portion. And if you use the simplified password hashing API I linked to, password_verify() does use the hash portion as well to verify the hash for you. In short, if you're directly generating salts, or using crypt directly, you're likely doing something wrong. How to use bcrypt for passwords in PHPDroop
I
0

If you use BlowFish algorithm, your code will finally run into this function: BF_crypt (the source code)

The declaration:

static char *BF_crypt(const char *key, const char *setting,
char *output, int size,
BF_word min)

The key is the $str and the setting is the $salt of php function string crypt ( string $str [, string $salt ] ), and the output will be the encrypted return value.

As you can see in the source code:

First, at line 777, memcpy(output, setting, 7 + 22 - 1);, this line copy the first 29 character(from pos 0 to pos 7 + 22 -1) of $salt into the return value, which is $2y$09$anexamplestringforsale

Second, the remains of $salt never got used.

Third, at line 784, BF_encode(&output[7 + 22], data.binary.output, 23);, append the encrypted string on the return value.

So, the $str and the first 29 character of $salt are factors that affects your return value.

Immunotherapy answered 5/9, 2018 at 10:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.