在为数据库存储散列密码时,我总是使用适当的每项salt字符串。对于我的需要,在DB中将盐存储在散列密码旁边总是很好。

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

从安全的角度来看,把盐存放在不同的地方值得吗?考虑一个web应用程序,其服务器代码和DB位于同一台机器上。如果salt存储在该机器上的平面文件中,那么如果数据库受到威胁,那么盐类文件也会受到威胁。

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


当前回答

之所以用盐腌是为了防止彩虹表附着。恶意用户以某种方式到达数据库并看到散列密码,获得最常见密码的表,找到它们的散列值并在表中查找密码。

所以当用户发送密码时,我们在密码中添加随机生成的salt。

 userPassword + salt

我们把这个传递给哈希算法。

 hash(userPassword+salt)

因为salt是随机生成的,所以userPassword+salt变成了一个随机值,绝对不是最常用的密码之一。因此恶意用户通过检查彩虹表就不会知道使用了什么密码。

现在salt值被放在哈希值之前,因为在用户登录时再次使用它来比较传递的凭据与保存的凭据。

 hash(userPassword+salt)=ashdjdaskhfjdkhfjdashadslkhfdsdh

这是这个密码如何存储在db: ashdjdaskhfjdkhfjdashadslkhfddhh .salt

现在,如果恶意用户看到这个,他可以找出密码,但这将花费大量的时间。因为每个密码将得到不同的盐。让我们恶意有表5000常用密码和他们的哈希。

重要的一点是,恶意用户不只有一个表。因为有太多不同的算法,所以恶意用户会对每个算法有5000个密码哈希值。

现在,对于每个密码,假设他从第一个用户的密码开始,他将把这个盐添加到5000个常用密码中,并为每个不同的算法创建一个新的彩虹表,以只找到一个密码。然后对于第二个用户的密码,他会看到不同的盐,他会计算新的彩虹表。它甚至不保证,用户的密码将在那些常用密码的列表。

其他回答

基于ASP的开发。NET MVC 4 Web应用程序的书由William Penberthy:

Getting access to the salts stored in a separate database requires hackers to hack two different databases to get access to the salt and the salted password. Storing them in the same table as the password, or even another table of the same database, would mean that when hackers gain access to the database, they will have access to both the salt and the password hash. Because security includes the process of making hacking into the system too expensive or time-consuming to be worth it, doubling the amount of access a hacker would have to gain should make the system more secure. Ease of use is the primary reason for keeping the salts in the same database as the hashed passwords. You would not have to ensure that two databases are always available at the same time, and always in sync. The advantage of having a salt is minimal if each user has a randomized salt because although it might make discovery of an individual’s password easier, the amount of force necessary to crack the passwords of the system overall will be high. In this level of discussion, that is really what the expectation is: to protect the passwords. If the hackers have acquired a copy of the database, your application data is already compromised. At this point, the issue is to mitigate users’ risks because of the potential of shared passwords. The requirement of maintaining two separate linked, databases is extensive. Granted, it adds the perception of security, but the only advantage that it gives is that it protects a password, a single element of data. If every field in the database were individually encrypted, and this same salt was used for that, it would make more sense to store it separately from the data because the basic security of your system is enhanced.

彩虹表的重点是,它们是预先创建的,并大量分布,以节省其他人的计算时间——实时生成彩虹表所需的时间与直接破解密码+salt组合所需的时间一样长(因为在生成彩虹表时,实际上所做的是预先运行计算以进行野蛮强制哈希),因此,通过知道盐就可以“生成彩虹表”的说法是虚假的。

在单独的文件中存储salt没有实际意义,只要它们是基于每个用户的——salt的意义只是为了使一个彩虹表不能破坏数据库中的每个密码。

之所以用盐腌是为了防止彩虹表附着。恶意用户以某种方式到达数据库并看到散列密码,获得最常见密码的表,找到它们的散列值并在表中查找密码。

所以当用户发送密码时,我们在密码中添加随机生成的salt。

 userPassword + salt

我们把这个传递给哈希算法。

 hash(userPassword+salt)

因为salt是随机生成的,所以userPassword+salt变成了一个随机值,绝对不是最常用的密码之一。因此恶意用户通过检查彩虹表就不会知道使用了什么密码。

现在salt值被放在哈希值之前,因为在用户登录时再次使用它来比较传递的凭据与保存的凭据。

 hash(userPassword+salt)=ashdjdaskhfjdkhfjdashadslkhfdsdh

这是这个密码如何存储在db: ashdjdaskhfjdkhfjdashadslkhfddhh .salt

现在,如果恶意用户看到这个,他可以找出密码,但这将花费大量的时间。因为每个密码将得到不同的盐。让我们恶意有表5000常用密码和他们的哈希。

重要的一点是,恶意用户不只有一个表。因为有太多不同的算法,所以恶意用户会对每个算法有5000个密码哈希值。

现在,对于每个密码,假设他从第一个用户的密码开始,他将把这个盐添加到5000个常用密码中,并为每个不同的算法创建一个新的彩虹表,以只找到一个密码。然后对于第二个用户的密码,他会看到不同的盐,他会计算新的彩虹表。它甚至不保证,用户的密码将在那些常用密码的列表。

The point of a salt is to render all rainbow tables useless and require a new set of them to be made. It takes just as long to guess a string as to make a rainbow table. For example the SHA-256 hash of "password" is 5e88 4898 da28 0471 51d0 e56f 8dc6 2927 7360 3d0d 6aab bdd6 2a11 ef72 1d15 42d8. After a salt is added, such as "badpassword" the new string to be hashed is "passwordbadpassword" which, due to the avalanche effect, dramatically changes the output, to 457b f8b5 37f1 802e f9c8 2e46 b8d3 f8b5 721b 7cbb d485 f0bb e523 bfbe 73e6 58d6.

通常情况下,盐只存储在与密码相同的数据库中,这也是因为如果一个数据库被黑客入侵,另一个数据库也很可能会被黑客入侵。

如果您使用的库(或自己创建的库)使用固定大小的字符串作为salt,那么您可以将salt和散列密码存储在同一个字段中。然后拆分存储的值以检索盐和散列密码以验证输入。

使用10个字符的salt和固定的40个字符的散列大小,它看起来像这样:

salt = "california"
passwd = "wp8tJ4Pr"

stored_passwd = salt + hash(passwd + salt)

salt = substr(stored_passwd, 0, 10)
hashed_passwd = substr(stored_passwd, 10, 40)

if hash(user_input + salt) == hashed_passwd:
    print "password is verified"

由于salt的全部目的是防止使用预先计算的表(例如彩虹表)进行密码攻击,因此将salt与散列密码一起存储实际上是无害的。