Если в 2-х словах (вкратце не получилось):
имеем хеш: $H$95MMFvTU4Lm1sASItv4J5HWXk18HW70 (пароль 123456)
соль от него 5MMFvTU4 (8 символов, начиная с 5-го)
Делаем такой цикл: (убрать 2 пробела после ..klmn)
$salt='5MMFvTU4'; $password='123456';
Код:
$settings='$H$95MMFvTU4Lm1sASItv4J5HWXk18HW70';
$itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$hash = md5($salt . $password, true);
do
{
$hash = md5($hash . $password, true);
}
while (--(1 << strpos($itoa64, $setting[3]) ));
Цикл возвращает бинарную строку из 16 символов, сделав много раз сначала функцию md5($salt . $password); затем md5( "предыдущий бинарный хеш" . $password);
Ну, и, наконец, чтобы получить из этого бинарного хеша строку Lm1sASItv4J5HWXk18HW70 (первые 12 символов не в счет, их отбрасываем), прогоняем его через следующую функцию ($input это полученный ранее $hash):
Код:
function _hash_encode64($input, &$itoa64)
{
$output = '';
$i = 0;
do
{
$value = ord($input[$i++]);
$output .= $itoa64[$value & 0x3f];
if ($i < 16)
{
$value |= ord($input[$i]) << 8;
}
$output .= $itoa64[($value >> 6) & 0x3f];
if ($i++ >= 16)
{
break;
}
if ($i < 16)
{
$value |= ord($input[$i]) << 16;
}
$output .= $itoa64[($value >> 12) & 0x3f];
if ($i++ >= 16)
{
break;
}
$output .= $itoa64[($value >> 18) & 0x3f];
}
while ($i < 16);
return $output;
}
Склеиваем строки в одну ($H$95MMFvTU4 + Lm1sASItv4J5HWXk18HW70). проверяем, радуемся. ВСЕ
Примеры:
$H$95MMFvTU4Lm1sASItv4J5HWXk18HW70:123456
$H$9ZKl5LLDygA/c8AGXcpWk7bRnHQQ.U0:testing
$H$9Uh5EWFcQEmJPaWy/7wsyzMPN4.jS3/:123321
где первые 4 символа
$H$9 сигнатура хеша
по умолчанию.
$H$9 присутствует всегда, хотя его и можно и менять прямо в коде (я имею ввиду последоватльность $H$)...
Я бы сделал префикс другой ) чтобы никто не догадался
______________________________________
P.S. Этот алгоритм применяется начиная с версии phpBB3 RC5. До этого везде был md5