据我了解,生成盐的最佳做法是使用源代码中存储的一些神秘公式(甚至魔术常量)。
我正在开发一个我们计划作为开源发布的项目,但问题是源代码是生成盐的秘密公式,因此能够在我们的网站上运行彩虹表攻击。
我认为很多人在我面前都考虑过这个问题,我想知道最佳做法是什么。在我看来,如果代码是开源的话,根本就没有盐,因为盐很容易被逆向工程化。
思想?
答案 0 :(得分:225)
答案 1 :(得分:18)
真正的盐只需要每个条目都是唯一的。即使攻击者可以计算盐的含量,也会使彩虹表极难创建。这是因为在哈希值被哈希之前将盐添加到密码中,因此它有效地增加了彩虹表必须包含的条目总数,以获得密码字段的所有可能值的列表。
答案 2 :(得分:7)
由于Unix变得流行,存储密码的正确方法是附加一个随机值(盐)并散列它。将盐分保存在以后可以到达的地方,但是你希望那些坏人不会得到它。
这有一些好的效果。首先,坏人不能只列出预期的密码,如“Password1”,将它们哈希到彩虹表中,然后通过密码文件查找匹配项。如果你有一个很好的双字节盐,他们必须为每个预期的密码生成65,536个值,这使得彩虹表不那么实用。其次,如果你能从查看密码文件的坏人那里得到盐,你就会更难以计算出可能的值。第三,你已经让坏人无法确定某个人是否在不同的网站上使用相同的密码。
为此,您将生成随机盐。这应该以均匀的概率生成所需范围内的每个数字。这并不困难;一个简单的线性同余随机数发生器可以很好地完成。
如果你有复杂的计算来制作盐,那你做错了。如果你根据密码计算它,那你就错了。在这种情况下,你所做的只是使散列变得复杂,而不是在功能上添加任何盐。
没有任何善于安全的人会依赖于隐藏算法。现代密码学基于已经过广泛测试的算法,并且为了进行广泛测试,它们必须是众所周知的。一般来说,人们发现使用标准算法比使用自己的算法更安全,并希望它是好的。如果代码是开源代码并不重要,那么坏人通常仍然可以分析程序的功能。
答案 3 :(得分:1)
您可以在运行时为每条记录生成随机盐。例如,假设您将散列的用户密码存储在数据库中。您可以在运行时生成一个8个字符的随机字符串,包含大写和小写的字母数字字符,并将其添加到密码,哈希那个字符串,并将其存储在数据库中。由于有62种 8 可能的盐,因此产生彩虹表(对于每种可能的盐)将非常昂贵;由于你为每个密码记录使用了一个独特的盐,即使攻击者生成了几个匹配的彩虹表,他仍然无法破解每个密码。
您可以根据安全需要更改salt生成的参数;例如,你可以使用更长的盐,或者你可以生成一个也包含标点符号的随机字符串,以增加可能的盐的数量。
答案 4 :(得分:0)
使用随机函数生成器生成salt,并将其存储在数据库中,每行生成一个salt,并将其存储在数据库中。
我喜欢在django-registration中生成盐的方式。参考:http://bitbucket.org/ubernostrum/django-registration/src/tip/registration/models.py#cl-85
salt = sha_constructor(str(random.random())).hexdigest()[:5]
activation_key = sha_constructor(salt+user.username).hexdigest()
return self.create(user=user,
activation_key=activation_key)
他使用随机数生成的sha和用户名组合生成哈希。
Sha
本身因强壮而牢不可破。添加多个维度以生成盐本身,具有随机数,sha和用户特定组件,您具有牢不可破的安全性!
答案 5 :(得分:0)
对于加密数据并在远程服务器上发送数据的桌面应用程序,您如何考虑每次使用不同的盐?
将PKCS#5与用户密码一起使用时,需要使用salt来生成加密密钥,以加密数据。我知道在桌面应用程序中保持盐硬编码(混淆)并不是一个好主意。
如果远程服务器必须永远不知道用户的密码,是否可以每次使用不同的盐?如果用户在另一台计算机上使用桌面应用程序,如果他没有密钥(在软件中没有硬编码),它将如何解密远程服务器上的数据?