0

我需要将密码存储在数据库中,并且我曾经将加盐密码的 sha1 哈希与随机盐一起存储,该随机盐是循环的,如下所示:

$salt = sha1(microtime().mt_rand());
for ($i=0; $i < 4000; $i++) {
    $password = sha1($password.$salt);
}

(在我的示例中,$password$salt存储在数据库中)。

我最近发现了这个hash_hmac()函数,它显然是一个比简单的 SHA1 哈希更安全的函数。我计划以相同的模式使用它(盐是密钥),但我想知道它是否值得像我之前的示例中那样循环它。如果有人能给我一些见解,那将不胜感激。

4

1 回答 1

2

是的。

您在此处所做的操作称为密钥拉伸,它会使攻击者检查每个候选密码与哈希值所需的时间相乘。在您的示例中,它将时间增加了 4000 倍。您在这里要防御的具体威胁是当攻击者掌握了您的哈希值(例如最近发生在 LinkedIn、Last.fm 和 eHarmony 上的事情)并且可以投入尽可能多的 CPU 能力来破解它们。

如果这不是研究项目,您应该使用众所周知且经过公开测试的函数,例如bcrypt(),PBKDF2()scrypt().

该循环中的数字应该远高于 4000,并且由于您的攻击者将使用 C 循环而不是 PHP 循环,因此您将无法在合理的时间内完成他想做的那么多。即使在 PHP 循环中,我也可以在 0.3 秒内完成 500,000 次。上述散列算法解决了这个问题,因为它们将在 C 中实现。(并非所有这些算法都可以在 PHP 中使用。)它似乎bcrypt在 5.3 中,但它被称为CRYPT_BLOWFISH. 有关如何使用它的详细信息,请参见 crypt() 页面


hash_hmac()不是更安全的散列算法,而是用于不同的目的。在此处查看Thomas 答案的结尾。像MD5SHA家族这样的算法是通用哈希算法,通常用作特定目的的更具体算法的一部分。例如,上述一些密码散列算法多次使用通用散列算法。 has_hmac()询问您要使用哪种通用哈希算法。

于 2012-06-21T07:49:47.023 回答