密码哈希还有更多内容吗?

信息安全 密码 哈希 密码管理
2021-09-07 17:01:11

你有一个纯文本密码和盐。假定纯文本密码是安全随机的,只有用户知道,salt 不是秘密,不一定是唯一的,而是与生成的哈希一起存储。单独调用以下内容并存储结果是否足够?

password_hash = Hash ( password || salt )

Hash目前被认为是“安全的”散列函数(SHA512,BCrypt等)

人们做得更多吗?如:

  1. 多次迭代:运行多次迭代有巨大的好处吗?如果是,这纯粹是成本优势吗?迭代次数是动态的还是静态的?多少次迭代?
  2. 多个散列函数:使用多个散列函数会有优势吗?例如,三轮,sha512 -> BCrypt -> sha512
  3. 盐混合人们是在密码中嵌套盐还是在结束/开始时连接?例如,将普通密码分成四个部分,盐分成三个部分,并在每个密码部分之间加入每个盐部分。
  4. 独特的方案password_hash:为每个不同的项目编写一个独特的函数会有什么好处吗?例如,项目 A 的password_hash函数运行 SHA512 20 次,项目 B 的password_hash函数运行 BCrypt 10 次,在每次迭代时在密码的不同端应用盐。
  5. “黑魔法”:将自己的“黑魔法”添加到散列函数中是否有好处?例如,在每次迭代之前,您应用一些基本的按位操作或基于简单算法混合字符。
  6. 混淆:对生成的哈希进行编码或混淆以隐藏其原始哈希函数会产生巨大的影响吗?例如在哈希中添加或删除 N 个字符以隐藏其原始长度。

这些行动真的有必要吗,它们会产生巨大的影响(如果是的话,以什么方式),人们在实践中是否使用了像上面提到的任何额外的行动?


我的想法:

最后,无论使用密码做什么都不会阻止某人使用愚蠢的密码(如“密码”或“123”);必须采取与该问题无关的其他方法。但是有可能通过多次迭代使计算成本更高,从而减慢速度或使暴力攻击变得不可行。

上面提到的大多数操作将对已经获得用户列表访问权限的人产生很大的影响——电子邮件、密码哈希和盐,并希望恢复纯密码。它不会阻止一个坚定的黑客,但会阻止并希望减慢他们的速度,让您有足够的时间进行适当的更改或采取措施来保护被入侵的帐户。

然而,这在很大程度上违背了“攻击者无所不知”的想法。假设攻击者可以看到密码散列是如何生成的(源代码和模式),那么差别不大。这与将数据库表的列名从更改为一样password重要ahoy

无论如何,只是使用password_hash = Hash ( password || salt )似乎太简单了。人们肯定做得更多吗?

2个回答
  1. 多次迭代——这有帮助。它被称为密钥强化,它提高了计算复杂度。例如,如果您将密钥加强 1000 倍,则攻击者可以在相同的 GPU/CPU 时间内尝试减少 1000 个可能的密码。

  2. 多个散列函数——理论上这有帮助,但实际上并没有。这种情况是,如果使用的一个哈希函数以某种方式被破坏(例如,您可以通过尝试显着少于 2256 个密码来反转任何 256 位哈希,或者可以在尝试常见密码时显着简化暴力破解过程),但另一个哈希链中使用的函数没有被破坏。例如,您的攻击者已经破坏了迭代的 sha512,因此可以快速想出一个适用于 sha512 密钥强化 N 次的密码,但不是sha512(salt||bcrypt(salt||sha512(salt||pw))). 然而,在我看来,对于现代密码散列函数和典型的攻击者来说,这是一个相当不可能的攻击场景——有很多较低的果实,不需要攻击者在计算机科学方面取得根本性的进步。NSA 或严肃的学术计算机科学家可能会想出聪明的方法来破解散列算法,但不是普通的恶意攻击者。即使在被破坏并且通常应该避免的哈希算法(例如,MD5 和 SHA-1)中,它们通常也只会被碰撞攻击破坏(找到一对不同的字符串s1s2hash(s1) == hash(s2)比预期的要快得多),而不是原像攻击(给定一个哈希,h找到一个s满足hash(s)=h),这是对密码哈希的相关攻击。

  3. 盐混合- 这是一个实现细节,这样做不会给攻击者增加复杂性。(不存在用于复杂键增强加盐哈希的预计算彩虹表。)

  4. 独特的方案- 又是一个实现细节,并且没有增加安全性。也不要多次运行 bcrypt;这很愚蠢。Bcrypt 已经经过密钥强化。例如,如果您使用成本为 16 的 bcrypt 进行散列,这意味着密钥经过 2^16 ~ 65536 轮,因此如果您想要更强的散列,只需增加成本(每增加 1;意味着 bcrypt 将慢两倍)。

  5. 黑魔法- 作为程序员,我不建议这样做;因为黑魔法对你和你的团队来说是一场维护噩梦,而且对于攻击者来说也不太重要。决定采用新技术,因此您必须在新平台上用新语言重写非标准哈希例程,除非它的文档非常完善,否则您可能会以稍微不同的方式破坏系统。如果它有据可查,攻击者可能会窃取您的源代码;查看该功能对密码的作用,然后可以将其用于暴力破解。如果他们设法窃取了您的哈希,他们可能至少有一个帐户,他们知道密码并窃取了哈希,因此可以尝试对其进行逆向工程(即使他们没有获得源代码)。这就像在您自己的服务器上混淆您的源代码。

  6. 混淆- 不要这样做。见黑魔法。或者只是按照 Kerckhoff 的原则,即香农的格言:即使敌人完全了解系统,也要让系统变得强大。混淆/黑魔法可以通过一点分析来克服,并提供一些安全性(深度防御),但不多。然而,一个具有高熵初始密码短语/密码的强密钥强化密码散列可以很容易地构建为具有计算复杂性,在没有重大进展的情况下,使用宇宙中的所有计算机进行数千年的攻击是完全不可行的。科学(例如,量子计算机或破坏散列函数)。


最后,无论使用密码做什么,它都不会阻止某人使用愚蠢的密码(如“密码”或“123”)

事实上,我不同意这一点。根据受众的俘虏程度(例如,工作人员必须将其用于他们的工作),您可以在设置新密码时使简单密码无效(例如,检查泄露的大约一百万个常用密码的密码列表并使所有匹配项无效,或未通过其他最低标准:必须是 8+ 个字符且带有大写/小写/数字/符号或 20+ 个字符的密码)。基本上,如果它是一个安全的应用程序,如果帐户被泄露,会对您的最终产生严重影响,那么这样的事情是个好主意。

如果您过于严格,授权用户将获得负面的用户体验(因此,如果您是一个简单的网络应用程序或在线零售商,需要大量用户并且并不真正担心帐户被弱密码窃取,您可能不想实施严格的密码规则;但零售商应采取措施,例如在电子邮件/收货地址更改后要求重新输入信用卡信息,并应在所有购买后发送收据电子邮件)。此外,请注意,用户在公共工作环境中在显示器上发布密码最终会削弱安全性;因此,请明确说明用户帐户遭到破坏会产生后果。

我将标签添加到哈希中,例如 ip 地址:

10.10.10.10:bDcxWMe1v81o97HbRrVF1:1234

此外,在数据库中,您可以添加时间戳:

bDcxWMe1v81o97HbRrVF1:Fri Aug  3 12:42:48 UTC 2012

另外,有时我会添加创建它的函数的版本和名称:

bDcxWMe1v81o97HbRrVF1:bcrypt1.0

结果,您有一个带有附加安全信息的哈希,然后您使用非对称公钥加密,如 RSA:

例如:

RSA(private, 10.10.10.10:bDcxWMe1v81o97HbRrVF1:1234:Fri Aug  3 12:42:48 UTC 2012:bcrypt1.0)

结果被加密:

7UnUO98lbDcxWMe1v817UnUO98lbDcxWMe1v817UnUO98lbDcxWMe1v817UnUO98lbDcxWMe1v817UnUO98lbDcxWMe1v81

当您提交密码时,哈希值与其他纯文本数据(例如从连接获得的 ip 地址或 cookie-id)一起正常计算,结果使用 RSA 加密,并验证用户是否可以获得会话,例如,如果值匹配。服务器上的数据是不可解密的,所以不能用普通的hash值破解,因为是用RSA加密的,不能像hash值那样解密RSA那么简单,而且额外的明文数据也是隐藏的,可以如果需要进行反转,例如在另一个系统上执行连接验证,因此哈希值绑定到负载均衡器之间的连接,例如负载均衡器解密请求而不计算复杂哈希但执行 RSA 解密和它验证的 Web通过进行完整的哈希计算得到密码。

这个具体的使用场景可能会很困难,但也许它可以使用密码,我会考虑这个他。