出于明显的安全原因,密码不应以纯文本形式存储:您必须存储哈希,并且还应仔细生成哈希以避免彩虹表攻击。
但是,通常您需要存储最后 n 个密码,并在不同密码之间强制实施最小的复杂性和最小更改(以防止用户使用 Password_1、Password_2、...、Password_n) 等序列。这对于纯文本密码来说是微不足道的,但是如何通过仅存储哈希来做到这一点呢?
换句话说:如何实现安全的密码历史记录机制?
-
2相关:security.stackexchange.com/questions/4704/...(顺便说一句,该网站可能是这个问题的更好位置)。就“最小变化”而言,我想不出任何替代方案来生成所有符合“最小变化”条件的选项(根据您的定义,这可能是很多!)并比较哈希值。“最小变化”的定义是什么?– 凯文·维米尔十一月 27, 2012 在 15:25
-
7存储最新的n个密码仅意味着用户将选择从 1 到n+1 的序列。– 约阿希姆·绍尔十一月 27, 2012 在 15:38
-
11我非常怀疑这样的密码策略是否可以提高安全性;恕我直言,它增加了人们诉诸于将密码保存在便笺上的机会。凯文的链接是一个很好的讨论。@KevinVermeer - 您实际上可以将变化量测量为 Levenshtein 距离 (en.wikipedia.org/wiki/Levenshtein_distance),也称为“编辑距离”。– 内森·朗十一月 27, 2012 在 17:03
-
5如果您的安全性如此严格,那么您也可以为用户生成一个随机密码,强制他们使用它,并定期更改它。这样您就可以完全控制他们的密码。– 反应古拉尔十一月 27, 2012 在 17:59
-
2@nathan:将密码存储在便笺上实际上是安全的。除非您可以物理访问便笺,否则无法攻击密码 - 消除了大约 99% 的威胁。把那张纸条放在钱包或钱包里,你基本上需要把这个人抢走才能得到它——这意味着安全漏洞被识别出来并且可以得到缓解。– 马特茨十一月 27, 2012 在 20:34
5 答案
存储哈希并根据这些存储的哈希验证输入的密码,就像登录时验证密码一样。您必须根据数字模式从给定的密码中生成“替代”密码,以检测您的“最小”更改。
登录时,您已经根据哈希验证输入的密码,无需以明文形式存储密码。在更改密码时,同样的技巧也有效,只需根据历史哈希检查输入和“最小更改”生成的密码即可。如果新密码令人满意,请将当前密码哈希移动到历史集,并将其替换为新密码的新哈希。
-
-
4@Lorenzo:正确。生成替代方案可以像您想要的那样复杂,只要确保您在复杂性和风险之间找到正确的权衡(不要让您的用户等待 5 分钟,同时检查所有可能性,并消失风险的可能性)。– 马丁·皮特斯十一月 27, 2012 在 15:49
-
-
2
-
当用户更改其密码时,要求他们输入以前的密码。您现在可以访问两个纯文本密码,即使您没有在数据库中存储纯文本密码也是如此。
对这两个密码执行您想要的任何验证。这不会阻止用户在两个密码之间交替(带有后缀 - 您可以根据其他答案中的建议防止直接交替),但它会防止更明显的情况。
-
-
2
-
是的。如果他们当前的密码是
potatoSalad1
,并且他们想要更新到potatoSalad2
,那么您会告诉更改太小,因为此时您同时拥有纯文本密码。但再往前追溯,你只有哈希,哈希的本质是你无法判断两个哈希是有相似还是完全不同的纯文本作为输入。– 内森·朗十一月 27, 2012 在 16:56
为了补充@martijnPieter的答案,可以通过基于新密码和旧密码(你们都有可用的密码)进行短暂的暴力破解来实现最小的更改
例如,您可以遍历与新密码相距为1 或 2 的所有密码,并查看它是否与旧密码匹配
但您可能要注意,这会降低用户对您正在散列密码的信心(因为您实际上是在说您可以取回以前的密码以拒绝新密码)
-
但是有许多序列具有较大的汉明距离,例如2012年2月-2012年3月>日或星期五-09-28-12->周二-11-27-12(日期),Password_Alpha-> Password_Beta,Pass_1111-> Pass_2222,Pass_qwer,Pass_tyui,传球,_op[]或十一->十二(交替计数系统),或弗兰克史密斯 ->弗雷德琼斯 ->修士塔克或愤怒 ->动物 ->苹果(公司目录中的名称或字典中的单词),具有先前密码的攻击者可以轻松猜到,但是您的算法将很难生成。– 凯文·维米尔十一月 27, 2012 在 16:00
-
-
+1 降低置信度。当我看到有人告诉我我的密码太像我三个月前使用的密码时,我立即想知道他们是否正在可逆地存储它们......或者如果他们有一个很棒的程序员。怀疑主义通常会获胜。– 蒂姆·波斯特十一月 28, 2012 在 1:58
这实际上更像是对@Brian聪明答案的补充。还要向@Martijn Pieters致敬,因为他们添加了有关如何根据当前密码暴力破解旧密码的详细信息,并@ratchet“汉明距离”的怪胎。我不删除我的答案,因为我认为它提供了有趣的背景来支持它们。
最先进的密码存储需要为每个用户使用多轮强大的单向加密哈希 (SHA-512+) 和唯一的盐 (128 位+)。但不要试图存储有关每个密码的其他信息。您存储的有关每个密码的信息越多,对哈希算法安全性的破坏就越大。
例
如果您知道以下情况,请考虑暴力破解密码变得多么容易:
- 它有 7 个字符长
- 字符 3-5 为大写(4 为小写)
- 1 和 7 是数字
- 6是一个符号
美式键盘有 95 个可打印字符,因此知道密码长度为 7 个字符会产生 95^7 = 69,833,729,610,000 = 7x10^13 排列。如果它真的是随机的,可能需要一年的时间才能在单个3Ghz处理器上破解它。但:
- 只有 26 个大写字符和 26 个小写字符
- 只有 10 位数字为这两个数字产生 100 种可能性
- 只有 32 个符号
所以(由于@Hellion而更正):
26^4 (charcters 2-5 are known upper or lower-case)
x 100 (characters 1 & 7 are digits)
x 32 (character 6 is a symbol)
====
1,462,323,200 possible passwords.
破解起来要容易5万倍!在这种情况下,存储良好的信息以防止类似的密码,已经将7个字符的密码的破解时间从一年缩短到几个小时。在功能强大的多处理器台式机上使用良好的视频卡和一点耐心解码所有密码现在非常可行。我希望这个简单的例子表明,您比较类似密码越有意义,您的哈希就越不安全。
强哈希的重要性
带有密码的数据库经常被盗,每个月都有巨大的闯入新闻。哎呀,就在上个月,南卡罗来纳州失去了每个人的社会安全号码——哎呀!这些违规行为还有多少被掩盖?
结语
对我来说最可怕的事情是当人们为多个站点选择相同或相似的密码时,因此闯入一个站点可以让攻击者访问所有站点。我很想看到一种行之有效的方法来防止这种情况,尽管我认为防止最常见的错误密码比防止单个用户在同一站点中重复使用他们的错误密码更有帮助。我能建议的最好的是公司范围内的策略,使用安全的密码管理器,为每个用户生成高度随机的密码并安全地存储它们。
首先,您可以存储最后“n”个先前密码的哈希值,以便检查其新密码是否与以前的密码重复。您还拥有其当前密码的纯文本(因为他们已登录或向您提供密码以验证其密码更改请求)及其新密码,因此您可以检查这两个密码之间的最小更改。
如果(对您来说)直接将这两个密码与“n”以前的密码进行比较非常重要,那么您必须存储这些密码(加密)以便以后能够检索它们。
虽然这样做可能被视为安全漏洞,但可以实施加密方法来提供足够的安全性。
- 存储每个密码(加密),用于最后的“n”个密码。
- 存储创建最新密码的日期和时间。
- 存储最新密码的哈希值。
- 使用当前密码的哈希(加盐)和密码创建时间戳(可能还有帐号或电子邮件地址之类的东西)加密所有密码。
- 每次创建新密码时,取消加密并重新加密所有密码。
然后,无论何时更改密码,您都可以取消加密所有旧密码,并进行所有最小更改测试。
现在,如果有人拥有此人的密码,并且知道所有其他必要的详细信息,他们可以为这个人解密此信息。但是,如果他们已经拥有此人的密码,则他们已经可以以此人的身份登录并访问此人的帐户。
此外,对于旧密码,它们可能不必以严格的纯文本形式存储。它们可以以某种混淆的方式存储。或存储为按字母顺序排列的密码字符列表。
我并不是说在一般情况下这是建议做的事情,但是假设您描述的任务在您的情况下是必需的,那么这是通过一些安全措施完成它的一种方法。