【问题标题】:Security of generating hash salts using PHP's mt_rand()?使用 PHP 的 mt_rand() 生成哈希盐的安全性?
【发布时间】: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) 几乎无法预测,不仅仅是数字

标签: php hash salt prng


【解决方案1】:

使用mcrypt 创建盐。

【讨论】:

  • 这是个好主意,我可以使用MCRYPT_DEV_RANDOM 而不是手动打开到/dev/urandom 的连接并从中读取然后将其转换为base64。
  • MCRYPT_DEV_RANDOM 打开与/dev/random 而非/dev/urandom 的连接。 MCRYPT_DEV_URANDOM 打开与/dev/urandom 的连接。
【解决方案2】:

使用 mt_rand 作为盐,足够安全;显然,您使用每个密码不同的随机盐。

但是,话虽如此;几乎所有自行实现的密码散列系统都是不安全的。很少有人精通生成和维护安全的密码散列系统。作为参考,我恳请您阅读一些 SO 主题:

Php/Password best practices

Salt generation and PHP

Do not roll your own

我建议不要自己动手。时期。如果可能,请考虑使用已建立的库 PhPass of password hashing 用于 PHP。好处包括真实世界的应用程序测试、高度安全的实施和极易使用。

【讨论】:

  • +1 安全需要大量时间和技能才能做好。为什么不利用那些在你之前犯过错误的人呢?
  • "自我实现的密码哈希系统不安全" --- 我没有看到自我实现的哈希,是吗?
  • @pst: 你有什么真正的反对 md5 + uniqid 生成盐
  • @pst:盐生成算法无关紧要——唯一重要的是结果盐是随机的。对不起,我很无聊讨论这种琐碎的事情
  • @zerkms 不用担心,你完全正确。当你无法让别人理解你的意思时总是很烦人,而我错了。
猜你喜欢
  • 2010-09-28
  • 2019-03-13
  • 2017-03-16
相关资源
最近更新 更多