fast-reflexes
fast-reflexes

Reputation: 5186

PHP crypt() returning 13, and not less than 13 characters, on failure

It is stated in the manual (http://php.net/manual/en/function.crypt.php) for the PHP crypt() function that it...

Returns the hashed string or a string that is shorter than 13 characters and is guaranteed to differ from the salt on failure.

However, the following example, where I use the rounds parameter in the prefix to crypt() in the wrong way, shows that the function might also return a 13 character hash on failure. Shouldn't then the manual state that the string is equal to or shorter than 13 characters on failure, or am I not getting something?

$password_to_encode = "foo";
$iv = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);
$error_hash = crypt($password_to_encode, 'rounds=10000$6$'.$iv);
echo 'Error hash: '.$error_hash.', length: '.strlen($error_hash)."<br>";

$correct_hash = crypt($password_to_encode, '$6$rounds=10000$'.$iv);
echo 'Correct hash: '.$correct_hash.', length: '.strlen($correct_hash)."<br>";

Output:

Error hash: rod2rRfdXBWy6, length: 13
Correct hash: $6$rounds=10000$¦yû*®gص=ºåé...NFk.5mrB07OM//, length: 119

(The correct hash has been abbreviated)

Upvotes: 0

Views: 1246

Answers (2)

Matt Gibson
Matt Gibson

Reputation: 38238

Your "incorrect" hash is being recognised as a standard two-character DES hash; the subsequent characters are ignored. crypt() is basically working out the algorithm to use based on your salt, but rather than seeing an incorrect SHA512 salt, it's seeing a correct DES salt, as the first two characters are a valid DES salt.

The big clue as to what's happening is here in the manual:

The standard DES-based crypt() returns the salt as the first two characters of the output. It also only uses the first eight characters of str, so longer strings that start with the same eight characters will generate the same result (when the same salt is used).

Note that your "incorrect" output starts with the same two characters as your salt—those are actually the entire salt in this case.

So, in fact, you're actually getting a real, 13-character hash, not a failure. It's just not the kind of hash you were expecting.

Upvotes: 2

markogrady
markogrady

Reputation: 21

The correct hash has a SHA-512 salt so its output is longer than 13 characters. The incorrect hash function has simply not recognised the salt of 'rounds=10000$6$' and output it as a standard crypt string of 13 characters.

Upvotes: 1

Related Questions