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 
user3388884
  • 4,748
  • 9
  • 25
  • 34

2 Answers2

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().

Álvaro González
  • 142,137
  • 41
  • 261
  • 360
ircmaxell
  • 163,128
  • 34
  • 264
  • 314
  • Thanks for the info , Max. Voting up. – Shankar Narayana Damodaran Mar 26 '14 at 17:44
  • Appreciate it! that helps. So basically the crypt functions breaks down the $hash string and uses the substring (salt portion) for the actual salt? – user3388884 Mar 26 '14 at 17:48
  • 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 PHP](http://stackoverflow.com/questions/4795385/how-do-you-use-bcrypt-for-hashing-passwords-in-php/17073604#17073604) – ircmaxell Mar 26 '14 at 19:08
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.

Gavin Kwok
  • 98
  • 6