关于安全性:您在哪里储存盐串?

Where do you store your salt strings?

在散列数据库存储的密码时,我总是使用适当的每项salt字符串。根据我的需要,将salt存储在哈希密码旁边的数据库中总是可以正常工作的。

但是,有些人建议将盐与数据库分开存储。他们的论点是,如果数据库受到破坏,攻击者仍然可以在考虑特定salt字符串的情况下构建彩虹表,以便一次破解一个帐户。如果这个帐户有管理员特权,那么他甚至不需要破解任何其他帐户。

从安全的角度来看,在不同的地方储存盐是否值得?考虑在同一台计算机上使用服务器代码和数据库的Web应用程序。如果盐存储在那台机器上的平面文件中,那么很有可能数据库受到破坏,盐文件也会受到破坏。

对此有什么建议的解决方案吗?


彩虹表的要点是,它们是预先创建的,并集中分布,以节省其他人的计算时间-在运行中生成彩虹表所需的时间与直接破解密码+盐组合所需的时间相同(因为生成彩虹表时所做的工作实际上是预运行计算因此,通过知道盐可以"生成彩虹表"的说法是错误的。

在单独的文件中存储盐没有真正的意义,只要它们是基于每个用户的基础上-盐的意义只是简单地使之成为一个彩虹表不能打破数据库中的每个密码。


我将提供一个略有不同的看法。

我总是把盐和盐密码散列一起存储。

例如,我将把盐的前半部分放在密码的盐散列之前,将盐的后半部分放在密码的盐散列之后。应用程序知道这种设计,因此可以获取这些数据,并获得salt和salt密码散列。

我采用这种方法的理由是:

如果密码/散列数据被破坏并落入攻击者手中,攻击者将不知道SALT从数据中是什么。这样一来,攻击者实际上无法执行暴力攻击以获取与哈希匹配的密码,因为他不知道要开始的哈希,也无法知道哪些数据部分是salt的一部分,或者是salt密码哈希的一部分(除非他知道应用程序的身份验证逻辑)。

如果salted密码散列按原样存储,则可以执行暴力攻击以获取一个密码,当salted和hashed产生与salted密码散列相同的数据时,该密码将被执行。

但是,例如,即使salted密码散列按原样存储,但预先挂起一个随机字节,只要攻击者不知道第一个字节将被丢弃,这也会增加攻击的难度。当用于验证用户身份时,应用程序将知道丢弃数据的第一个字节。

结论……

1)永远不要将您的身份验证应用程序使用的数据以其准确的形式存储。

2)如果可能,为增加安全性,请对您的身份验证逻辑保密。

再往前走一步……

如果您不能对应用程序的身份验证逻辑保密,那么许多人都知道您的数据是如何存储在数据库中的。假设您已经决定将盐密码散列与盐混合存储在一起,其中一些盐在盐密码散列前面,其余的盐在散列后面。

当生成随机的salt时,您还可以随机决定在salt密码哈希之前/之后要存储的盐的比例。

例如,生成512字节的随机salt。您将salt附加到您的密码,并获得您的salt密码的sha-512哈希。您还可以生成一个随机整数200。然后存储前200个字节的salt,然后存储salt密码散列,最后存储其余的salt。

当验证用户的密码输入时,应用程序将传递字符串,并假设数据的前1个字节是salt的前1个字节,然后是salt散列。这个通行证将失败。应用程序将继续使用数据的前2个字节作为salt的前2个字节,并重复,直到在使用前200个字节作为salt的前200个字节后找到正结果。如果密码错误,应用程序将继续尝试所有排列,直到找不到为止。

这种方法的优点是:

提高了安全性—即使您的身份验证逻辑已知,但在编译时确切的逻辑是未知的。即使知道确切的逻辑,也几乎不可能执行蛮力攻击。增加盐的长度将进一步提高安全性。

这种方法的缺点是:

由于确切的逻辑是在运行时推断出来的,所以这种方法占用大量CPU。盐的长度越长,这种方法的CPU强度就越大。

验证不正确的密码将涉及最高的CPU成本。这可能会对合法请求产生反作用,但会提高对攻击者的安全性。

这种方法可以以各种方式实现,并且可以通过使用可变宽度的salts和/或salted密码散列使其更加安全。


通常情况下,它们被预先添加到散列并存储在同一个字段中。

不需要单独存储它们——重点是对每个密码使用随机的salt,这样就不能对整个密码哈希集使用一个彩虹表。对于随机的盐类,攻击者必须对每个散列值分别强制执行(或者为所有可能的盐类计算一个彩虹表——要做的工作要多得多)。

如果您有一个更安全的存储位置,那么只将散列存储在那里是有意义的。


基于William Penberthy的《开发ASP.NET MVC 4 Web应用程序》一书:

  • 要访问存储在单独数据库中的盐,需要黑客攻击两个不同的数据库可以访问salt和salted密码。将它们存储在与密码相同的表,甚至同一数据库的另一个表都将这意味着当黑客访问数据库时,他们将可以访问salt和密码哈希。因为安全包括黑客攻击的过程进入系统的成本太高或时间太长,不值得,将金额翻倍如果让系统更安全,黑客必须获得的访问权限。
  • 易用性是保持盐与哈希密码。您不必确保两个数据库始终可用同时,始终保持同步。如果每个用户都有一个随机的盐,因为尽管它可能会发现一个人的密码更容易,破解密码所需的力度系统总体将很高。在这一级别的讨论中,这正是我们所期望的是:保护密码。如果黑客获得了数据库的副本,您的应用程序数据已被破坏。此时,问题是要减轻用户的共享密码的潜在风险。
  • 维护两个独立的链接数据库的要求非常广泛。当然,它增加了对安全的感知,但它所给予的唯一好处是它可以保护一个密码,一个数据元素。如果数据库中的每个字段都是单独的加密的,同样的盐也用于此目的,存储它会更有意义。与数据分开,因为系统的基本安全性得到了增强。

  • 盐的作用是使所有彩虹桌都变得无用,并要求制作一套新的彩虹桌。猜一根绳子就像做一张彩虹桌一样长。例如,"password"的sha-256散列是5e88 4898 da28 0471 51d0 e56f 8dc6 2927 7360 3d0d 6aab bdd6 2a11 ef72 1d15 42d8。添加salt后,例如"badpassword",要散列的新字符串是"passwordbadpassword",由于雪崩效应,它会将输出显著更改为457b f8b5 37f1 802e f9c8 2e46 b8d3 f8b5 721b 7cbb d485 f0bb e523 bfbe 73e6 58d6

    通常,salt与密码存储在同一个数据库中,也因为如果一个数据库被黑客攻击,另一个数据库也很可能被黑客攻击。