27

我被要求对 Intranet 站点进行一些更改/更新;正如他们所说,让它成为“未来的证明”。

我们发现密码是使用 MD5 算法进行哈希处理的。(该系统自 2001 年以来就已经存在,因此当时就足够了)。
我们现在想将散列算法升级到更强大的算法(BCrypt-hash 或 SHA-256)。

我们显然不知道明文密码,并且为用户库创建新密码不是一个选项*)

所以,我的问题是:

在不访问明文密码的情况下更改散列算法的公认方法是什么?
最好的解决方案是完全“在幕后”的解决方案。

*) 我们尝试了; 试图说服他们,我们使用“密码年龄”的论据,试图用咖啡贿赂他们,试图用蛋糕贿赂他们等等。但这不是一个选择

更新
我希望有某种自动解决方案来解决问题,但显然除了“等待用户登录,然后转换”之外没有其他选择。

好吧,至少现在我现在没有其他可用的解决方案。

4

7 回答 7

33

首先,在数据库中添加一个字段来识别密码是使用 MD5 还是新算法。

对于所有仍在使用 MD5 的密码:

-- 在登录过程中,验证用户输入的密码:将用户提交的密码临时存储在内存中(这里没有安全问题,因为它已经在内存中的某个地方)并进行通常的 MD5 哈希并与存储的哈希进行比较;

-- 如果给出了正确的密码(与现有哈希匹配),则通过新算法运行临时存储的密码,存储该值,更新新字段以识别此密码已更新为新算法。

(当然,您只需对任何新用户/新密码使用新算法。)

于 2009-10-07T19:51:30.687 回答
7

我不完全确定这个选项,因为我不是密码学专家。如果我在这里的某个时候错了,请纠正我!

我认为 Dave P. 显然是最好的选择。

... 但。有一个自动解决方案 - 自己散列旧的散列。也就是说,获取当前的哈希值,并使用更强大的算法再次对其进行哈希处理。请注意,据我了解,这里的哈希长度不会增加任何安全性,只会增加新算法的加密复杂性。

当然,问题是检查密码必须经过两个哈希。而且您也必须对每个新密码执行相同的操作。这很愚蠢。除非您想使用像 Dave P. 这样的类似方案,并解释说最终使用新的散列算法回到单散列密码......在这种情况下,为什么还要为此烦恼?(当然,您可能会在华丽的“提高所有密码的安全性,立即应用!”中使用它——在公司西装的演示中,脸相对直...)

尽管如此,它仍然是一个可以立即应用于所有当前密码的选项,无需任何逐步迁移阶段。

但是,天哪,天哪,以后有人会因为看到那段代码而大笑!:)

于 2009-10-13T08:41:11.653 回答
3

将 passwordChange 日期时间字段添加到数据库。

第 X 天之前设置的所有密码,使用 MD5 检查

第 X 天之后设置的所有密码,使用 BCrypt 或其他方式检查。

于 2009-10-07T19:44:59.950 回答
3

您可以在散列字段本身(例如“MD5:d41d8cd98f00b204e9800998ecf8427e”)或另一列中存储用于创建该散列的算法。然后,您必须修改登录过程以在检查密码时使用正确的算法。自然,任何新密码都将使用新算法进行哈希处理。希望密码最终会过期,并且随着时间的推移,所有 MD5 哈希值都将被淘汰。

于 2009-10-07T19:45:43.663 回答
3

由于您不知道明文密码,也许您应该创建一个指示加密版本的字段(如PasswordVersion bit default 0

下次用户尝试登录时,使用当前算法版本检查散列密码,就像您今天一样。如果匹配,则再次对其进行哈希处理并更新PasswordVersion字段。

希望您不需要PasswordVersion大于bit. =)

于 2009-10-07T19:46:16.280 回答
3

您应该更改密码数据库以存储 3 项:

  1. 算法标识符。
  2. 服务器首次计算和存储密码哈希时选择的随机盐字符串。
  3. 使用指定算法的 salt+password 连接的哈希值。

当然,这些可以一起存储在一个带有分隔符的文本字段中:

“SHA256:this-is-salt:this-is-hash-value”

现在将现有条目转换为具有空盐和旧算法的值

“MD5::this-is-the-old-md5-hash-without-salt”

现在您有足够的信息来验证所有现有的密码条目,但您也可以验证新条目(因为您知道使用了哪个哈希函数)。您可以在现有用户下次登录时将旧条目转换为新算法,因为在此过程中您将获得他们的密码:

  1. 如果您的数据库表明他们正在使用没有加盐的旧算法,请首先通过检查密码的 MD5 哈希值是否匹配来以旧方式验证密码。如果不是,拒绝登录。
  2. 如果密码被验证,让服务器选择一个随机盐字符串,计算盐+密码的 SHA256 哈希,并用一个新的密码表条目替换密码表条目,指定新算法、盐和哈希。
  3. 当用户再次登录时,您会看到他们正在使用新算法,因此计算 salt+password 的哈希值并检查它是否与存储的哈希值匹配。

最终,在该系统运行适当的时间后,您可以禁用尚未转换的帐户(如果需要)。

为每个条目添加唯一的随机盐字符串使该方案更能抵抗使用彩虹表的字典攻击。

于 2009-10-07T21:06:32.190 回答
0

最佳答案来自真正的密码学专家 https://paragonie.com/blog/2016/02/how-safely-store-password-in-2016#legacy-hashes

这篇文章还有助于解释您应该使用哪种散列。即使它说的是 2016 年,它仍然是最新的。如果有疑问,请使用 bcrypt。

在您的用户帐户表中添加一列,称为 legacy_password(或等效项)。这只是一个布尔值

计算现有密码散列的新的更强散列并将它们存储在数据库中。

修改您的身份验证代码以处理旧标志。

当用户尝试登录时,首先检查是否设置了 legacy_password 标志。如果是,首先使用旧密码散列算法对他们的密码进行预散列,然后使用这个预散列值代替他们的密码。之后 (md5),重新计算新哈希并将新哈希存储在数据库中,禁用进程中的 legacy_password 标志。

于 2019-05-26T18:21:12.127 回答