这是我第一次在PHP中使用crypt()函数,我不知道为什么它不起作用。我的代码基于这篇文章: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;
}
我使用示例密码"password"调用函数。
合成盐为:$2y$10$NzRQNjTRfP4jXKvb4TCO.G
但密码是"$2mV0NZp92R3g"
,似乎太短了。
谁能帮我弄清楚我做错了什么?
正如您在评论中所述,您使用的是PHP 5.2.x。
Blowfish的实现只在PHP中可用>= 5.3.x。如果由于任何原因无法安装较新的PHP版本,您可以在这里查看有关如何使Blowfish与较旧的PHP版本一起工作的更多信息。
由于PHP 5.2中的crypt
不支持CRYPT_BLOWFISH,因此它默认将盐解释为CRYPT_DES样式的盐。请注意,输出以"$2"开头,这是CRYPT_DES从salt输入中选择的两个字符salt,并附加到散列中,输出长度与CRYPT_DES的输出长度完全匹配。
crypt('password', '$2y$10$NzRQNjTRfP4jXKvb4TCO.G') /* in PHP 5.2 */
==
crypt('password', '$2') /* in PHP 5.4 */
理论上,如果在PHP 5.2中错误地使用了CRYPT_BLOWFISH样式的salt,这可能有助于向后兼容。
这实际上最近给我带来了一点困惑,因为根据PHP crypt文档,"$"字符不是CRYPT_DES的有效盐输入,它说:
基于des的标准散列,包含来自字母表"。/0-9A-Za-z"的两个字符盐。在salt中使用无效字符将导致crypt()失败。
但是这里的"$"字符显然在v5.2和v5.4中都被crypt()
所接受。
如果crypt
像文档所说的那样实际返回失败,而不是接受"$"并默认为CRYPT_DES,则会更清晰和更安全。
这是我的河豚加密函数....
<?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
}
?>
最初只支持以$2a$
开头的盐的河豚哈希。
$2x$
和$2y$
Blowfish模式来处理潜在的高比特攻击。
您的PHP 5.2.17不支持$2y$
河豚模式