ASP.net有一个System.Web.Helpers.Crypto类用于散列和验证密码。它似乎在运行中生成盐并将其存储为密码哈希的一部分。
我的问题是,随着计算机变得越来越强大并且需要增加迭代次数来帮助防止暴力攻击,你怎么能增加现有密码的迭代次数呢?
迭代次数被硬编码到帮助程序中。将其更改为更大的数字将增加新密码的迭代次数,但在验证时也会单方面增加所有密码。这会破坏旧密码的密码验证吗?
为了规划未来,您不想存储盐和迭代次数吗?
此外,是否可以通过执行额外的迭代来“加强”现有的密码哈希值,还是所有迭代都必须作为一个操作进行?
答案 0 :(得分:3)
该助手实际上存储了一个前缀,表明算法和使用的迭代次数,因此如果算法在未来发生变化,旧密码仍然可以验证。
我们考虑将默认值从1,000提高到更高。但是,当我们这样做时,新的CPU命中是不可接受的。消费者设备可以要求1,000,000次迭代,因为如果你的平板电脑或手机需要0.5秒才能让你登录,你可能不会非常在意。但是当一个网页需要花费大量时间来处理登录请求时..好吧..您不希望用户只需登录即可对服务器执行操作。:)
仍然遗憾的是,1000次迭代是提供更高安全性(通过直接盐和哈希)并保持Web服务器响应的最佳权衡。
答案 1 :(得分:2)
你说存储盐和迭代计数对于将来的计划更好是正确的,只需看看PHP的password_verify()。
不仅迭代计数(称为成本,不是完全迭代计数,而是基于相同的概念)和盐与派生密钥一起存储,算法也存储在以后需要替换算法的情况下。
System.Web.Helpers.Crypto类使用PBKDF2来散列密码,这些密码在内部使用散列算法超过定义的迭代次数来散列密码。由于内部操作都是不可逆的,并且“迭代”段不是最终段,因此执行额外散列不起作用。整个密码需要从其原始明文来源重新进行。
通常,当用户下次再次登录时,会发生重新密码的过程。此时,系统可以确定是否需要重新设置用户的密码,并在需要时继续相应地进行。这不仅可以避免运行可能导致停机的主要重复操作的成本,而且是用户的纯文本密码再次可用的唯一时间。如果在不久的将来可能存在漏洞,而不是漏洞完全暴露的时间,那么密码应该重新进行,因为此时可能为时已晚。
如果数据的安全性是一个问题以及未来的规划,我建议您使用另一个类(可能是自己的),允许自定义的迭代次数并将所有相关数据存储在派生密钥/散列中密码本身。
答案 2 :(得分:1)
不,您无法“加强”现有密码 - 更改哈希迭代次数会破坏现有验证。除非您要强制所有当前用户创建新密码,否则请勿更改哈希设置。如果您正在加密而不是散列,那么这是可能的(但不要进行加密)。
我们使用一个通用的辅助库进行salting和散列,让我们可以调整每个项目的散列迭代次数,这样我们就可以任意增加迭代次数。如果您担心面向未来,可能会让您在将来扩大规模。
通常我们使用算法组合(SHA256,MD5等)加盐然后散列大约100次。迭代次数和散列序列是单个项目设置的一部分 - 我们不会将它与salt和散列结果一起存储在DB中。
编辑:
现在我发现(通常)你实际上可以哈希现有密码哈希更多次以使它们与更新的哈希功能同步 - 只要你的新哈希例程的第一部分与您现有的相同。例如,如果您当前散列10次并将其更改为100次,则可以将现有值散列90次并更新数据库。如果Crypto
实现没有沿途腌制,我希望10 + 90次迭代哈希产生与100次哈希相同的结果。
但是,如果您搞砸了这个过程,最终可能会破坏所有用户的现有密码。除非我真的需要,否则我不愿意实施这样的事情。