SHA-1密码存储安全吗?

结论: SHA-1对于图像前攻击是安全的,但是它很容易计算,这意味着它更容易安装一个暴力或者字典式攻击。(对于 SHA-256这样的继任者也是如此。)根据具体情况,设计成计算代价高昂的哈希函数(如 bcrypt)可能是更好的选择。


有些人经常说“ SHA-1坏了”,所以我想知道这到底是什么意思。假设我有一个 SHA-1密码哈希的数据库,一个拥有最先进的 SHA-1破解算法的攻击者和一个拥有100,000台机器的僵尸网络可以访问它。(拥有10万台家用电脑的控制权意味着它们可以每秒执行10 ^ 15次操作。)他们需要多长时间

  1. 找出任何一个用户的密码?
  2. 找出给定用户的密码?
  3. 找出所有用户的密码?
  4. 找到作为用户之一登录的方法?
  5. 找到以特定用户身份登录的方法?

如果密码被加了盐,这种情况会发生什么变化呢?Salting (前缀,后缀,两者都有,或者像 xor-ing 这样更复杂的东西)的方法重要吗?

以下是我目前的理解,经过一些谷歌搜索。如果我误解了什么,请在回答中纠正。

  • 如果没有} ,彩虹攻击将立即找到所有密码(除了极长的密码)。
  • 如果有一个足够长的随机盐,找到密码的最有效的方法是暴力或字典式攻击。无论是碰撞攻击还是前像攻击都无助于找到实际的密码,因此针对 SHA-1的加密攻击在这里都没有帮助。使用什么算法并不重要——甚至可以使用 MD5或 MD4,密码也同样安全(因为计算 SHA-1散列比较慢,所以略有不同)。
  • 为了评估“一样安全”的安全程度,假设一次 sha1运行需要1000个操作,密码包含大写、小写和数字(即60个字符)。这意味着攻击者每天可以测试10156060 * 24/1000 ~ = 1017潜在密码。对于一个穷举法来说,这意味着在3小时内测试所有密码最多9个字符,一周内测试最多10个字符,一年内测试最多11个字符。(每增加一个字符需要60倍的时间。)字典式攻击的速度要快得多(即使只有一台电脑的攻击者也能在几个小时内完成) ,但只能找到弱密码。
  • 要以用户身份登录,攻击者不需要找到确切的密码; 只需找到导致相同散列的字符串即可。这被称为第一次前像攻击。据我所知,没有针对 SHA-1的图像前攻击。(暴力攻击需要2160操作,这意味着我们的理论攻击者需要1030年才能完成。理论上可能性的极限大约是260操作,在这种情况下,攻击将需要几年时间。)针对 SHA-1简化版本的前像攻击的效果可以忽略不计(对于使用44步而不是80步的简化 SHA-1,攻击时间从2160操作下降到2157)。有一些针对 SHA-1的碰撞攻击在理论上是可行的(我找到的最好的将时间从280减少到252) ,但是这些攻击对密码哈希来说是无用的,即使没有加盐。

简而言之,用 SHA-1存储密码看起来非常安全。我错过了什么吗?

更新: 马塞洛指出了一篇提到 在2 < sup > 106 操作中的第二次前像攻击的文章。(编辑:作为 托马斯解释道,这种攻击是一种假设的结构,不适用于现实生活中的场景。)不过我还是不明白这对于 SHa-1作为密钥导出函数的使用有什么危险。一般来说,是否有充分的理由认为一个碰撞攻击或第二个前像攻击最终会变成第一个前像攻击?

62704 次浏览

在 SHA-1中已经发现了严重的漏洞,这使得搜索速度比蛮力快得多。这在很大程度上仍然是难以解决的,但是这种情况不会持续太久; 偏执的程序员喜欢 SHA-2系列中的某些东西。

这篇文章对2005年最初结果的评价如下:

“是时候走路了,但不要跑,走到安全出口。你看不到烟,但是火灾警报已经响了。”

并不是当前的密码分析使得 SHA-1变得不安全,而是加密社区担心更糟糕的消息可能即将到来。这种担心也适用于 SHA-2,它与 SHA-1有相同的缺陷,尽管搜索空间要大得多,因此正在寻找 SHA-3

简而言之,SHA-1目前是安全的,而且可能在未来一段时间内也是安全的,但加密社区对预后感到不安。

如果存储带盐的密码,那么 SHA-1可以满足实际需要。 SHA-2被认为是更安全的,但 SHA-1不是一个问题,除非你有一个真正的偏执狂的理由。

下面是 NIST :

到目前为止 SHA-1上显示的结果 不要把它的保安叫到 问题。然而,由于 NIST 计划逐步淘汰 SHA-1支持更大的和 更强的哈希函数(SHA-224, SHA-256、 SHA-384及 SHA-512) 二零一零年。

就目前的技术水平而言,你的描述听起来很准确。

但是,您不应该使用任何散列函数的单次迭代: 至少,您应该多次迭代(散列的1000次迭代使攻击者的工作增加了1000倍。它同样增加了你的工作量,但是你做的密码哈希比他们少得多)。

但是,在理想情况下,您应该使用现有的密码存储原语,如所描述的 给你

对于你的问题,简短的回答是: SHA-1是最安全的,因为你可以得到。MD5也可以,甚至 MD4也可以,但它可能会让一些投资者感到紧张。对于 公共关系,最好使用“更好的”散列函数,例如 SHA-256,即使将其输出截断为160或128位(以节省存储成本)。一些 SHA-3第二轮候选人似乎比 SHA-1更快,同时可以说是“更安全”; 但他们仍然是一个新的有点,所以坚持 SHA-256或 SHA-512将是一个更安全的路线现在。这会让你看起来很专业,很谨慎,这很好。

请注意,“尽可能安全”与“绝对安全”是不一样的。请参阅下面相当长的解释。

关于已知攻击:

已知的对 MD4、 MD5和 SHA-1的攻击是关于碰撞的,碰撞不会影响前像电阻。已经证明,MD4有一些弱点,当试图破坏 HMAC/MD4时,可以(仅在理论上)利用这些弱点,但是这并不适用于您的问题。Kesley 和 Schneier 在论文中提出的2106秒前像攻击是一种通用的权衡,它只适用于非常长的输入(260字节; 即100万 TB ——注意106 + 60超过160; 这就是你看到的权衡没有任何魔力的地方)。

此消息的其余部分假设您使用的散列函数(例如 SHA-1)是一个“黑盒”,没有攻击者可能使用的特殊属性。即使使用“破碎”的散列函数 MD5和 SHA-1,您现在也可以得到这个结果。

关于彩虹桌:

“彩虹攻击”实际上是字典或穷举法的成本分摊。它是从1980年赫尔曼首次描述的 时间-记忆权衡衍生出来的。假设你有 N可能的密码(这是你的字典的大小,或者2[俄语],如果你认为强迫一个哈希函数输出 N位) ,有一个分时攻击,你预先计算的 N哈希密码,并存储在一个大表。如果对散列输出进行排序,则可以在一次查找中获得密码。彩虹桌是一种用大大减少的空间存储该表的聪明方法。您只存储 没有散列密码,并使用 O (T2)查找破解密码。彩虹表允许您虚拟地处理比您实际存储的表大得多的预计算表。

然而,无论彩虹与否,攻击者仍然必须运行完整的攻击至少一次。这可以看作是几个连续的优化层:

  1. 暴力/字典式攻击破解每个密码的成本为 N
  2. 使用预先计算好的表,攻击者支付 N 一次的成本,然后可以攻击 很多密码,每个密码只需要很小的额外成本。
  3. 如果预先计算的表是一个彩虹表,那么 N可以稍微大一些,因为 储藏室的成本降低了。N的瓶颈在于攻击者能够聚集的 CPU 能力,而不是硬盘的大小。

如果 N足够大,散列 N密码的 CPU 开销是荒谬的,那么无论是否使用彩虹表,这样的攻击都是不可行的。这意味着一个输出为80位或更多的(预像抗性)哈希函数足以使穷举法不可行。

关于盐类:

盐是打败预计算的一种方法。在上面的描述中,salt 将攻击者带回到步骤1: salting 防止攻击者在几个被攻击的密码之间共享 O (N)开销。预先计算的表,更何况彩虹表,不再可行。

你之所以要加盐,是因为当散列数据包含在 密码中时,也就是某个随机人的大脑中的数据,那么 N可能会相当低: 人类在选择和记忆密码方面真的很糟糕。这就是“字典攻击”的目的: 在假设许多用户密码将位于特定选择的空间的前提下,使用潜在密码(“字典”)的空间减少。

因此,加盐至少可以防止攻击者使用预计算表,特别是预计算彩虹表。这假设攻击者 将会是能够破解一个或两个密码; 我们不希望他以很少的额外开销破解1000个其他密码。

此外,盐有利于公共关系。

关于 SHA-1成本:

SHA-1的基本代价是散列一个64字节的块。这就是 SHA-1的工作原理: 将数据填充,然后分割成64字节的块。在 Intel Core2系统上,处理单个块的成本大约是500个时钟周期,而且是针对单个核的。MD5和 MD4更快,分别计数400和250个周期。不要忘记,大多数现代 CPU 都有几个核,因此相应地增加。

一些 Salting 方案规定使用大量的 salt; 例如,输入 hash 函数的实际上是单个128位 salt 的40000个连续副本,后面是密码本身。这使得密码散列对于合法用户和攻击者来说都更加昂贵(在我的示例中是10000倍)。这是否是一个好主意取决于设置。对于在桌面系统上登录来说,这是好事: 用户甚至不会注意到他的密码是10ms 而不是1μs; 但是攻击者的成本已经上升了非常明显的10000倍。在每秒拥有数千个客户端的共享服务器上,总成本可能变得令人望而却步。从概念上讲,为合法用户和攻击者提高同样的标准最终并不是很好的安全性; 但在某些特定情况下,这可能是一个有价值的想法。

关于网络攻击:

以上所有都是关于如何击败 离线攻击。离线攻击是指攻击者拥有他所需要的所有数据以便“测试”密码的攻击; 例如,攻击者可以获得一个保存散列密码的数据库的副本。在脱机攻击中,攻击者只受到其计算资源的限制。相反,在线攻击是一种攻击,攻击者的每次猜测都必须通过诚实的验证程序(例如,攻击者只是试图登录受攻击的系统)。通过限制每秒可以尝试多少个密码来阻止在线攻击。极端的例子是智能卡在三个错误的 PIN 码后关闭。

通常,为了密码安全,安排系统不让攻击者构建脱机攻击会带来更多好处。Unix 系统就是这样做的: 散列密码,过去在世界可读的 /etc/password文件中,现在在 /etc/shadow文件中,除了少数特权应用程序之外,/etc/shadow文件受到读访问的保护。这里的假设是,如果攻击者能够读取 /etc/shadow,那么他可能对系统有足够的控制,他不再真正需要密码了..。

以前的答案没有提到任何 GPU,它可以并行 SHA-1散列,以至于整个数据库现在可以在几分钟或几小时而不是几天或几周内被强迫,即使密码已经被盐。

现代密码哈希算法,比如 bcrypt 或 script,是专门为难以在 GPU 上运行而设计的,因为它们是具有更高内存要求的块密码(而且 GPU 中的内存访问不能并行到相同的程度)。它们还有一个“工作功能”,可以让它们随着技术的进步而变得更慢。

简而言之,你应该只使用最好的工具来完成工作。而且 SHA-1还远远达不到最先进的水平。

进一步阅读:

SHA1是一个 信息摘要,它是 永远不会意味着密码哈希(或密钥派生)功能。(尽管它可以用作 KDF 的构建块,例如在带有 HMAC-SHA1的 PBKDF2中。)

密码哈希函数应该防御字典攻击和彩虹表。一个好的密码哈希方案还应该防止攻击者通过使用 GPU、 FPGA 或 ASIC 获得优势。已经设计了几种算法来实现这些目标。

目前,最好的选择可能是 Argon2。这个密码哈希函数家族赢得了2015年的密码哈希竞赛。

如果 Argon2不可用,其他选择包括 脚本和旧的 地下室。最后,如果这些都不能使用,那么 PBKDF2仍然是一个比使用消息摘要作为密码哈希函数更好的选择,PBKDF2是一个古老的 NIST 标准。

维基百科为这些功能提供了网页:

截至2017年2月,SHA-1应该不再被认为是安全的。谷歌已经报告成功的碰撞攻击对完整的,非减少轮 SHA-1(报告链接)。对于谷歌的声明,点击这里

编辑: 正如其他人指出的,密码不容易受到散列冲突攻击。然而,作为一般指导原则,我不会选择 SHA-1用于与安全相关的应用程序。还有更好的选择。