...

View Full Version : PHP crypt_blowfish issue



Serihon
07-12-2012, 12:33 AM
Good evening fellow coders,

I am updating security on a site I am working on and have decided to use crypt with blowfish to hash users passwords. I am having an issue with my method to create a random salt. I am using an array of stored numbers (04-31 is what is accepted in the correct portion of the blowfish salt) and using array_rand to pull a random number out to use in the also random string of the salt for crypt. However when I use this random method 1 out of 4 times the page will drop an Internal Server Error and fail. However if I change the number to a fixed number the page works perfectly every time. I am not sure where I am going wrong so I will post the code I have for the encrypting process.

Code for random number in an array.


function RandNumber($e){
$numbers = Array(04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31);
$rand_key = array_rand($numbers);
$rand = $numbers[$rand_key];
return($rand);
}

Code to assemble the salt and create the hashed password.


$salt= "$2a$";//Append beginning of salt
$salt.=RandNumber(2);//Generate a random number between 03 and 33
$salt.="$";
$string = str_shuffle("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");//Generate random 22 character string for salt
$salt.= substr($string,1,22);//Append 22 string to the salt
$pass = crypt($pass, $salt);//Encrypt password

If I use the blow code for the random generator (pointless) the page works fine.


function RandNumber($e){
$rand = 17;
return($rand);
}

Any thoughts on this would be greatly appreciated!

Regards,

Frank

firepages
07-12-2012, 12:47 AM
how are you going to check an incoming password if the salt is random ?

Serihon
07-12-2012, 02:17 AM
The salt is random per user but stored to rehash input to match passwords.

Serihon
07-12-2012, 11:54 AM
I seem to have figured out what is causing the Internal Server Error. I rather think it is a timeout due to long processing from the crypt_blowfish hash.

Basically the crypt_blowfish function in php requires a salt and there is a two digit number in the salt that is the base-2 logarithm of the iteration count for the hashing algorithm.

If I set this 2 digit number low, like 04-10 then the page doesn't generate the Internal Server Error.

Originally I was randomly getting a two digit number between 04-31 (those are supported by the crypt_blowfish script). So to test my theory I set the digit to 04 and the form worked fine without any hitches. I then set the number to 31 and right off the bat it returned Internal Server Error. Also 04 processed faster than 10 which proves it must be a timeout issue.

Is there anyway for me to increase how long it would take before the server would time out?

Regards,

Frank

Serihon
07-12-2012, 01:42 PM
Did some further testing and the highest number I can use is 17. Anything above that causes the 500 Internal Server Error.

Any thoughts?

Serihon
07-12-2012, 03:25 PM
GoDaddy is currently using PHP version 5.3.6. I noticed in 5.3.7 there are some fixes to crypt and crypt_blowfish but security vulnerabilities so 5.3.8 is preferred. Does anyone think that the issues fixed in 5.3.7 would solve my issue?

http://www.php.net/ChangeLog-5.php#5.3.7

Regards,

Frank

Fou-Lu
07-12-2012, 03:47 PM
500 errors shouldn't be caused by this, but I won't rule it out given the change note for crypt's overlog on its salt.
I can't test this until I get to a machine that supports it (neither codepad nor writecodeonline support blowfish through crypt).
What does stand out is the invalid weight:


$numbers = Array(04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31);

crypt_blowfish requires between 4 and 31 inclusive. What you have given for options are 4 - 7 inclusive, 10 - 31 inclusive, and 0. Prepending a number with a 0 indicates its an octal number, and not an integer, so 08 and 09 are both invalid octals which results in 0.

Why not just use a rand(4, 31)?

Serihon
07-12-2012, 03:55 PM
Hey Fou-Lu, thanks for the response.

Well I may have been taking the php manual's description of the crypt_blowfish method literally.

http://us2.php.net/manual/en/function.crypt.php

CRYPT_BLOWFISH - Blowfish hashing with a salt as follows: "$2a$", a two digit cost parameter, "$", and 22 digits from the alphabet "./0-9A-Za-z". Using characters outside of this range in the salt will cause crypt() to return a zero-length string. The two digit cost parameter is the base-2 logarithm of the iteration count for the underlying Blowfish-based hashing algorithmeter and must be in range 04-31, values outside this range will cause crypt() to fail.

I did test from 01-10 by setting those myself and crypt() worked fine so I don't think that is the issue. Especially since I also tested 17-31 and 17 is the last one that will work fine before causing an Internal Server Error.

At this point I am not sure what to do. Currently I have set the numbers from 10-17 as I assume that the lower the number the less protected the password? Though if I am wrong in any way shape or form I would definitely appreciate being corrected.

Also if there is a better/more secure way to keep users passwords safe I would definitely consider implementing it over the way I am doing it since my way is causing issues.

Thanks again!

Regards,

Frank

Fou-Lu
07-12-2012, 04:56 PM
Oh yes I see what you mean. It wants it as a two digit numeric string from what I can see too.
Your array must be a string array then. Like I said, 08 = 0, and that's no good for it to use in either case. When you set it yourself (assuming you mean in the salt), that is now a string, so using 08 is fine. But in your array, its an integer value of 0, so those need to be strings to retain it with the 0's.

And no you are right. The higher the weight, the higher the iterations. That's what this line describes: The two digit cost parameter is the base-2 logarithm of the iteration count, so from what I read into that, using 17 would give the antilogbase2 of 17, or ~132K. This shouldn't be an issue during any type of calculation.

Serihon
07-12-2012, 05:11 PM
so this is the correct way to do it?


$numbers*=*Array('04','05','06','07');*

Also would it be best to use just 15+ for added security or is a wider range better for random security?

Will try this if it is a fix once I get home.

Fou-Lu
07-12-2012, 05:46 PM
That's right. And yeah, the higher the number the more times the algorithm factors it from the looks of it. Theoretically if you want the highest, hardcode in 31.

Serihon
07-12-2012, 06:41 PM
Wouldn't appending it to a string turn t into a string value? I did try $rand=31 and it still passed the internal server error.

Fou-Lu
07-12-2012, 06:45 PM
Wouldn't appending it to a string turn t into a string value? I did try $rand=31 and it still passed the internal server error.

Yes, but if its a number to start with, they do not retain prepended 0's. So doing this:


$i = 07;
$s = "the number is " . $i;
var_dump($s);

Will come up with:


string(15) "the number is 7"



BTW, an alternative is to provide numbers with a formatter:


$i = 07;
$s = sprintf('the number is %02d', $i);
var_dump($s);

Serihon
07-12-2012, 08:11 PM
Well I will change it so that the numbers are strings. Still I can't use 31 since any number above 17 will cause the Internal Server Error. Not sure what to do.

I did contact GoDaddy about the version of php and asked if it would be possible to update to 5.3.8 and they said not as of yet.

So I guess I am either stuck using 17 for crypt blowfish or I need to find a different hasher.

Thanks for the help Fou-lu.

Serihon
07-13-2012, 12:08 PM
Is SHA512 a better hasher than blowfish? It seems to me that by default it iterates itself 5000 times so it would be better. Though if my server can't even handle anything above 17 times I guess it may not even handle SHA512.

Serihon
07-13-2012, 01:01 PM
For kicks and giggles I developed two pages to test how many iterations I could do with blowfish and sha512 and to make sure it wasn't other code on my page causing the issue.

With blowfish I can still only do a max of 17 iterations before the server passes an Internal Server Error.
http://marestareliveevents.com/bidder/blowfish.php

For Sha512 I can do up to around 3,260,000 iterations before the server passes the Internal Server Error.
http://marestareliveevents.com/bidder/sha512.php

If anyone would like to test this and see if they can do a higher value I would appreciate it as it may point out that it isn't server related but an issue somewhere else?

I just can't figure out what to do if it is a different value for each person. If it stops working at the same value for every user I guess it would point out that GoDaddy's servers can't handle too many iterations and I may need to upgrade or move.

Regards,

Frank

Blowfish Code


function blowfish($p,$n){
if(strlen($n) < 2){ $n = '0'.$n; }//Check length of the iteration value as 2 digits are needed (04,05,etc)
$salt= "$2a$";//Append beginning of salt
$salt.=$n;//Append iteration value
$salt.="$";//Append essentials
$string = str_shuffle("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");//Generate random 22 character string for salt
$salt.= substr($string,1,22);//Append 22 string to the salt
$crypt = crypt($p, $salt);//Encrypt password
return($crypt);
}

Sha512 Code


function sha512($p,$n){
if($n < 5000){ $n = '5000'; }//Min iterations for sha512 is 5000
$salt= "$6$";//Append beginning of salt
$salt.="rounds=".$n;//Append iteration value
$salt.="$";//Append essentials
$string = str_shuffle("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");//Generate random 22 character string for salt
$salt.= substr($string,1,16);//Append 16 string to the salt
$crypt = crypt($p, $salt);//Encrypt password
return($crypt);
}



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum