将旧的MD5密码迁移到bcrypt密码

17

我正在使用Devise进行身份验证重构一个基于Rails的网站。之前的网站使用一个用户数据库,其中密码被md5加密,因此我想将这些密码迁移到Devise使用的加密方式。我该怎么解决?


4个回答

22

Oleksi和josnidhin在回答您的问题时做得很好。我只想添加一些在过渡阶段应该做的事情:

将数据库迁移至拥有两个“密码哈希”列,一个包含现有的旧MD5哈希值,另一个用于新的bcrypt哈希值,最初都填充为NULL。下次用户登录时,请执行以下步骤:

1)检查bcrypt列中是否已经存在值。如果存在,则继续执行第3步,否则执行第2步。

2)使用MD5机制对用户进行身份验证,使用MD5列中的值。如果成功,请额外计算新的bcrypt哈希并将其存储在新列中。完成。

3)使用bcrypt值对用户进行身份验证。简单地忽略MD5值。

然后,定期检查新的bcrypt列是否填充。如果是这样,请丢弃MD5列并更新应用程序以仅使用新机制。

但这只是一厢情愿的想法,总会有一些用户在此期间没有登录。向他们发送一封邮件,告诉他们您正在做什么,这对他们最有利,并请求他们尽快登录。

几周后,再次检查bcrypt状态。如果仍然缺少某些密码(肯定会有的 :)),您可以重置这些用户的密码,生成一个随机密码并通过邮件通知他们,就像如果他们忘记密码时所做的那样。

然后,您最终可以清除MD5列,丢弃相应的代码,并升级您的应用程序以仅使用新的身份验证。


谢谢您的解释,现在我要和 Devise 进行一场大战 :D - Marco Godínez
2
每次插入相应的bcrypt版本时,为什么不从md5列中删除条目? - celicni
5
另外,还有一种更优雅的“哈希哈希”方法,因为您可以在不需要用户登录的情况下完成它。使用新的安全函数对旧的哈希值进行哈希处理。然后当用户登录时,您将使用旧函数哈希处理其密码,并使用新函数对结果进行哈希处理。 - celicni

13

我有另一种解决方案:

  1. 添加bcrypt列。
  2. 通过bcrypt算法运行MD5哈希,填充bcrypt列。
  3. 将登录更改为始终使用bcrypt列和哈希函数,即明文->md5->bcrypt

这样一来,所有密码都可以同时迁移,并永久丢弃MD5哈希。考虑自己尝试这样做,但没有发现任何问题。有人愿意试试吗?是否有什么明显的遗漏?


3
根据你提出的建议(即仅传递哈希码而不是密码),降低传递给bcrypt的数据的熵可能会削弱bcrypt算法。我不知道这是否属实,但我认为这绝对值得进一步研究。 - Brann
2
@Brann,这个方案显然是可行的。迭代bcrypt具有相同的熵减效果,但被认为是安全的。所以这里没有问题。 - usr
我自己也考虑过这个问题。我一直在想,将哈希值转换为MD5是否会降低安全性。另一种方法是,你可以将一个指示器与账户绑定,指示密码是旧的还是新的。如果是新的,先将其哈希为MD5,然后再使用bcrypt。如果是旧的,只需使用bcrypt即可。这样,你就可以完全转换现有的数据库,而不必等待用户转换他们的旧密码。 - peabody
根据这个Reddit帖子,除此之外,您还可以包括一个额外的位字段“legacy”,并在每次验证“legacy”密码并取消设置遗留字段时将密码转换为plain text -> bcrypt。此外,@celicni 评论了接受答案中的内容。 - icc97

7

无法将MD5哈希转换为其他类型的哈希。您需要让用户使用旧系统登录,然后使用新方法对其提供的密码进行哈希处理。一旦获得了新哈希,就可以删除旧的MD5哈希。


2

您需要要求用户使用旧密码登录,然后更改密码。例如,显示一个强制更改密码页面,该页面将使用bcrypt存储密码。一旦给出新密码,您可以在系统中禁用/删除旧密码。


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