1

我想在我的系统中使用 Bcrypt 进行密码加密。但是所有的例子都是这样的:

$password = $_POST['password'];
$salt = substr(str_replace('+', '.', base64_encode(sha1(microtime(true), true))), 0, 22);
$hash = crypt($password, '$2a$12$'.$salt);

这对我来说看起来很安全,但我想知道,在每个示例中,没有人在使用 Bcrypt 之前对密码进行哈希处理。

由于独特的盐,Rainbow 表应该无法一次破解所有密码。但是,如果黑客获取一条记录并使用该特定记录的盐创建一个彩虹表,他应该能够破解一个弱密码。

因此,如果有人使用弱密码(比如说“foo”),在使用 Bcrypt 之前先使用 SHA-512 对其进行哈希处理会更安全。我对吗?或者这只是看起来更安全?

4

4 回答 4

2

实际上答案必须是no,它不会使散列在密码学意义上显着更强。您可能知道,bcrypt(虽然要使用的函数名为crypt)本身就是一个散列函数,而不是一个加密函数。

在 bcrypt 中,您传递了一个成本因子,它定义了将完成多少次迭代(通常是数百次)。这会减慢哈希的计算速度,这使得蛮力攻击变得不切实际。之前使用 SHA-512,只会多增加一次迭代。

您所说的是正确的,但是当然如果您必须为每个密码构建一个彩虹表,您将简单地暴力破解直到找到匹配项,无需构建整个彩虹表。

如果攻击者可以控制数据库和代码,那么额外的 SHA-512 将毫无帮助(仅多一次迭代)。如果他只有没有代码的数据库(SQL-Injection),那么他将识别 bcrypt 哈希。他现在可以使用 bcrypt 进行暴力破解,但由于 SHA-512,没有任何弱密码。这就像 SHA-512 哈希将是破解密码,所以字典是没有用的。这是默默无闻的安全性,但只要代码未知,它就会有效。在使用带有唯一盐的 bcrypt 之前,您可以通过添加一个固定的硬编码盐(密钥)更容易获得相同的效果。

于 2012-06-30T20:00:23.853 回答
1

crypt()是一种单向字符串散列,而不是一种加密机制。要使用 SHA-512 哈希,您必须使用该hash()函数。Bcrypt 需要 PHP 扩展。对于存储密码,为什么要使它们可逆,而不仅仅是散列它们?这不太安全——如果有人得到了你的密钥和数据库,他们就有了所有的密码,但是一个 SHA512 哈希表是毫无用处的。

于 2012-06-30T18:50:31.590 回答
1

首先散列无济于事。错误密码是攻击者认为更有可能出现的密码,并在他尝试使用的密码列表中较早放置。

Bcrypt 结合了盐来消除预先计算的查找表(彩虹表就是一个例子)。为什么攻击者要为单个记录构建彩虹表?不,当攻击一个加盐密码时,攻击者只需通过他最可能的密码的有序列表,重复哈希算法来查看它是否匹配。

他可以通过该列表工作多长时间取决于哈希算法执行多长时间。Bcrypt 用“成本”因素来控制它——在你的例子中是 12(这没关系,但可能是我使用的最低限度)。额外的 SHA-512 轮并没有增加任何东西。您已经在执行 4096 次昂贵的 bcrypt 迭代。添加 1 个廉价的 SHA-512 迭代可以忽略不计。

如果您选择列表中的第一个密码,它将在几分之一秒内被破解。如果你选择了第 10 亿个密码,攻击者在几十年内都不会破解它。

于 2012-06-30T19:28:32.557 回答
0

bcrypt 已经使用了 salt,它在内部做的事情比 SHA512 强很多。在 bcrypt 之上添加 SHA512 迭代(和/或额外的一层盐)不会给你带来明显更强的结果。如果这两个函数以错误的方式交互,以这种方式组合它们实际上可能会给你一个更弱的哈希函数。

于 2012-06-30T19:18:42.157 回答