Prevent use of an invalid salt for Blowfish hashing of passwords

This commit is contained in:
Fedor A. Fetisov 2014-07-11 09:20:49 +00:00 committed by Dmitriy Simushev
parent dadbe36bd2
commit 524302fb2e

View File

@ -837,9 +837,9 @@ function calculate_password_hash($login, $password)
$hash = '*0';
if (CRYPT_BLOWFISH == 1) {
if (defined('PHP_VERSION_ID') && (PHP_VERSION_ID > 50306)) {
$hash = crypt($password, '$2y$08$' . $login);
$hash = crypt($password, '$2y$08$' . generate_bf_salt($login));
} else {
$hash = crypt($password, '$2a$08$' . $login);
$hash = crypt($password, '$2a$08$' . generate_bf_salt($login));
}
}
@ -850,6 +850,61 @@ function calculate_password_hash($login, $password)
return strcmp($hash, '*0') ? $hash : md5($password);
}
/**
* Generates correct blowfish salt based a string.
*
* @param string $string A string which should be turned to blowfish salt.
* @return string Correct blowfish salt.
*/
function generate_bf_salt($string)
{
$result = '';
$bin = unpack('C*', md5($string, true));
for ($i = 0; $i < count($bin); $i++) {
$shift = 2 + ($i % 3) * 2;
$first = ($bin[$i + 1] >> $shift);
$second = ($bin[$i + 1] & bindec(str_repeat('1', $shift)));
switch ($shift) {
case 2:
$result .= bf_salt_character($first);
$tmp = $second;
break;
case 4:
$result .= bf_salt_character(($tmp << 4) | $first);
$tmp = $second;
break;
case 6:
$result .= bf_salt_character(($tmp << 2) | $first);
$result .= bf_salt_character($second);
break;
}
}
if ($shift == 2) {
$result .= bf_salt_character($second);
}
return $result;
}
/**
* Convert character code to a correct blowfish character.
*
* @param integer $num Character code.
* @return string Character that can be used in blowfish salt.
*/
function bf_salt_character($num)
{
if ($num > 63) {
return chr(46);
} elseif ($num < 12) {
return chr(46 + $num);
} elseif ($num < 38) {
return chr(53 + $num);
} else {
return chr(59 + $num);
}
}
/**
* Validate incoming hashed value to be the hashed value of operator's password
*