Bcrypt中盐的随机性有多重要?

3
我需要为Bcrypt生成盐,并试图理解我的PRNG需要多随机,以使盐不会太弱而使使用Bcrypt毫无意义。我有五个一般的随机性来源:
  1. Perl 5自带的 PRNG,使用默认种子进行初始化(似乎是当前秒的分数、持有当前秒的东西的地址、进程的pid以及Perl堆栈指针的地址混合在一起并与一些素数混合)
  2. Perl 5自带的 PRNG,使用其他种子进行初始化
  3. Math::Random::Secure 这样基于Perl 5的其他PRNG
  4. 只需从/dev/urandom读取字节
  5. 只需从/dev/random读取字节
在我看来,这段代码将在的机器上已经对/dev/random过度使用了(当计算机繁忙时,/proc/sys/kernel/random/entropy_avail低于500),否则这将不是问题,我将只使用/dev/random。 话虽如此,如果很重要,我仍然会使用/dev/random/(人们并不经常设置新密码)。
4个回答

6

Salt被用来在同一输入上多次运行哈希函数时使输出不同,并防止彩虹表攻击。密码强度由函数本身的实现提供。任何合理分布的随机数生成器都可以用于Salt,没有真正的熵是必要的。


3
密码盐不需要随机或者保密,重要的是每个密码的盐值必须是唯一的。请参考Schneier的《应用密码学》第二版52-53页的摘录。
随机选择位数是一种实现方式,可以生成具有一定碰撞概率的唯一盐值。这通常被认为是一个不错的权衡,因为这样的盐生成器不需要特权来读取系统中当前使用的盐值列表。
使用bcrypt时,盐值以明文形式存储以备后续的身份验证尝试。这意味着您系统中所有哈希密码的列表都可能会被泄露。此时,随机盐值无济于事。请注意下面摘录的最后一段话的要点:盐值可以使字典攻击变得困难,但仅限于某个程度。
保守的做法是使用加密安全的随机数生成器来选择盐值,“以防万一”,但这取决于您所要保护的价值以及对手愿意投入多少努力,这可能会过度杀伤。

字典攻击和盐

使用单向函数加密的密码文件仍然是有漏洞的。Mallory在空闲时间内编制了一个包含1,000,000个最常见密码的列表。他对这100万个密码都进行了单向函数操作并存储了结果。如果每个密码大约8字节,那么生成的文件将不超过8兆字节;它可以放在几张软盘上。现在,Mallory窃取了一个加密密码文件。他将该文件与他的可能加密密码文件进行比较,并查看匹配项。

这就是一种字典攻击,而且成功率惊人(参见第8.1节“生成密钥”)。是一种使攻击变得更困难的方法。盐是一个随机字符串,在进行单向函数操作之前与密码连接在一起。然后,盐值和单向函数的结果都存储在主机上的数据库中。如果可能的盐值数量足够大,则这几乎消除了对常用密码的字典攻击,因为Mallory必须为每个可能的盐值生成单向哈希。这是一个简单的初始化向量尝试(请参见第9.3节“密码块链模式”)。

关键在于确保每次试图破解另一个人的密码时,Mallory必须对他字典中的每个密码进行一次试验性加密,而不是只进行一次所有可能密码的大量预计算。

需要很多盐。大多数UNIX系统只使用12位盐。即使如此,Daniel Klein开发的密码猜测程序通常可以在一周内破解给定主机系统上40%的密码[847,848](请参见第8.1节)。David Feldmeier和Philip Karn编制了一个包含约732,000个常见密码和4096个可能盐值的列表。他们估计,在任何给定主机上,30%的密码可以用这个列表破解[561]。

盐不是万能药;增加盐位数并不能解决所有问题。盐只能防止对密码文件进行一般字典攻击,而不能防止对单个密码进行有计划的攻击。它保护那些在多台设备上使用相同密码的人,但它并不能让选择不当的密码变得更好。

561. D.C. Feldmeier and P.R. Karn, “UNIX Password Security—Ten Years Later,” Advances in Cryptology—CRYPTO ’89 Proceedings, Springer-Verlag, 1990, pp. 44–63.
847. D.V. Klein, “ ‘Foiling the Cracker’: A Survey of, and Implications to, Password Security,” Proceedings of the USENIX UNIX Security Workshop, Aug 1990, pp. 5–14.
848. D.V. Klein, personal communication, 1994.


你知道Bcrypt如何使用盐吗?对于传统的哈希算法,我同意唯一性是最重要的事情,但我还没有时间详细研究Bcrypt以确保它以相同的方式使用其盐。 - Chas. Owens
2
根据定义,强算法必须保持强大(撇开暴力/字典攻击的问题),无论输入数据是什么。盐值只是这个输入数据的一部分。如果算法对于特定的输入有问题,你将会面临比仅仅确保其“合适”的盐值更加严重的问题。 - Oleg V. Volkov

1

我建议使用Math::Random::Secure,因为它通常会从/dev/urandom读取。

您可以使用弱随机种子,但这样做,您就有点赌博了,因为bcrypt可能存在一种仅在盐“容易”可预测时才出现的弱点。机会是,您没问题,但您也偏离了加密最佳实践。

对于密码,我会默认“以正确的方式处理”。


1

我最终阅读了描述Bcrypt的原始文章,并找到了以下引用:

任何bcrypt实现的一个重要要求是利用完整的128位盐空间。OpenBSD从一个arcfour(arc4random(3))密钥流生成128位bcrypt盐,该密钥流使用内核从设备定时收集的随机数据进行种子处理。

基于此,我将使用/dev/random来初始化高质量PRNG以生成种子。

使用高质量PRNG的原因也可以在文章中找到


你有128位的盐值。你真的相信你会在任何合理的非熵 RNG 中实现碰撞吗? - Oleg V. Volkov
@OlegV.Volkov 我认为来自链接文章的这句话很好地概括了它:“然而,在实践中,我们发现盐碰撞的数量通常比预期的要高。原因是许多操作系统生成较差的随机数。” 如果您的盐没有在128位空间中随机分布,攻击者可能会获得优势,类似于您使用了较小的盐或稍微弱一些的算法。 - Michael Lucas

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