5

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?

Joel G
  • 67
  • 1
  • 7
  • I've tested your example and it outputs exactly the same as in the article. How do you output/debug the $password. On a website? per cli? – hek2mgl Jan 15 '13 at 03:22
  • I just printed to a file (I omitted the lines of code for that). Is there a specific version of PHP required for this function...? – Joel G Jan 15 '13 at 03:25
  • What version do you using? (I'm using: 5.3.10-1ubuntu3.4) – hek2mgl Jan 15 '13 at 03:26
  • FYI, in this line, `fwrite($file, "\n\n\n".$str);` $str seems undefined. – DWright Jan 15 '13 at 03:29
  • @DWright Thanks! Sorry, that was a typo... – Joel G Jan 15 '13 at 03:30
  • @NullUserException Same thing when printing out the hash. I am writing to a database, just using the file for testing... – Joel G Jan 15 '13 at 03:32
  • 1
    you seem to be "printing" the hash to the file before actually computing it – Eevee Jan 15 '13 at 03:35
  • 1
    @Eevee My apologies, the problem wasn't in my source code. I originally posted w/out the 'printing', and then decided to add it after, but put it in the wrong place... – Joel G Jan 15 '13 at 03:46

4 Answers4

2

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.

Community
  • 1
  • 1
helmbert
  • 35,797
  • 13
  • 82
  • 95
  • user1403777 does this solve your problem, not responding in any way to answers is not the right way to behave on stackoverflow... – Maarten Bodewes Jan 28 '13 at 23:22
1

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.

B-Con
  • 454
  • 6
  • 15
1

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
    }

?>
Alex
  • 461
  • 5
  • 6
0

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.