在散列数据库存储密码时,我总是使用正确的每个条目的盐字符串。根据我的需要,将盐存储在哈希密码旁边的数据库中一直运行正常。
但是,有些人建议将盐与数据库分开存储。他们的论点是,如果数据库受到攻击,攻击者仍然可以构建一个彩虹表,将一个特定的盐字符串考虑在内,以便一次破解一个帐户。如果此帐户具有管理员权限,那么他甚至可能不需要破解任何其他帐户。
从安全角度来看,将盐储存在不同的地方是否值得?考虑在同一台机器上具有服务器代码和DB的Web应用程序。如果盐存储在该机器上的平面文件中,则很可能如果数据库受到损害,则salt文件也是如此。
有什么建议的解决方案吗?
彩虹表的重点在于它们是预先创建的,并且是为了节省其他人的计算时间而集中分配 - 生成彩虹表需要同样长的时间,因为它只是直接破解密码+盐组合(因为实际上,在生成彩虹表时正在执行的操作是预先运行用于强制执行散列的计算,因此通过了解某人可能“生成彩虹表”的参数是虚假的。
将盐存储在单独的文件中没有任何意义,只要它们是基于每个用户的 - 盐的目的只是为了使一个彩虹表不能破坏数据库中的每个密码。
我会对此略有不同。
我总是使用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成本。这可能会对合法请求产生反效果,但会增加对攻击者的安全性。
该方法可以以各种方式实现,并且可以通过使用可变宽度盐和/或盐渍密码哈希来使其更加安全。
通常,它们被预先添加到哈希并存储在相同的字段中。
不需要单独存储它们 - 关键是对每个密码使用随机盐,这样就不能对整个密码哈希集使用单个彩虹表。对于随机盐,攻击者必须分别强制使用每个哈希(或计算所有可能盐的彩虹表 - 更多的工作)。
如果您有一个更安全的存储位置,那么将哈希存储在那里是有意义的。
基于William Penberthy开发的ASP.NET MVC 4 Web Applications一书:
盐的要点是使所有彩虹表无用,并且需要制作一组新的彩虹表。猜测一个字符串就像生成彩虹表一样长。例如,“密码”的SHA-256哈希是5e88 4898 da28 0471 51d0 e56f 8dc6 2927 7360 3d0d 6aab bdd6 2a11 ef72 1d15 42d8
。添加一个盐后,例如“badpassword”,要散列的新字符串是“passwordbadpassword”,由于雪崩效应,它会显着改变输出到457b f8b5 37f1 802e f9c8 2e46 b8d3 f8b5 721b 7cbb d485 f0bb e523 bfbe 73e6 58d6
。
通常,salt只是与密码存储在同一个数据库中,因为如果一个数据库被黑客攻击,那么另一个数据库也可能存在。