Reputation: 67
This is my first time using the crypt() function in PHP, and I can't figure out why it isn't working. My code is based on this article: http://www.techrepublic.com/blog/australia/securing-passwords-with-blowfish/1274
function blowfishHash ($pw) {
//generate random salt
$salt = "$2y$10$";
for ($i = 0; $i < 22; $i++) {
$salt .= substr("./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", mt_rand(0, 63), 1);
}
$hash = crypt($pw, $salt);
//printout to file
$file = fopen("debug.txt", "w+");
fwrite($file, "\n\n\n".$pw);
fwrite($file, "\n\n\n".$salt);
fwrite($file, "\n\n\n".$hash);
fclose($file);
return $hash;
}
I called the function with the sample password "password".
The resultant salt was: $2y$10$NzRQNjTRfP4jXKvb4TCO.G
But the password was "$2mV0NZp92R3g"
– which seems far too short.
Could someone please help me figure out what I'm doing wrong?
Upvotes: 5
Views: 5209
Reputation:
Initially only blowfish hashing with a salt starting with $2a$
was supported.
$2x$
and $2y$
Blowfish modes were added in PHP 5.3.7 to deal with potential high-bit attacks.
Your PHP 5.2.17 does not support $2y$
Blowfish mode.
This why your code is not working.
Upvotes: 0
Reputation: 461
here is my blowfish encryption function ....
<?php
function bcrypt($input, $salt=null, $rounds=12) {
if($rounds < 4 || $rounds > 31) $rounds = 12;
if(is_null($salt)) $salt = sprintf('$2a$%02d$', $rounds).substr(str_replace('+', '.', base64_encode(pack('N4', mt_rand(), mt_rand(), mt_rand(), mt_rand()))), 0, 22);
return crypt($input, $salt);
}
$hash = bcrypt('password');
if($hash = bcrypt('password', $hash)) {
// password ok
}
?>
Upvotes: 1
Reputation: 454
Since crypt
in PHP 5.2 doesn't support CRYPT_BLOWFISH, it is instead defaulting to interpreting the salt as a CRYPT_DES style salt. Notice that the output starts with "$2", which is the two character salt that CRYPT_DES chose from the salt input and prepended to the hash, and the output length matches the exact CRYPT_DES output length.
Interestingly, you can achieve the same result in later PHP versions with CRYPT_BLOWFISH support by simply truncating the salt to two characters. Ie:
crypt('password', '$2y$10$NzRQNjTRfP4jXKvb4TCO.G') /* in PHP 5.2 */
==
crypt('password', '$2') /* in PHP 5.4 */
In theory, this might come in handy for backwards-compatibility if a CRYPT_BLOWFISH style salt was used in error on PHP 5.2.
This actually caused me a bit of confusion recently because the "$" character isn't valid salt input for CRYPT_DES as per the PHP crypt documentation, which says:
Standard DES-based hash with a two character salt from the alphabet "./0-9A-Za-z". Using invalid characters in the salt will cause crypt() to fail.
But here the "$" character clearly seems to be accepted by crypt()
in both v5.2 and v5.4.
It would be both clearer and safer if crypt
actually returned a failure like the documentation says it's supposed to, rather than accepting the "$" and defaulting to CRYPT_DES.
Upvotes: 1
Reputation: 37934
As you stated in your comment, you are using PHP 5.2.x.
The Blowfish implementation is only available in PHP >= 5.3.x. If for any reason it is not possible to install a newer PHP version, you could check here on more information on how to make Blowfish work with older PHP versions.
Upvotes: 2