PHP:Blowfish算法给出* 0作为输出

时间:2014-08-03 11:17:32

标签: php algorithm blowfish

我今天正在玩Blowfish算法。一切正常,但有时我的程序失败,因为Blowfish Algo将*0作为输出,所以整个逻辑在之后就会崩溃。

enter image description here

CRYPT下的changelog的PHP官方文档页面上,提到此问题已在5.3.2版本中解决

5.3.2    Fixed Blowfish behaviour on invalid rounds to return "failure" string ("*0" or "*1"), instead of falling back to DES.

我正在使用PHP 5.5.9-1ubuntu4.2并仍面临同样的问题。这是程序:

<?php
$password = 'Rajat';
$userpassword = 'Rajat';
echo $password;
echo "\n";
echo "Salt: ";
$salt = substr(uniqid(rand()),0,22);
echo $salt;
echo "\n";
echo "Using Blowfish: ";
$bf = crypt($password,'$2y$10$'.$salt);
echo $bf;
echo "\n";
echo "Starting password checking...\n";
$full_bf_salt = substr($bf,0,29);
$verify_hash = crypt($userpassword,$full_bf_salt);
echo "Verified calculated hash: ".$verify_hash;
if($verify_hash==$bf){
 echo "Password is correct\n";
}else{
 echo "Password is incorrect\n";
}
?>

大多数情况下,crypt函数按预期工作,但有时会失败。有人知道为什么或者有什么我以错误的方式实现了吗?

1 个答案:

答案 0 :(得分:1)

我设法用你的代码重现错误。当生成的盐的长度小于22时,你得到*0。在我的例子中,长度是21个字符。

Salt: string(21) "6948531853de8c4cd7a85"
Using Blowfish: *0

Bcrypt期望以base64格式编码的128位salt,导致22个字符的salt。当salt无效时,将返回*0以指示存在错误。

以下是使用mcrypt_create_iv()正确生成salt的一种方法:

$raw_salt_len = 16;
$required_salt_len = 22;

$salt = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM);

$base64_digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
$bcrypt64_digits = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

$base64_string = base64_encode($salt);
$salt = strtr(rtrim($base64_string, '='), $base64_digits, $bcrypt64_digits);

if (function_exists('mb_substr')) {
    $salt = mb_substr($salt, 0, $required_salt_len, '8bit');
} else {
    $salt = substr($salt, 0, $required_salt_len);
}

我从password_compat库中提取了此代码。我强烈建议研究它的代码。它涵盖mcrypt_create_iv()不可用时的案例等。