为密码存储盐
Storing Salts for Passwords
我一直在做一些关于存储盐的研究,显然最常见的方法是将它存储在与用户名和密码相同的单独列中 table。我在这个网站和其他网站上都看到过,但对我来说,这就像把钥匙放在保险箱旁边一样。如果有人能够访问身份验证 table,黑客就会获胜。如果他们这样做了,但那里找不到盐,他们就没有那么多的事情要做了。
我运行一个三层系统,并且更喜欢将盐存储在 Java 运行的中间层某处的方法,该中间层位于防火墙后面并且无法直接从 Internet 访问。也许应用程序其他部分的某些 XML 或 none 会触及?
那么让我们来看看盐到底是什么。
这是确保
的一种方式
- 两个拥有密码的用户并不明显。
- "password" 与 PBKDF2-HMAC-SHA-512,10000 次迭代,仅保留输出的前 32 个字节,存储在 Base64 中,空字符串的盐总是
9MpQfAfQvTG8d5oIdWgmpv2d2X1DrCXkspoJM6vqA/M=
- 因此,如果您有 5% 的用户将其作为密码哈希值,您可以非常确定它是 "password" 或“12345”或其他最糟糕的密码之一。
攻击者无法在泄漏之前预先计算攻击列表,然后几乎立即将他们的 "rainbow table" 结果与泄漏匹配以消除整个预先计算的列表,然后继续破解困难无需在简单的密码上浪费宝贵的时间。
因此,如果攻击者的密码列表为 "password" 和“12345”,并且您不使用 salt,那么他们已经发现上述设置的结果是:
9MpQfAfQvTG8d5oIdWgmpv2d2X1DrCXkspoJM6vqA/M=
和
I2bEyBbaxTBvHdJ7rIu7kdR2liwGMCg62lyuoj41NB8=
因此,攻击者获得了您的密码列表,他们几乎立即消除了在您的许多用户选择糟糕密码上花费的任何计算时间,这意味着他们有更多的时间和组合,剩下尝试更高难度的目标。
如果您为每个用户 ID 使用 16 字节的加密随机盐,那么他们不必为列表中的每个密码*规则执行一次哈希算法,他们必须执行 2^128每个时间,这在此时计算上是不可行的,更不用说存储要求了。
将 salt 保密是没有意义的 - 它可以满足这两个目的,不需要比密码哈希本身更多的保密性。
我一直在做一些关于存储盐的研究,显然最常见的方法是将它存储在与用户名和密码相同的单独列中 table。我在这个网站和其他网站上都看到过,但对我来说,这就像把钥匙放在保险箱旁边一样。如果有人能够访问身份验证 table,黑客就会获胜。如果他们这样做了,但那里找不到盐,他们就没有那么多的事情要做了。
我运行一个三层系统,并且更喜欢将盐存储在 Java 运行的中间层某处的方法,该中间层位于防火墙后面并且无法直接从 Internet 访问。也许应用程序其他部分的某些 XML 或 none 会触及?
那么让我们来看看盐到底是什么。 这是确保
的一种方式- 两个拥有密码的用户并不明显。
- "password" 与 PBKDF2-HMAC-SHA-512,10000 次迭代,仅保留输出的前 32 个字节,存储在 Base64 中,空字符串的盐总是
9MpQfAfQvTG8d5oIdWgmpv2d2X1DrCXkspoJM6vqA/M=
- 因此,如果您有 5% 的用户将其作为密码哈希值,您可以非常确定它是 "password" 或“12345”或其他最糟糕的密码之一。
- "password" 与 PBKDF2-HMAC-SHA-512,10000 次迭代,仅保留输出的前 32 个字节,存储在 Base64 中,空字符串的盐总是
攻击者无法在泄漏之前预先计算攻击列表,然后几乎立即将他们的 "rainbow table" 结果与泄漏匹配以消除整个预先计算的列表,然后继续破解困难无需在简单的密码上浪费宝贵的时间。
因此,如果攻击者的密码列表为 "password" 和“12345”,并且您不使用 salt,那么他们已经发现上述设置的结果是:
9MpQfAfQvTG8d5oIdWgmpv2d2X1DrCXkspoJM6vqA/M=
和
I2bEyBbaxTBvHdJ7rIu7kdR2liwGMCg62lyuoj41NB8=
因此,攻击者获得了您的密码列表,他们几乎立即消除了在您的许多用户选择糟糕密码上花费的任何计算时间,这意味着他们有更多的时间和组合,剩下尝试更高难度的目标。
如果您为每个用户 ID 使用 16 字节的加密随机盐,那么他们不必为列表中的每个密码*规则执行一次哈希算法,他们必须执行 2^128每个时间,这在此时计算上是不可行的,更不用说存储要求了。
将 salt 保密是没有意义的 - 它可以满足这两个目的,不需要比密码哈希本身更多的保密性。