加盐密码:最佳实践? [关闭]
Posted
技术标签:
【中文标题】加盐密码:最佳实践? [关闭]【英文标题】:Salting Your Password: Best Practices? [closed] 【发布时间】:2010-10-15 01:33:38 【问题描述】:我一直很好奇...为哈希加密密码时哪个更好:前缀还是后缀?为什么?还是只要你加盐就可以了?
解释一下:我们现在都(希望)知道我们应该salt 一个密码,然后我们将其哈希存储在数据库中[编辑:所以你可以避免像what happened to Jeff Atwood recently 这样的事情]。通常这是通过在将盐传递给散列算法之前将盐与密码连接起来来完成的。但例子各不相同......一些例子在密码前加上盐。一些示例在密码之后添加盐。我什至见过一些人试图把盐放在中间。
那么哪种方法更好,为什么?有没有一种方法可以减少哈希冲突的机会?我的谷歌搜索还没有对这个主题进行像样的分析。
编辑:很好的答案伙计们!对不起,我只能选择一个答案。 :)
【问题讨论】:
另见:***.com/questions/1645161/… 最佳实践是使用加密函数为您进行加盐处理,使用 PBKDF2(标准)、bcrypt 甚至 scrypt。感谢斯蒂芬指出这一点。 几乎所有标准密码散列结构都负责组合盐和密码,因此您不必担心这一点。如果您不使用标准密码哈希,请迁移到一个。 @Omu 不好的推荐。 1) SHA-1 的单次迭代太快了,你至少应该使用 10000,即使这样也很弱。 2)默认盐太小。最少 8 个字节,建议使用 16 个。 相关:Does prepending a salt to the password instead of inserting it in the middle decrease security?,Salt placement prior to one-way hash,How to securely hash passwords? 【参考方案1】:真正的答案,似乎没有人提到,是both are wrong。如果您正在实施自己的加密,无论您认为自己在做什么微不足道的部分,您都会犯错误。
HMAC 是一种更好的方法,但即便如此,即使您使用的是 SHA-1 之类的东西,您也已经选择了一种不适合密码散列的算法,因为它的设计是为了速度。使用bcrypt 或scrypt 之类的东西,完全摆脱你的困扰。
哦,甚至不要考虑将生成的哈希值与您的编程语言或数据库字符串比较实用程序进行比较。如果字符不同,则将逐个字符比较并短路为false
。所以现在攻击者可以使用统计方法来尝试计算哈希是什么,一次一个字符。
【讨论】:
关于最后一段:攻击者如何获得有关比较失败的确切字符数的任何信息?这毫无意义.. 你说的既对又错。 Timing attacks 是真实的,并且已被反复证明即使在可变延迟网络连接上也能以惊人的准确性来确定比较失败的确切位置。也就是说,定时攻击实际上并不适用于常见的密码哈希,因为在计算上要找到只改变输出的一小部分的输入是不可行的。【参考方案2】:前缀或后缀无关紧要,只是为密码添加一些熵和长度。
你应该考虑这三件事:
-
您存储的每个密码的盐值都必须不同。 (这是一个很常见的误解。)
使用加密安全的随机数生成器。
选择足够长的盐。想想生日问题。
有一个很好的answer by Dave Sherohman 来回答另一个问题,为什么您应该使用随机生成的盐而不是用户名(或其他个人数据)。如果你遵循这些建议,那么你把盐放在哪里都没关系。
【讨论】:
我添加了一个旧问题的链接,请阅读这些答案。基本上,通过不为每个密码使用不同的随机盐,您将承担不必要的安全风险,这可能在未来成为一个真正的问题。 站点范围的随机盐是不好的,因为攻击者可以预先计算彩虹表并获取您的整个用户数据库。如果您不理解这一点,请不要编写登录/安全系统:) - 您需要每个用户的盐。 是的,每个用户的盐。理想情况下,存储每个用户的迭代(因此您可以随着时间的推移增加使用的迭代次数)。任何体面的框架都会有这个内置的。 (.NET 有 PasswordDeriveBytes 可以为你处理一切。) 如果您正在设计任何类型的安全系统,那么不使用每个用户的 salt 就是脑死。 你的网站可能不是很有趣,但考虑到用户在多个网站上使用相同的密码......试图保持数据库安全往往会失败:) 当然盐可以防止字典攻击,正是通过使它们变得更慢。在密码中使用盐远早于彩虹表。专门添加了盐来减缓字典攻击,防止攻击者对密码进行一次哈希处理,然后将其与所有用户进行比较。【参考方案3】:首先,“彩虹表”一词一直被滥用。 “彩虹”表只是一种特定的类型查找表,它允许对键进行特定类型的数据压缩。通过用计算换取空间,可以将占用 1000 TB 的查找表压缩一千倍,以便将其存储在更小的驱动器上。
您应该担心哈希到密码查找表、彩虹或其他方式。
@onebyone.livejournal.com:
攻击者的“彩虹表”不是由字典单词的哈希组成,而是在完成哈希计算之前的哈希计算状态。
然后,使用后缀 salt 暴力破解密码文件条目可能比前缀 salt 更便宜:依次为每个字典单词加载状态,将 salt 字节添加到哈希中,然后完成它。使用前缀盐,每个字典单词的计算之间没有任何共同点。
对于线性扫描输入字符串的简单哈希函数,例如简单的线性同余生成器,这是一种实用的攻击。但是加密安全的散列函数被故意设计为多轮,每轮都使用输入字符串的所有位,因此在添加盐之前计算内部状态就在没有意义第一轮之后。例如,SHA-1 有 80 轮。
此外,像 PBKDF 这样的密码哈希算法会多次组合它们的哈希函数(建议迭代 PBKDF-2 至少 1000 次,每次迭代应用 SHA-1 两次)使得这种攻击更加不切实际。
【讨论】:
你应该仔细检查回合的描述。这些轮次是基于每个块的,而不是整个消息。 (否则,散列流数据将需要一次又一次地倒带。)但是使用迭代确实可以防止出现大家提到的问题。【参考方案4】:如果使用加密安全哈希,则无论您是前置还是后缀都无关紧要;散列的一点是源数据中的单个位更改(无论在哪里)都应该产生不同的散列。
重要的是,但是,使用长盐,使用适当的加密 PRNG 生成它们,并具有每个用户的盐。在数据库中存储每个用户的盐不是安全问题,使用站点范围的哈希是。
【讨论】:
错误答案:攻击者可以预先计算许多常用密码的 MD(pass),然后非常便宜地计算 MD(pass+salt),因为消息摘要以增量方式工作以支持流式传输。 【参考方案5】:在密码中插入任意数量的盐是最不期望的情况,因此在社交上最“安全”,但在一般情况下,只要您使用长而唯一的,它真的不是很重要-盐的每个密码字符串。
【讨论】:
【参考方案6】:我认为这都是语义。将其放在之前或之后并不重要,除非针对的是非常具体的威胁模型。
它的存在应该可以打败彩虹桌。
我提到的威胁模型是攻击者可以在密码中附加/预先设置彩虹表的场景。 (比如美国国家安全局)你猜他们要么附加了它,要么附加了它,但不是两者兼而有之。这很愚蠢,而且是一个糟糕的猜测。
最好假设他们有能力存储这些彩虹表,但不能存储密码中间散布着奇怪盐的表。在那种狭义的情况下,我猜想穿插是最好的。
就像我说的。是语义。为每个密码选择一个不同的盐,一个长盐,并在其中包含奇数字符,如符号和 ASCII 码:©¤¡
【讨论】:
@onebyone,该死的!他发现了我的“密码盐”盐! @Samuel:我不了解你们,但我们使用 '12345' 作为我们的盐。 :) @onebyone 有效。我的真正意思是“常见”为“字符集 Y 中长度为 X 的所有盐”,其中 X、Y 是合理的;说 20 个字符和字母数字大写/小写。可以扩展为长度为 Z(比如 160)的所有十六进制字符串,因为我认为散列哈希的彩虹表会很有用.. @Randolpho:嘿,这也是我的盐!几率是多少? 并确保盐是不可预测/随机的:***.com/questions/1645161/…【参考方案7】:BCrypt hash 如果平台有提供者。我喜欢你不用担心产生盐的方式,如果你愿意,你可以让它们变得更强壮。
【讨论】:
据我所知,BCrypt Hash 需要加盐,就像任何其他散列方案一样。【参考方案8】:应该没什么区别。无论你把盐放在哪里,哈希都不会更容易被猜到。由于故意非线性,哈希冲突既罕见又不可预测。如果它对安全性产生影响,则表明散列存在问题,而不是加盐问题。
【讨论】:
哈希冲突取决于哈希的大小。由于生日问题,很可能发生碰撞。 仅当您截断结果时。无论如何,我仍然坚持盐在哪里不会有什么不同,因为哈希的目的是使输入和输出之间的关系不包含任何模式。以上是关于加盐密码:最佳实践? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章