我可以通过加盐现有的 MD5 散列并使用 Scrypt 或 PBKDF2 HMACSHA256 散列结果来提高 MD5 散列密码的安全性吗?

Posted

技术标签:

【中文标题】我可以通过加盐现有的 MD5 散列并使用 Scrypt 或 PBKDF2 HMACSHA256 散列结果来提高 MD5 散列密码的安全性吗?【英文标题】:Can I improve the security of MD5 hashed passwords by salting the existing MD5 hash and hash the result using Scrypt or PBKDF2 HMACSHA256? 【发布时间】:2013-03-24 08:32:20 【问题描述】:

我有一个使用 MD5 加盐和散列的旧密码数据库。我想更新系统,让数据更安全。

第一个选项是当用户登录并在一段时间后停用旧用户时将用户转换为新的哈希方案(Salt + Scrypt 或 PBKDF2 HMACSHA256),因此他们必须使用会自动更新的密码恢复功能他们的哈希。

另一个可以让我立即升级每个人的选项是采用现有的 MD5 哈希值,为每个哈希值添加一个新的随机盐值,然后使用新的哈希方案(Salt + Scrypt 或 PBKDF2 HMACSHA256)对结果进行哈希处理,然后将该值存储到数据库中并删除旧值。

然后当用户登录时,我必须先应用旧方法,然后再应用新方法。我更喜欢第二个选项,因为它允许我尽早从数据库中删除所有旧的不安全哈希。

对现有哈希进行加盐和重新哈希是否安全? MD5 是否如此损坏,以至于我可以运行一个脚本来对密码进行去散列并使用新方案对其进行重新散列?

或者最好的解决方案是结合使用这两个选项?这样我就不必将现有的 MD5 哈希值保留在数据库中,并且可以在一段时间内将用户迁移到新系统?

【问题讨论】:

Use SHA-512 and salt to hash an MD5 hashed password? 的可能副本。 (不完全相同,但大多数答案听起来也适用于此。) 刚刚发现一个...最重要的方面是尽快删除/保护当前数据。 【参考方案1】:

这实际上是您的一个非常巧妙的想法。通常我会:

等到用户返回 意识到他们存储的密码需要更新 现在我在内存中有他们的(已知有效)密码:用新算法重新哈希它 在数据库中存储新的哈希

只使用 MD5 的缺点是它很容易被暴力破解。通过在应用真正的 scrypt/Argon2 之前(暂时)将 MD5 结果作为中间步骤,您可以阻止暴力破解尝试。

“真实”密码哈希之前使用快速哈希算法作为预处理步骤并非闻所未闻 - 甚至可能很有用。

BCrypt 的已知密码长度限制为 72 个字节(71 个 utf-8 字符,然后是一个空终止符)。 Dropbox applies SHA2-512 to the incoming plaintext password 在通过 bcrypt 运行之前。通过首先通过哈希运行长密码,他们克服了 71 个字符的限制。 这不仅克服了密码长度限制(避免必须截断或限制密码大小),而且在someone supplies an extraordinarily long password 时可以防止拒绝服务攻击。 BCrypt 和 Scrypt 容易受到密码较长的攻击(我不知道 Argon2)。

因此,使用预散列(虽然不一定是 MD5)是有好处的。

我不知道您当前如何存储 MD5 哈希值。 MD5 是 128 位的。假设你将它存储在 Base64 中,你可以很容易地识别它:

MD5nMKuihunqT2jm0b8EBnEgQ==

期望的最终目标类似于 scrypt:

MD5nMKuihunqT2jm0b8EBnEgQ== 加密$s0$e0801$epIxT/h6HbbwHaehFnh/bw==$7H0vsXlY8UxxyW/BWx/9GuY7jEvGjT71GFd6O4SZND0=

因此,当根据保存的哈希验证凭据时,您可以确定它是哪个哈希并使用适当的算法。您的中间步骤(增加了计算复杂性)正在定义您自己的格式:

MD5 + 加密

类似:

MD5nMKuihunqT2jm0b8EBnEgQ== MD5 + scrypt$md5s0$e0801$eX8cPtmLjKSrZBJszHIuZA==$vapd0u4tYVdOXOlcIkFmrOEIr1Ml2Ue1l2+FVOJgbcI= 加密$s0$e0801$epIxT/h6HbbwHaehFnh/bw==$7H0vsXlY8UxxyW/BWx/9GuY7jEvGjT71GFd6O4SZND0=

现在您可以根据保存的哈希识别正在使用的算法,并且可以分段升级密码。

【讨论】:

老问题了!我最终只是等待用户升级,计划最终锁定旧帐户并让他们恢复密码,这将使他们达到最新标准。此外,我在密码系统中添加了一个版本,以便在每个用户可用时轻松升级到新算法,并且系统会在他们登录时自动将它们升级到最新版本。【参考方案2】:

MD5 并没有破坏到您可以轻松地对所有密码进行去散列处理,但是假设密码的质量不太好,那么您可能会暴力破解它们并将它们转换为新的、更安全的格式。 MD5 的破坏性源于它相对较小的长度(更多的碰撞表面)和计算简单的计算(意味着蛮力攻击比具有较大运行时复杂度的算法(如 SHA2)更可行)

如果我是你,我会使用你列出的两种方法(因为正如你所提到的,如果你的数据库被黑客入侵,快速移动密码很重要)。首先,我将暴力破解所有暴力破解 MD5 密码并将它们转换为新格式。我过去曾这样做过,到目前为止,最好的结果是使用HashCat(最好是 Cuda 或 OCL 风格,因为它们使用 GPU 并且速度快 200 倍)。如果 Hashcat 太难(学习曲线可能很陡峭),那么试试John the Ripper。它比 HashCat 慢很多,但更容易使用。

对于您无法破解的密码,请使用户的帐户过期并让他们重置密码。或者为了对您的用户更好,只需在他们下次登录时通过发送两个哈希值将数据库中的密码更新为新格式。如果 MD5 检出,则将其销毁并替换为新格式。这些只是一些想法。

编辑:

忘了提一下,如果您只想将 MD5 密码散列成新的格式,这在安全方面会很好,尽管它会为您的代码增加另一层复杂性,并且存在复杂性的地方有实现的空间缺陷。只是想一想。

【讨论】:

“MD5 的破损是由于它的长度相对较小(碰撞面更大)而且计算简单”——MD5 的真正问题,非常严重,是它不耐碰撞。使用 Klima 的方法,您可以在使用 CPU 的低端系统上大约一分钟内找到与给定键的冲突——无需大量 GPU 设置。这不会显示原始密码,但它会提供一个与通过哈希质询一样好的“密码”。

以上是关于我可以通过加盐现有的 MD5 散列并使用 Scrypt 或 PBKDF2 HMACSHA256 散列结果来提高 MD5 散列密码的安全性吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何迁移密码哈希?

MD5加密加盐

MD5加密加盐

使用 MD5 或 sha-256 C# 散列密码

使用 SHA-512 和 salt 来散列 MD5 散列密码?

加盐哈希以验证明文(不是密码)