这是一个大学的任务。 在我们学院,他们使用微软的Active Directory运行他们的networking。
每个月我们都会被要求更改我们的密码,而当我们这样做的时候,它不会接受我们以前使用过的五个密码或类似的密码。 例如,如果我的密码是'secretpassword1',下个月我就不能使用'secretpassword2'。
然而,我可以看到这样做的唯一方法是,如果哈希algorithm中存在用于存储密码的缺陷, 密码不被散列但被encryption; 或者更糟糕的是它们以明文forms存储。
经过快速的Google-Fu会话之后,Active Directory会将密码存储在常规的Windows哈希中。 那么谁能解释这个?
干杯
PS这可能是我们的想象; 也许你可以重复使用一个稍微不同的密码?
旧的密码以散列格式存储在AD数据库中。 作为密码更改过程的一部分,这将被检查和/或更新。
如果您使用新密码生成变体,而不是旧密码,则很容易。
想象一下,一个算法需要一个密码,并生成几百个简单的变体。 所以对于像password1
这样的输入,它会产生以下变种:
PASSWORD1 PasSSword1 password2 password P@aaW0RD2 ....
还有几百人 (请注意,其中一种变体是"password"
。)
密码破解者有这样的算法,并用它们对字典进行猜测。
使用这个算法,我们可以执行以下步骤:
用户将他们的第一个密码设置为"password"
。 系统存储hash("password")
,并且每当用户登录时使用该散列进行比较。
几个星期后,用户将他们的密码更改为"hunter2"
。 当前的密码哈希被改为hash("hunter2")
。 hash("password")
存储在N个历史密码散列列表中。
几个星期后,用户尝试将密码更改为"password1"
。 在此更改尝试执行以下步骤。
3a)由于用户刚刚输入了新的密码,因此可以清除新的密码。 "password1"
被用作上述变体生成算法的输入。 生成几百个变体密码(清除)。
3b)对于每个变体密码,计算该密码hash(variant)
,对每个旧密码使用salt。 如上所述, "password1"
的变体之一是"password"
,所以在我们的变体哈希列表中,我们将有hash("password")
。 我们最终用V变体哈希来测试每个旧密码,总共V * N哈希。
3c)针对每个变体散列的正确的盐渍版本,针对当前的散列和先前的散列,针对总共V * N个二进制数组比较进行测试。
3d)其中一个变体散列是hash("password")
,其中一个存储的N个历史散列也是hash("password")
。 这些散列完全匹配,所以密码被拒绝。
这种技术需要生成V * N散列,其中V是〜500,N是〜10。 这只需要几秒钟(即使使用PBKDF2,bcrypt或scrypt),并且无需磁盘访问即可轻松完成。
关于salt的说明:每当你改变用户的密码(你应该这么做)时,改变盐的确会让事情变得困难一些,不过你只需要生成一个线性数量的哈希值,不管你的盐有多大。