SHA-1是否可以保存密码?

结论: SHA-1与任何对付原像攻击的攻击一样安全,但它易于计算,这意味着安装暴力破解或字典攻击更容易。 (对于像SHA-256这样的后继者也是如此)。根据具体情况,被devise为计算成本高昂的散列函数(比如bcrypt)可能是更好的select。


有些人大肆宣传“SHA-1已经破产”这样的言论,所以我试图去理解这个意思。 假设我有一个SHA-1密码哈希数据库,攻击者使用最新的SHA-1破解algorithm和一个拥有100,000台计算机的僵尸networking访问它。 (控制10万台家用电脑就意味着他们每秒可以做10 ^ 15次左右的操作。)他们需要多less时间

  1. 找出任何一个用户的密码?
  2. 找出给定用户的密码?
  3. 找出所有用户的密码?
  4. find一种方式作为用户之一login?
  5. find一种方式作为特定的用户login?

如果密码被腌制,这个变化如何? 腌制的方法(前缀,后缀,两者,还是像xor-ing更复杂的东西)的问题?

这是我目前的理解,一些谷歌search。 如果我误解了某些东西,请在答案中予以纠正。

  • 如果没有盐,彩虹攻击会立即find所有的密码(除了非常长的密码)。
  • 如果有足够长的随机盐,找出密码的最有效的方法是暴力或字典攻击。 冲突和原像攻击都不能帮助find真正的密码,所以对SHA-1的encryption攻击在这里没有任何帮助。 甚至使用什么algorithm都不算什么 – 甚至可以使用MD5或MD4,密码也是一样安全的(因为计算SHA-1散列速度较慢,所以稍有不同)。
  • 为了评估“同样安全”的安全性,我们假设一次sha1运行需要1000次操作,并且密码包含大写,小写和数字(即60个字符)。 这意味着攻击者每天可以testing10 15 * 60 * 60 * 24/1000〜= 10 17的潜在密码。 对于暴力攻击,这意味着要在3个小时内testing所有密码,最多9个字符,一周最多10个字符,一年最多11个字符。 (每增加一个字符,就要花费60倍)字典攻击要快得多(甚至一台计算机的攻击者可能会在几个小时内就把它拉出来),但是只能find弱密码。
  • 要以用户身份login,攻击者不需要find确切的密码; find一个导致相同散列的string就足够了。 这被称为第一次原像攻击。 据我所知,没有对SHA-1的原像攻击。 (暴力攻击需要2 160次操作,这意味着我们的理论攻击者需要10年30年的时间才能完成,理论可能性的限制大约是60次 ,攻击将需要几年时间)。 对减less的SHA-1版本的影响可以忽略不计(对于减less的SHA-1使用44步而不是80步,攻击时间从2 160次降到2 157次 )。 对SHA-1的碰撞攻击在理论上是可能的( 我发现的最好的结果是从2 80到2 52 ),但是对于密码哈希值,即使没有腌制,也是无用的。

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

更新: Marcelo指出了一篇文章,其中提到了2 106次操作中的第二次原像攻击 。 ( 编辑:正如托马斯解释 ,这种攻击是一个假设的构造,不适用于现实生活中的场景)。但我仍然不明白这是如何使用SHA-1作为密钥派生函数的危险。 是否有足够的理由认为碰撞攻击或第二次原像攻击最终可能会变成第一次原像攻击?

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

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

关于已知的攻击:

对MD4,MD5和SHA-1的已知攻击是关于碰撞,这不会影响前像抵抗。 已经certificate,MD4有一些弱点,当试图破坏HMAC / MD4时可能(只在理论上)被利用,但这不适用于你的问题。 Kesley和Schneier在文章中的第二次1061原像攻击是一个通用的权衡,它只适用于非常长的input(2 60字节;这是一百万太字节 – 注意到106 + 60超过了160;这是你看到的地方这个交易没有什么魔力)。

这个消息的其余部分假定你使用的散列函数(如SHA-1)是一个“黑匣子”,攻击者可以使用它没有特殊的属性。 这就是你现在即使使用“破碎”哈希函数MD5和SHA-1。

关于彩虹桌:

“彩虹攻击”实际上是字典或蛮力攻击的费用分摊。 它是1980年由Hellman首先描述的时间 – 内存折衷的一个衍生。假设你有N个可能的密码(这是你的字典的大小,或者2 n,如果你考虑使用输出的哈希函数n位),则存在分时攻击,您可以预先计算N个散列密码并将其存储在一个大表中。 如果您对散列输出进行sorting,则可以通过单个查找来获取密码。 彩虹桌是一个聪明的方式来存储该表的空间大大减less。 您只存储N / t哈希密码,并用O( t 2 )查找破解密码。 彩虹表让您可以虚拟处理比您实际存储的预计算表格大得多的表格。

但是,不pipe是否彩虹,攻击者至less还要进行一次全面攻击。 这可以被看作几个连续的优化层:

  1. 蛮力/字典攻击已经花费N破解每个密码。
  2. 使用预先计算的表格,攻击者支付一次 N的费用然后可以以很小的额外成本密码攻击许多密码。
  3. 如果预先计算的表是一个彩虹表,那么N可能稍大,因为存储成本降低。 N上的瓶颈就成了攻击者所能掌握的CPU能力,而不是硬盘的大小。

如果N足够大,散列N个密码的CPU代价是可笑的,那么不pipe是否使用彩虹表,这样的攻击都是不可行的。 这意味着输出80位或更多的(抗原像)散列函数足以使暴力攻击不可行。

关于盐:

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

你想要腌制,因为当散列数据包含在密码中时 ,即在随机的人的大脑中的东西,那么N可以是相当低的:人类在select和记忆密码方面真的很差。 这就是“字典攻击”的意义所在:在假设许多用户密码将在特定select的空间中的情况下,使用潜在密码的缩小空间(“字典”)。

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

另外,腌制对公共关系也有好处。

关于SHA-1成本:

SHA-1的基本成本是散列一个64字节块。 这就是SHA-1的工作原理:数据被填充,然后分成64字节块。 处理单个模块的成本在Intel Core2系统上大约为500个时钟周期,这是单核的。 MD5和MD4速度更快,分别计数约400和250个周期。 不要忘记,大多数现代的CPU有几个核心,所以相应的乘法。

一些腌制scheme规定了巨大的盐; 例如什么进入散列函数实际上是一个单一的128位盐的40000个连续副本,其次是密码本身。 这使得密码哈希值对于合法用户和攻击者来说都更昂贵(以我的例子来说是10000倍)。 这是否是一个好主意取决于设置。 对于在桌面系统上login,这是很好的:用户甚至不会注意到花了10ms来密码,而不是1μs; 但攻击者的成本已经上升了一个非常明显的因素10000.在每秒数千客户端的共享服务器上,总成本可能会变得过高。 从概念上说,对合法用户和攻击者提高标准并不是最终的好处。 但在某些特定的情况下,这可能是一个值得的想法。

关于在线攻击:

以上所有内容都是关于打败离线攻击。 离线攻击是攻击者为了“testing”密码而拥有所有他需要的数据的攻击; 例如,攻击者可以得到一个拥有散列密码的数据库副本。 在离线攻击中,攻击者仅受其计算资源的限制。 相反, 在线攻击是一种攻击,攻击者的每个猜测必须经过一个诚实的validation者(例如,攻击者只是试图login被攻击的系统)。 通过强制限制每秒可以尝试多less个密码来阻止在线攻击。 极端的例子是三个错误的PIN码后closures的智能卡。

通常,对于密码安全性来说,安排系统不要让攻击者构build离线攻击就更有价值。 这就是Unix系统所做的事情:曾经是世界可读/etc/password文件的哈希密码现在位于/etc/shadow文件中,除了less数特权应用程序之外,它们受保护,不受读访问限制。 这里的假设是,如果攻击者可以读取/etc/shadow ,那么他可能对系统有足够的控制,以至于他不再需要密码了。

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

像bcrypt或scrypt这样的现代密码哈希algorithm被devise成特别难以在GPU上运行,因为它们是具有更高内存要求的块密码(并且GPU中的存储器访问不能并行地达到相同的程度)。 他们也有一个“工作职能”,使他们可以随着技术的进步而变慢。

总之,你应该只使用最好的工具来完成这项工作。 而SHA-1落后于现有技术。

进一步阅读:

您的描述听起来对于当前的艺术状态是准确的。

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

但是,理想情况下,您应该使用现有的密码存储原语,如此处所述。

SHA1是一个消息摘要 ,它从来没有被认为是密码哈希(或密钥派生)函数。 (虽然它可以用于KDF的构build块,比如在带有HMAC-SHA1的PBKDF2中)。

密码散列函数应该防御字典攻击和彩虹表。 已经devise了几种algorithm来实现这个目标。

目前,最好的select可能是Argon2 。 这个密码散列函数系列在2015年赢得了密码散列比赛。

如果Argon2不可用,唯一的其他标准密码哈希或密钥派生函数是PBKDF2 ,这是一个古老的NIST标准。 其他select,如果使用标准是不需要的,包括bcryptscrypt

维基百科有这些function的页面:

在SHA-1中发现了严重的漏洞,这使得search比暴力更快。 这仍然是很难处理的,但预计情况不会持续太久。 偏执的程序员喜欢SHA-2家族的东西。

从这篇关于2005年原始结果的文章 :

“现在是时候行走了,但不能跑到火口,你看不到烟,但是火警已经熄灭了。

目前的密码分析并不是说SHA-1不安全,而是密码社区担心更糟的消息可能就在眼前。 这种恐惧也适用于SHA-2,虽然在更大的search空间上,SHA-2performance出与SHA-1相同的缺陷,因此对SHA-3进行持续的追求。

总而言之,SHA-1现在是安全的,可能还会有一段时间,但是密码社区对预后感到不舒服。

截至2017年2月,SHA-1不再被视为安全。 谷歌已经报告了对全面,非简化的SHA-1( 链接到报告 )的碰撞攻击的成功。 有关Google的声明, 请点击此处 。

编辑:正如别人指出的,密码不容易受到哈希碰撞攻击。 然而,作为一般指导原则,我不会selectSHA-1作为安全相关的应用程序。 那里有更好的select。

如果你存储了腌制的密码,SHA-1在实际应用中是很好的。 SHA-2被认为更安全,但SHA-1不是一个问题,除非你有一个真正的偏执的理由。

这就是NIST 所说的 :

迄今为止在SHA-1上提出的结果并不把它的安全问题称为问题。 然而,由于技术的进步,NIST计划到2010年逐步淘汰SHA-1,以利用更大更强大的散列函数(SHA-224,SHA-256,SHA-384和SHA-512)。