6

我正在尝试生成河豚哈希,我想知道依靠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)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 快 - 但它包含无效的河豚字符,如+. 所以现在改成md5。

function blowfish($string, $salt = NULL, $iterations = '12')
{
    return crypt($string, $salt ?: "$2a\$$iterations$" . md5(mcrypt_create_iv(22, MCRYPT_DEV_URANDOM)));
}
4

2 回答 2

6

使用mcrypt创建盐。

于 2012-04-16T23:40:40.823 回答
4

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

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

PHP/密码最佳实践

盐生成和 PHP

不要自己滚动

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

于 2012-04-16T23:44:06.017 回答