系统如何在不以明文形式存储或处理旧密码的情况下强制密码中的最小更改字符数?
我不确定是否要与用户之前使用的所有密码进行比较,因为它实际上取决于您使用的散列系统,我会说是否可以从散列中得出任何相似性,那么它不是一个很好的开始系统和。
但是假设用户在设置他们的新密码时必须提供他们当前的密码,你至少可以检查新密码和当前密码,因为此时你将两者都没有散列。
Linux 上的pam_cracklib
模块会像这样检查密码,默认情况下会进行一些基本检查。
- 新密码是否只是字母颠倒(“password”与“drowssap”)或旋转(“password”与“asswordp”)的旧密码?
- 新密码是否仅因大小写改变而与旧密码不同(“密码”与“密码”)?
- 新密码中至少有一些最少字符数不存在于旧密码中吗?这就是“difok”参数发挥作用的地方。
您可以在此处找到有关它的更多详细信息。
这很容易在密码更改时完成(用户在哪里并且应该被要求提供旧密码和新密码)。
通常,当您更改密码时,您需要先输入旧密码。这对安全很有用,可以确保路过您计算机的人不能很快更改密码并在您转身时将您锁在门外。它还允许服务器强制执行密码距离规则。服务器只需将旧密码保存在内存中,直到验证新密码与旧密码有足够的不同。它永远不需要存储未散列的密码。
顺便说一句,这样的密码更改规则不利于安全。(是的,我知道你是这里的受害者。)如果用户必须经常更改密码,他们要么选择一个非常容易记住的密码,要么将其写在易于访问的地方。密码过期几乎没有什么优势,而且由于让用户每隔几个月更改一次密码而导致的密码强度损失超过了这些优势。有关密码过期的更深入处理,请参阅每 90 天更改一次密码如何提高安全性?强制用户更改密码有用吗?和需要定期更改密码但存储以前的密码?
通常,当您更改密码时,您需要先输入旧密码。这对安全很有用,可以确保路过您计算机的人不能很快更改密码并在您转身时将您锁在门外。它还允许服务器强制执行密码距离规则。服务器只需将旧密码保存在内存中,直到验证新密码与旧密码有足够的不同。它永远不需要存储未散列的密码,并且可以在存储新散列后立即删除旧散列。
如果服务器检查旧密码是否相等,而不仅仅是最后一个密码,那就是另一回事了。使用旧散列检查密码重用很容易:对于每个旧散列,用旧盐计算新密码的散列并与旧散列值进行比较。在正确配置的系统上,这应该需要几秒钟。
如果服务器正在检查与旧密码的相似性,而不仅仅是与旧密码的相等性以及与前一个密码的相似性,那就不同了。如果服务器使用正确的散列,那么它必须尝试新密码的变体,并使用所有旧盐对每个变体进行散列。这可能需要几分钟或更长时间,而变化的数量不可忽略。因此,如果服务器抱怨与旧密码相似,我会警惕他们可能存储了不正确散列的密码。
还有另一种相似性的方法,即在设置密码后立即存储每个密码变体的散列,每个变体独立加盐。但这并没有给你带来太多好处:服务器仍然需要使用所有这些盐计算新密码的哈希值,这仍然需要很长时间,对于典型的密码更改来说太长了。
恢复实际有效但我从未见过在任何地方实施的旧密码的方法是在提示用户输入旧密码并从内存中删除旧密码之前对密码更改执行以下操作:
- 从新密码派生对称密钥(使用密钥加强算法)。
- 以相同的方式从旧密码中派生密钥。
- 使用旧密钥解密旧密码列表。
- 将以前的密码附加到列表中。
- 进行策略检查——此时所有先前的密码都是已知的。如果新密码通过检查...
- 使用新密钥加密旧密码列表。
- 更改数据库的密码和先前密码的加密列表。
这有点冒险,因为如果当前密码被泄露,所有之前的密码也会被泄露。但它确实允许通过合理的计算工作对任意数量的先前密码执行密码距离策略。