【发布时间】:2012-04-28 07:30:33
【问题描述】:
我正在尝试生成河豚哈希,我想知道依靠 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 个字符 blowfish-salt alphabet。我打算用它来生成和比较密码。
$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)sleeps 或其他原因。
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 快 - 但它包含 invalid 河豚字符,例如 +。所以现在改成md5了。
function blowfish($string, $salt = NULL, $iterations = '12')
{
return crypt($string, $salt ?: "$2a\$$iterations$" . md5(mcrypt_create_iv(22, MCRYPT_DEV_URANDOM)));
}
【问题讨论】:
-
盐生成算法无关紧要。重要的是每个密码都有不同的盐。 ps:我个人认为你目前的盐生成过度设计,我会选择
md5(uniqid('', true)) -
@pst:我的建议有任何真正的问题吗?
-
你可以使用
$salt = substr(str_shuffle("./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), -22);可能更快.. -
ps:这里似乎还有另一个编程神话:关于盐生成算法的高估。
-
@Lattyware:“这意味着你让他们知道你正在使用什么盐”——那又怎样?盐并不打算保密。 “这在理论上意味着他们可以预先计算攻击”——现在的彩虹表是无稽之谈,CPU 更便宜codinghorror.com/blog/2012/04/speed-hashing.html PS:
uniqid('', true)几乎无法预测,不仅仅是数字