密码加密和存储问题

4

相关问题:

我是否正确使用PHP的crypt()函数?

使用SHA-512进行密码存储哈希还是使用blowfish(bcrypt)的crypt()?

我正在尝试弄清楚如何使用PHP安全地存储密码。经过一些阅读,我确定应该使用crypt()而不是hash(),并且应该使用blowfish(bcrypt)或SHA-512算法,我认为更经常建议使用bcrypt,虽然也有很多支持基于SHA-512的算法。

还有许多建议,我的盐应该尽可能随机,有许多建议使用openssl_random_pseudo_bytes()而不是核心rand()mt_rand()

我的主要问题是:

  1. 如果选择使用bcrypt,应考虑哪些负载因素?我注意到对于PHP 5.5,新密码API中的默认负载因子为10,因此我想至少需要该值。

  2. 负载系数与密码安全性如何相关?从我所了解的来看,该算法将进行2 ^负载系数次迭代,但我更感兴趣的是如何将其转化为防止暴力破解方法的安全性。什么是“安全”的含义?需要10年才能破解吗? 5年? 1年?

  3. 为什么应该选择bcrypt而不是基于SHA-512的方法(反之亦然)?我听说SHA-512被设计为一种快速散列方法,因此随着时间的推移,它将不会像bcrypt一样好。这是真的吗?两种方法都有盐参数,允许crypt多次迭代。

  4. 据我所知,我实现了以下测试代码,生成了bcrypt盐。这是推荐的方法吗?有更好的方法吗?

_

function gen_salt($cost)
{
    return "$2y$" . $cost . "$" . str_replace('+', '.', base64_encode(openssl_random_pseudo_bytes(22)));
}

你关心的是哈希的安全性还是速度? - N.B.
我会考虑在登录时添加类似于sleep()的东西,让它睡眠一段你想要的时间。同时,还可以添加一些代码来禁止该IP地址或在同一IP地址下进行并发尝试时增加睡眠时间。 - CSᵠ
@godka 我不确定那是否回答了问题2。此外,IP地址可以轻易地被重新制作和欺骗,因此您不能依赖IP地址来阻止某些流量,特别是来自僵尸网络的流量。 - Sammaye
@N.B. 我很好奇这两者如何平衡。我可以计时/基准测试哈希所需的时间,但我真的不知道如何确定它有多安全。 - helloworld922
好的,如果一切条件相等,我可以计算哈希所需的时间来粗略估计安全性吗?还是有其他因素我应该考虑的(比如只考虑不同负载因子下的bcrypt,以及不同迭代次数下的SHA-512)? - helloworld922
显示剩余6条评论
1个回答

1

根据评论,我创建了一个简单的基准测试来测试各种哈希方法需要多长时间。

function bcrypt_salt($cost)
{
    return "$2y$" . $cost . "$" . str_replace('+', '.', base64_encode(openssl_random_pseudo_bytes(22))) . '$';
}

function sha512_salt($cost)
{
    return "\$6\$rounds=" . $cost . "\$" . openssl_random_pseudo_bytes(16) . '$';
}

$password = "stackoverflow";
$times = 1;
echo "<p>bcrypt method</p>";
for($iters = 10; $iters < 15; ++$iters)
{
    $salt = bcrypt_salt(strval($iters));
    $pword_crypt = crypt($password, $salt);
    $start_time = microtime(true);
    for($i = 0; $i < $times; ++$i)
    {
        crypt($password, $pword_crypt);
    }
    $end_time = microtime(true);
    echo "<p> cost = $iters: " . ($end_time - $start_time) . "</p>";
}

echo "<p>SHA512 method</p>";
for($iters = 1024; $iters < 1000000; $iters *= 2)
{
    $salt = sha512_salt(strval($iters));
    $pword_crypt = crypt($password, $salt);
    $start_time = microtime(true);
    for($i = 0; $i < $times; ++$i)
    {
        crypt($password, $pword_crypt);
    }
    $end_time = microtime(true);
    echo "<p> log2(iters) = ". log($iters,2) . ": " . ($end_time - $start_time) . "</p>";
}

基准测试结果(秒):

在我的i5-m430笔记本电脑上运行:

bcrypt方法 成本=10:0.11740303039551 成本=11:0.23875308036804 成本=12:0.46739792823792 成本=13:0.96053194999695 成本=14:1.8993430137634
SHA512方法 log2(iters)=10:0.0034840106964111 log2(iters)=11:0.0077731609344482 log2(iters)=12:0.014604806900024 log2(iters)=13:0.02855396270752 log2(iters)=14:0.068222999572754 log2(iters)=15:0.12677311897278 log2(iters)=16:0.24734497070312 log2(iters)=17:0.54663610458374 log2(iters)=18:1.0215079784393 log2(iters)=19:2.0223300457001
所有条件相等的情况下,SHA-512方法需要更多的迭代次数才能与bcrypt在相同的时间内完成。话虽如此,我猜想任何需要至少0.1秒的方法都已经足够了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接