你在哪里储存盐串?

fri*_*edo 242 security authentication hash cryptography salt

在散列数据库存储密码时,我总是使用正确的每个条目的盐字符串.根据我的需要,将盐存储在哈希密码旁边的数据库中一直运行正常.

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

从安全角度来看,将盐储存在不同的地方是否值得?考虑在同一台机器上具有服务器代码和DB的Web应用程序.如果盐存储在该机器上的平面文件中,则很可能如果数据库受到损害,则salt文件也是如此.

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

Amb*_*ber 248

彩虹表的重点在于它们是事先创建的,并且是为了节省其他人的计算时间而集中分配 - 生成彩虹表需要同样长的时间,因为它只是直接破解密码+盐组合(因为实际上,在生成彩虹表时正在执行的操作是预先运行用于强制执行散列的计算,因此通过了解某人可能"生成彩虹表"的参数是虚假的.

将盐存储在单独的文件中没有任何意义,只要它们是基于每个用户的 - 盐的目的只是为了使一个彩虹表不能破坏数据库中的每个密码.

  • 同意.您通过单独存储盐来保护的威胁模型是一个用户,他可以通过恶意方式以某种方式访问​​数据库中的salt,但不能访问哈希(在数据库中).而且那个人会提前开始计算彩虹表,假设他以后能够找到哈希.并非不可能,但也不值得为这个单一攻击途径捍卫aginst的工程努力. (16认同)
  • @Jigzat - 如果你没有为每个用户提供单独的盐,那么Salting是没有意义的.salt的要点是为每个用户密码打破哈希单独的任务; 如果所有人的盐相同,那就不是这样了. (9认同)
  • @TomRitter不是唯一的案例.你假设所有的密码都很复杂.一些攻击者可能会使用salt和hash并仅检查10,000个最常用的密码.这样他们就会得到相当多的人.但是,如果他们没有访问盐,则类似于用户拥有更长安全性的密码.现在,在密码数据库被盗的情况下,盐数据库保持安全的可能性有多大可供辩论,但这是一个单独的问题. (3认同)

Ibr*_*eem 33

我会对此略有不同.

我总是使用salted-password哈希存储混合的盐.

例如,我将在密码的salted-hash之前放置salt的前半部分,在密码的salted-hash之后放置salt的后半部分.应用程序知道此设计,因此可以获取此数据,并获取salt和salted-password哈希.

我对这种方法的理由:

如果密码/哈希数据被泄露并落入攻击者的手中,攻击者就不会知道查看数据的盐是什么.这样,攻击者实际上无法执行暴力攻击来获取与哈希匹配的密码,因为他不知道哈希开头并且无法知道数据的哪些部分是盐的一部分,或者salted-password hash的一部分(除非他确实知道你的应用程序的身份验证逻辑).

如果salted-password哈希按原样存储,则可以执行暴力攻击以获得密码,该密码在salted和hashed产生与salted-password哈希相同的数据时.

但是,例如,即使salted-password哈希按原样存储,但预先填写了一个随机字节,只要攻击者不知道要丢弃第一个字节,这也会增加难度攻击 当用于验证用户身份时,您的应用程序会知道丢弃数据的第一个字节.

对此的结论..

1)切勿以您的确切形式存储您的身份验证应用程序使用的数据.

2)如果可能,请将您的身份验证逻辑保密,以增加安全性.

更进一步..

如果您无法保密应用程序的身份验证逻辑 - 很多人都知道您的数据如何存储在数据库中.并且假设您已经决定将salted-password哈希与salt一起存储,其中一些盐在salted-password哈希之前加上,其余的盐附加在它上面.

生成随机盐时,您还可以随机确定在盐渍密码哈希之前/之后存储的盐的比例.

例如,您生成512字节的随机盐.您将salt附加到您的密码,并获取您的salted密码的SHA-512哈希值.您还生成一个随机整数200.然后存储salt的前200个字节,然后是salted-password哈希,然后是salt的其余部分.

在验证用户的密码输入时,您的应用程序将遍历字符串,并假设数据的前1个字节是salt的前1个字节,后跟salted-hash.这个过程将失败.应用程序将继续使用数据的前2个字节作为salt的前2个字节,并重复直到使用前200个字节作为salt的前200个字节后找到肯定结果.如果密码错误,应用程序将继续尝试所有排列,直到找不到密码.

这种方法的优点:

提高安全性 - 即使您的身份验证逻辑已知,在编译时也不知道确切的逻辑.即使知道确切的逻辑,实际上也不可能进行暴力攻击.增加盐的长度将进一步提高安全性.

这种方法的缺点:

由于在运行时推断出确切的逻辑,因此这种方法非常耗费CPU.盐的长度越长,这种方法就越耗费CPU.

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

该方法可以以各种方式实现,并且通过使用可变宽度盐和/或盐渍密码哈希可以使得更安全.

  • 使用您的方法,您只需在散列过程中添加一个秘密(应用盐的算法).这个秘密你可以添加更加容易添加一个**辣椒**盐,我试图在我的[教程](http://www.martinstoeckli.ch/hash/en/index.php)中指出这一点.像BCrypt这样的现代哈希函数会在每次迭代中使用原始盐自己应用盐,所以无论如何你都无法控制它. (8认同)
  • @PeterToTheThird-这将否定辣椒的优势。胡椒添加了服务器端的秘密,并且只有在秘密(与盐相反)的情况下才起作用。一种典型的攻击是SQL注入,当有人获得对数据库的访问权而不是对代码的访问权时,存储在数据库中的Pepper将变得毫无用处。大多数BCrypt实现都会自动将盐添加到生成的哈希值中,因此该值已经包含了盐,成本因子,算法和哈希。该字符串可以存储在长度为60个字符的单个字段中。 (2认同)
  • @martinstoeckli - 是的,实际的实现取决于您使用的哈希函数.显然,在实现身份验证逻辑时,需要考虑哈希函数的参数和输出.最终,胡椒只是你的散列函数中引入的另一个变量,它不会存储在与盐和散列相同的位置. (2认同)

And*_*ico 23

通常,它们被预先添加到哈希并存储在相同的字段中.

不需要单独存储它们 - 关键是对每个密码使用随机盐,这样就不能对整个密码哈希值使用单个彩虹表.对于随机盐,攻击者必须分别强制使用每个哈希(或计算所有可能盐的彩虹表 - 更多的工作).

如果您有一个更安全的存储位置,那么将哈希存储在那里是有意义的.

  • @mghaoui但是如果你想知道"密码",你仍然需要为每种盐构建一个彩虹表,除非一些盐是相同的. (9认同)
  • 但是,如果所有散列密码泄漏,包括匹配的盐,会发生什么?那不是那么不安全吗? (3认同)

DaN*_*eSh 5

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

\n\n
    \n
  1. 要访问存储在单独数据库中的盐,黑客需要破解两个不同的数据库才能访问盐和加盐密码。将它们存储在与密码相同的表中,甚至是同一数据库的另一个表中,意味着当黑客获得数据库的访问权限时,他们将能够访问盐和密码哈希。由于安全性包括使黑客入侵系统的过程过于昂贵或耗时,因此不值得,因此将黑客必须获得的访问量加倍应该会使系统更加安全。
  2. \n
  3. 易于使用是将盐与哈希密码保存在同一个数据库中的主要原因。\n 您不必确保两个数据库始终同时可用\n并且始终同步。如果\n每个用户都有一个随机盐,那么拥有盐的优势是微乎其微的,因为虽然它可能会使发现个人\xe2\x80\x99s\n密码变得更容易,但破解整个系统密码所需的力量\n很高。在这一级别的讨论中,这确实是我们的期望:保护密码。如果黑客获取了数据库的副本,\n您的应用程序数据就已经受到威胁。此时,问题是减轻用户\xe2\x80\x99\n由于共享密码的可能性而带来的风险。
  4. \n
  5. 维护两个独立的链接数据库的需求非常广泛。诚然,它增加了安全感,但它提供的唯一优点是它保护密码(单个数据元素)。如果数据库中的每个字段都被单独加密,并且使用相同的盐,那么将其与数据分开存储会更有意义,因为系统的基本安全性得到了增强。
  6. \n
\n