我正在尝试生成河豚哈希,我想知道它是否足够安全,可以指望 mt_rand() 为我生成盐?
function blowfish($string, $salt = NULL, $iterations = '08')
{
if( ! $salt)
{
$seed = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for ($i = 0; $i < 22; $i++)
{
$salt .= $seed{mt_rand(0, 63)};
}
$salt = '$2a$' . $iterations . '$' . $salt;
}
return crypt($string, $salt);
}
上面$seed字符是允许的 64 个字符的河豚盐字母表。我计划使用它来生成和比较密码。
$password = 'my^$%#password';
$hash = blowfish($password);
if($hash = blowfish($password, $hash))
{
print "Matches'n";
print $hash . "'n";
}
编辑
我从来没有意识到这一点,但@zerkms说的是真的。盐只是为了防止可重用的预计算攻击,因为盐在它们有权访问哈希的同一点是已知的。所以目标不是不可逆的盐 - 它是一种随机盐。
那么,这有什么问题吗?
function blowfish($string, $salt = NULL, $iterations = '12')
{
return crypt($string, $salt ?: "$2a'$$iterations$" . md5(uniqid('', true)));
}
此外,如标题和上面的代码中所述,我没有实现自己的哈希算法。
更新 2
如果加载,使用 mcrypt 扩展会导致以下内容,这实际上更快,可能是因为 uniqid
(u) 睡眠或其他什么。
function blowfish($string, $salt = NULL, $iterations = '12')
{
return crypt($string, $salt ?: "$2a'$$iterations$" . base64_encode(mcrypt_create_iv(22, MCRYPT_DEV_URANDOM)));
}
更新 3
base64_encode 比 md5 快 - 但它中有无效的河豚字符,如 +
.所以现在改为 md5。
function blowfish($string, $salt = NULL, $iterations = '12')
{
return crypt($string, $salt ?: "$2a'$$iterations$" . md5(mcrypt_create_iv(22, MCRYPT_DEV_URANDOM)));
}
使用 mcrypt 创建盐。
使用mt_rand作为盐,足够安全;显然,前提是您使用每个密码不同的随机盐。
然而,话虽如此;几乎任何自我实现的密码哈希系统都是不安全的。很少有人精通生成和维护安全的密码哈希系统。作为参考,我恳请您阅读一些 SO 线程:
PHP/密码最佳实践
盐生成和PHP生成
不要自己滚动
我建议不要自己滚动。时期。如果可能的话,请考虑使用已建立的PhPass密码散列PHP库。优点包括实际应用程序测试、高度安全的实施和极高的易用性。