密码重置链接:随机值还是经过身份验证的消息?

信息安全 密码 密码策略
2021-09-09 01:35:09

哪个更好?

  1. 创建防篡改加密密码重置令牌,其中包含加密令牌中的用户 ID 和到期时间。

  2. 生成一个随机令牌并将其与用户 ID 和到期日期一起存储在数据库中。当用户单击链接时查找令牌。

我可以看到 #2 的一个优势是您可以控制这些令牌。如果你想早点过期,你可以。我看到#1 的一个困难是确保你发送的令牌确实是安全的和防篡改的。您完全依赖于不搞砸密码学。

ASP.NET 2.0 是否有任何用于生成密码重置令牌的内置方法?

4个回答

创建一个绝对不包含任何信息的随机令牌并将其与用户名和过期时间链接到数据库中是迄今为止最好的解决方案。

加密(和散列)用于存储和传输绝对必须发送的数据。如果有任何方法可以做某事而不必发送该数据,无论是否加密,提供相同的功能和安全性,您应该使用该方法。换句话说,加密应该是保护数据的最后手段。

这些令牌是密码等价物,因此必须满足类似的要求。但到目前为止,最大的一点是它不能被对手任意猜测。因此,它应该与随机数据无法区分。

当您对任何数据进行编码时,显然需要对其进行加密。现在,这可能会涉及到您自己的某种程度的滚动,或者至少自己将加密原语放在一起,您可能会做错(请参阅:不要成为戴夫)。

因此,这意味着您最安全和最简单的解决方案是创建一个非常随机的令牌,并将其哈希/加盐存储在数据库中,以及该令牌的 id。加入 id 和 token,并将其序列化为 hex 或 Base32 并将其发送给用户。当令牌返回时,使用 id 从数据库中获取令牌/盐,并对令牌的其余部分进行哈希处理以查看它是否匹配。

您必须确保有关令牌的一些额外信息,因为它们将出现在人们的电子邮件中。

  • 确保他们有足够高的熵来抵抗猜测
  • 它们必须足够短以方便地编码成 URL
  • 它们必须在相当短的时间窗口后过期,因为它们将在人们的电子邮件收件箱中
  • 他们必须一次性使用

您可以将过期时间编码为令牌并使用 HMAC,但通常密码重置涉及访问特定 URL。通常为了让用户更轻松,在 URL 中包含令牌作为 GET 字段。

想要保持 URL 相对较小且仅由可打印字符组成,您可能会将时间戳编码为整数并使用固定宽度设置。这必须指定用户、到期时间和 MAC。我认为它是可靠的,但它并非没有某种编码工作。

由于无论如何您都需要访问数据库以获取密码,并且无需考虑对随机的固定宽度值进行编码,但是,我就这样做了。在其他条件相同的情况下(我认为相当平等),容易胜出。额外的好处:更低的 CPU 使用率。

这是一个共同的主题。您的方案#1 是对方案#2存储优化在#2 中,您必须在服务器端生成并存储一个随机值。这为您提供了您可能想要的所有控制,但需要在您的数据库中添加一个额外的列,或类似的东西。方案在客户端卸载此存储需求。由于客户端不可信,您必须在链接中添加完整性检查,即MAC不需要加密,因为重置链接中没有任何内容需要对用户保密(用户已经知道他的姓名以及何时要求重置密码),但您希望防止恶意客户端创建假重置链接,因此 MAC。

因此,在场景 #1 中,令牌内容必须包含执行密码重置策略所需的所有数据,但选择不存储在服务器上;这意味着用户名和时间戳(密码重置过程被触发的时间,或到期时间)。如果您想防止用户多次重复使用重置链接,您可能希望在 MAC 的输入中包含先前密码的哈希(不一定在令牌中)。

计算和验证 MAC 不会占用大量资源,可能比生成随机令牌并将其存储在数据库中要少一点(数据库访问将比密码学昂贵得多)。但是,无论如何这种影响可能都可以忽略不计(数据库很快)。方案 #1 的一个缺点是您需要在服务器上保留一个密钥,在前端之间共享(如果您有多个),对重启有弹性(所以不是仅在 RAM 中的密钥,除非您准备好使其失效服务器重新启动时的所有密码重置链接),当然,还可以防止窃听。

随机令牌(场景 #2)可能更容易,或者,如果您愿意,更难出错这是一个足够好的理由推荐它。