如果盐是未知的,破解 bcrypt 哈希有多难?

信息安全 密码 哈希 bcrypt
2021-08-13 16:28:16

(这不是链接问题恕我直言的重复,因为这更多的是关于盐和密码之间的差异:两个变量都用于生成哈希)

假设攻击者可以离线访问数据库,其中密码使用 bcrypt 散列(没有添加胡椒)。哈希看起来像:

$2y$10$H0mRpD2XJZDguAzxTehwzunRkjUR8lB3O4UGrAGLiqJuvnlWjFA7G

其中盐是:H0mRpD2XJZDguAzxTehwzu哈希是nRkjUR8lB3O4UGrAGLiqJuvnlWjFA7G.

攻击者将无法运行彩虹表来匹配哈希,但她可以使用包含的盐计算常见密码,因此执行:

bcrypt("abcd1234", 10, "H0mRpD2XJZDguAzxTehwzu")

将产生:

nRkjUR8lB3O4UGrAGLiqJuvnlWjFA7G

你有!她可以通过所有数据库测试“abcd1234”,并能够在几秒钟/几分钟内识别出哪些用户正在使用该弱密码。

那么如果只有哈希nRkjUR8lB3O4UGrAGLiqJuvnlWjFA7G存储在数据库中(没有盐)呢?

如果攻击者强烈认为用户“abcdefg”可能正在使用密码“abcd1234”,她如何离线测试她的理论?她需要猜盐。她怎么可能做到?有没有比尝试每种组合更简单的方法?也许在那种特定情况下,没有足够的动力去尝试它。但是,如果她怀疑系统对所有密码使用相同的盐(因为某些哈希值是相同的)怎么办?她要破解它有多难?


更新

Peleus 的回答接近我的预期。我将尝试扩展它(如果我错了,请纠正我):

在 Bcrypt 中,盐通常是 16 个随机字节(128 位)。如果我们将其与相同长度的密码进行比较,那么盐的熵将比密码更大,因为密码通常仅限于用户可以使用键盘键入的内容。

这 16 个字节被编码为 HEX(使用 Base64)并变成 22 个长度。如果我们将它们与 22 个字符的密码进行比较,那么密码将包含更大的熵(因为它可以包含符号和完整的字母表)。

长度

Bcrypt 盐限制为 16 个字节,而密码可能限制为 72 个字节,具体取决于实现。

碰撞

2 种不同的盐将生成 2 种不同的哈希值,因此密码也是如此。然而,在某些时候,2 个不同的盐可以使用相同的密码产生相同的哈希值,反之亦然。每种情况的概率是多少?这也许是我应该在 crypto.SE 中问的问题。但我把它留在这里,以防有人知道它的答案。

设计

该算法旨在保护密码而不是盐。这意味着盐在设计上并不意味着安全,这表明可能有一种方法可以在不强制使用的情况下获得它们。

虚构案例

我们习惯于使用用户密码方法来保护对系统的访问。但是,如果发生这样的事情怎么办(请告诉我,这只是一个例子)?:

公司CauseWeWantItThatWay使用微芯片存储唯一的 22 位十六进制字符值(用作盐)。每个用户将使用该唯一盐生成总共 5 个密码或 PIN 码(每个 4 位,是的,他们很懒惰)以访问 5 个不同的系统。

现在让我们假设我被分配到其中一个系统,并且我知道其中一个 PIN 码,并且不知何故我可以访问数据库。如果包含盐,那么获得这些 PIN 码将是微不足道的,但是如果没有盐,我将不得不破解它。

我知道你在想什么。该公司的安全实施非常糟糕(他们应该在地狱中燃烧)。此外,他们本可以使用“盐”作为胡椒粉,而让盐随意放置。所以我的问题是,在那种情况下,添加一个 22-hex-chars 作为胡椒和使用那些作为盐是一样的吗?根据 Peleus 的说法,是相同的(因此不存在获取盐的捷径)。

毕竟不是每个人都遵循建议,并且算法允许您设置盐,这使得这种情况完全可能(尽管不太可能也不推荐)。

3个回答

我认为您误解了盐的目的,因为如果您了解它的目的是为了实现您可能不会问这个问题。唯一的目的是为每个密码提供一定程度的唯一性,以防止预先计算的表(“彩虹表”)成为一种有效的攻击形式。

因此,它并非设计为“秘密”或以任何方式向密码添加熵,这就是为什么它与密码的哈希一起存储的原因。事实上,在大多数情况下,它不能保密,因为应用程序本身需要访问 salt 才能计算出正确的密码哈希值。允许访问应用程序是非常困难的,但要防止已经破坏应用程序的攻击者获得相同的权限。

无论如何,要回答您的实际问题-在理论世界中,您必须“破解”盐,因为它是未知的,并且由于某种原因无法检索,它与密码的复杂程度完全相同。基本上(字符空间)^(长度)。

在您的示例中,您给出了“H0mRpD2XJZDguAzxTehwzu”的哈希值。假设大写/小写字母数字是 62 个字符的字符空间,并且它的长度为 22 个字符。因此 62^22 = 3.397504e+23 年的猜测假设每秒有 10 亿次猜测。换句话说,不可破解(这甚至假设密码是已知的并且您试图简单地猜测系统范围的盐)。

盐存储在密码旁边。没有规则说它必须是这样的,但这是盐的预期目的的逻辑结果。构建彩虹桌并非易事。加盐的要点是,攻击者需要为每个加盐密码创建一个单独的彩虹表(在这种情况下,直接攻击每个密码哈希会更容易)。

您可以阅读有关 salt 的长答案,这应该清楚为什么没有必要保密。

如果你想包含一些秘密盐,你应该阅读通常称为辣椒的东西,它会在你的加盐密码中添加一个应用程序范围的密钥。可以保护您免受部分破坏(例如通过 SQL 注入导致的数据库破坏),但在整个系统破坏的情况下无济于事,除非您使用硬件安全模块 (HSM) 来保护胡椒值。

当攻击者只知道哈希而不知道盐时,他们不仅要测试每个可能的密码,而且还要用所有可能的盐测试每个可能的密码。对于长且随机的盐值,这实际上是不可能的。

然而,这不是一个现实的场景。当攻击者破坏系统时,您必须假设他们破坏了哈希和盐的数据库。以某种方式分离这两个数据集是不可行的,因为它们总是一起使用。