哈希函数变化

信息安全 密码 哈希 密码管理
2021-09-01 04:20:51

我使用不安全(旧)加密哈希函数将用户帐户密码存储在数据库中。

更改密码哈希函数的最佳/常用方法是什么?我的脑海里只有两个想法:

  1. 提示所有用户在下次登录时更改他们的密码,并在他们这样做时使用新函数对他们的密码进行哈希处理。这不是一个好的选择,因为有很多问题(非活跃用户、迁移周期长、实施复杂......)

  2. 用新的散列函数对旧的散列值进行散列,并重写数据库校验密码的方法:newHash(salt + oldHash(salt + password))

这种双重散列在我看来是个好主意,既优雅又易于实现。

我想知道这里是否有任何我没有注意到的警告。这是通常的做法,还是有另一种方法?使用弱散列函数的输出作为强散列函数的输入是否存在一些已知的加密漏洞。

如果这是个好主意,那么盐呢?可以对两个哈希函数使用相同的盐吗?

4个回答

就个人而言,我可能会同时实现新用户获得强大的现代散列(bcrypt 或其他密钥增强加密散列)和老用户使用弱散列包裹 bcrypt。在人们抱怨额外的实现复杂性之前,另一种选择是总是强制新用户使用弱散列算法包裹强散列算法,这意味着你永远不会摆脱原来的方案。

我会有一些类似于 , , 或 in crypt 的类型哈希方案的记录指示符$1$$2a$$5$$6$crypt 手册页):

   If  salt is a character string starting with the characters "$id$" fol‐
   lowed by a string terminated by "$":

          $id$salt$encrypted

   ... id  identifies  the  encryption
   method  used  and  this  then  determines  how the rest of the password
   string is interpreted.  The following values of id are supported:

          ID  | Method
          ─────────────────────────────────────────────────────────
          1   | MD5
          2a  | Blowfish (not in mainline glibc; added in some
              | Linux distributions)
          5   | SHA-256 (since glibc 2.7)
          6   | SHA-512 (since glibc 2.7)

在这种情况下,您需要三种类型的密码哈希:

  1. 旧的快速弱散列
  2. 用强盐包裹在慢速散列周围的旧的快速弱散列
  3. 新的慢哈希。

在第 1 天,我会将第 1 类中的所有内容移至第 2 类。新密码将放入第 3 类。此外,当人们登录时,您甚至可以将每个成功验证的哈希从第 2 类迁移到第 3 类,而明文密码在内存中。在某些时候,您甚至可以完全消除弱散列方案的任何证据/遗留维护。(例如,强制帐户在更改后 2 年以上未登录的用户重置其密码)。

如果以下条件都成立,您的建议 2(将旧哈希值作为新哈希的“密码”)是好的

  • 旧哈希对原有足够的抵抗力
  • 新的哈希使用所有需要的花哨功能来认为它是“健壮的”(即bcrypt有很多轮次,每个密码都有一个新的随机盐,包括给定用户的密码更改)。
  • 旧的散列可以足够有效地计算,以至于整个“可配置的慢速”业务完全依赖于新的散列。

请注意,虽然 MD5 在碰撞方面彻底崩溃,但在原像方面仍然显得相当强大。

在您的数据库中包含“哈希类型”字段仍然符合您的最佳利益,以便可以顺利处理迁移。例如,您可以应用您的哈希值,然后计划迁移到仅使用新哈希的密码哈希方案 - 每当创建或更改密码时,密码都会更新为新方案,例如逐渐迁移。稍后(比如一年后),您可以为仍然使用旧格式的密码设置强制更新(用户必须在下次登录时重新输入密码)。

即使您不喜欢迁移(谁喜欢?),如果当时的条件迫使您进行迁移(例如破坏性的密码分析中断),为可能的未来迁移做准备似乎只是谨慎的做法。

我会使用bcrypt作为新的哈希值。否则,鉴于您为 bcrypt 使用了良好的盐,您“包装”旧哈希的解决方案应该是安全的。当系统想要升级他们如何散列密码时,我已经看到这个解决方案运行良好几次。

如果您不想费心使用旧的哈希函数,又不想强迫所有人更改密码,那么有一种优雅的解决方案。

为每个用户配置文件添加一列/值。让我们调用 HashVersion

当用户在迁移后第一次登录时,系统将能够检测到它正在使用旧的哈希函数。因此,如果用户提供的密码与您的哈希值匹配,那么您将获取纯文本密码并使用您的新算法对其进行哈希处理,重置盐等。然后你提高 HashVersion,这样你就知道它现在正在使用新的哈希函数。

在我看来,这是最好的解决方案,尤其是如果您以前的哈希函数确实不安全。