我能通过向现有的MD5哈希值添加盐并使用Scrypt或PBKDF2 HMACSHA256再次哈希结果来提高MD5哈希密码的安全性吗?

7
我有一个遗留密码数据库,使用MD5进行盐值加密。我希望更新系统以提高数据安全性。
第一种选择是在用户登录时过渡到新的哈希方案(Salt + Scrypt或PBKDF2 HMACSHA256),并在一定时间内停用旧用户,以便他们必须使用密码恢复功能自动更新其哈希。
另一种选项是让我立即升级所有人,即对现有的MD5哈希添加新的随机盐值,然后使用新的哈希方案(Salt + Scrypt或PBKDF2 HMACSHA256)对结果进行哈希,并将该值存储到数据库中并删除旧值。
然后当用户登录时,我需要应用旧方法和新方法。我更喜欢第二种选项,因为它可以让我尽快从数据库中删除所有旧的不安全哈希。
重新盐化和重新哈希现有哈希值是否安全? MD5是否如此破解,以至于我可以运行脚本来解密密码并使用新方案重新哈希?
或者也许最好的解决方案是两种选择的组合?这样我就不必在数据库中保留现有的MD5哈希,同时可以将用户迁移到新系统一段时间?

可能是重复的问题:使用SHA-512和盐来哈希MD5哈希密码?。(虽然不完全相同,但大多数答案似乎也适用于这里。) - Oliver Charlesworth
刚刚发现了一个问题...最重要的方面是尽快删除/保护当前数据。 - jpshook
2个回答

7

MD5并非如此破解,以至于你可以轻松地反向哈希所有密码,但是假设密码的质量不太好,那么您可能可以暴力破解它们并将它们转换为新的、更安全的格式。MD5的破碎性源于其相对较小的长度(更多冲突表面)和其计算上的简单性(这意味着暴力攻击比具有更大运行时复杂度的算法(如SHA2)更可行)。

如果我是你,我会执行你列出的两种方法(因为正如你所提到的,快速移动密码非常重要,以防您的数据库被黑客攻击)。首先,我会暴力破解所有可暴力破解的MD5密码,并将其转换为新格式。 我过去做过这件事,迄今为止最好的结果是使用HashCat(最好使用Cuda或OCL版本,因为它们使用GPU,速度快200倍)。 如果Hashcat太难了(学习曲线可能很陡峭),那就试试John the Ripper。 它比HashCat慢得多,但使用起来容易得多。
对于你无法破解的密码,可以让用户的账户过期并让他们重置密码。或者,为了更友好地对待用户,只需通过发送两个哈希值,在下次用户登录时将密码更新到数据库中的新格式。如果MD5检查通过,则销毁并替换为新格式。这些只是一些想法。
编辑:
忘记提到,如果您只想将MD5密码散列成新格式,那么从安全角度来看也完全可以,尽管这会给您的代码增加另一个复杂层面,而在复杂性存在的地方就有实现缺陷的空间。这只是需要思考的一些事情。

MD5的破碎性源于其相对较小的长度(更多的碰撞表面)和计算上的简单。而MD5真正的问题在于它不具备碰撞抵抗能力。使用Klima的方法,您可以在低端系统上的CPU上在约一分钟内找到给定密钥的碰撞,无需大规模GPU设置。这并不会揭示原始密码,但它提供了一个“密码”,它与原密码一样好,因为它通过了哈希挑战。 - Damon

2

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

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

只使用MD5的缺点是易于暴力破解。通过(临时地)将MD5结果视为应用真正的scrypt / Argon2之前的中间步骤,您可以防止暴力破解尝试。

在应用“真正”的密码哈希之前使用快速哈希算法作为预处理步骤并不罕见,甚至可能很有用。

  • BCrypt具有72个字节(71个UTF-8字符,然后是空终止符)的已知密码长度限制。Dropbox在运行明文密码之前应用SHA2-512,然后才将其传递给bcrypt。通过先对长密码进行哈希处理,他们克服了71个字符的限制。
  • 这不仅可以克服密码长度限制(避免截断或限制密码大小),而且可以防止在提供异常长的密码时发生拒绝服务攻击。BCrypt和Scrypt易受具有更长密码的攻击(我不知道Argon2的情况)。

因此,使用预哈希可能有优点(但不一定是MD5)。

我不知道您目前如何存储MD5哈希值。 MD5为128位。假设您将其存储在Base64中,您可以轻松识别它:

  • MD5: nMKuihunqT2jm0b8EBnEgQ==

所需的最终目标是类似于scrypt:

  • MD5: nMKuihunqT2jm0b8EBnEgQ==
  • scrypt: $s0$e0801$epIxT/h6HbbwHaehFnh/bw==$7H0vsXlY8UxxyW/BWx/9GuY7jEvGjT71GFd6O4SZND0=

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

MD5 + scrypt

类似于:

  • MD5: nMKuihunqT2jm0b8EBnEgQ==
  • MD5 + scrypt: $md5s0$e0801$eX8cPtmLjKSrZBJszHIuZA==$vapd0u4tYVdOXOlcIkFmrOEIr1Ml2Ue1l2+FVOJgbcI=
  • scrypt: $s0$e0801$epIxT/h6HbbwHaehFnh/bw==$7H0vsXlY8UxxyW/BWx/9GuY7jEvGjT71GFd6O4SZND0=

根据保存的哈希值,您现在可以识别使用的算法,并逐步升级密码。


1
这是一个相当老的问题!最终,我只是等待用户升级,计划最终锁定旧账户并让他们恢复密码,这将使他们达到最新标准。此外,我在密码系统中添加了一个版本,以便在每个用户可用时轻松升级到新算法,并且当他们登录时,系统会自动将其升级到最新版本。 - jpshook

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接