关于加密:SHA-1对密码存储是否安全?

Is SHA-1 secure for password storage?

结论:sha-1与任何东西一样安全,但是它很容易计算,这意味着更容易安装一个野蛮或字典攻击。(对于sha-256这样的继承者也是如此。)根据具体情况,设计为计算成本较高(如bcrypt)的哈希函数可能是更好的选择。

有些人经常说"sha-1坏了"之类的话,所以我想弄明白这到底是什么意思。假设我有一个sha-1密码散列数据库,一个拥有最先进的sha-1破解算法和一个拥有100000台机器的僵尸网络的攻击者可以访问它。(拥有超过10万台家庭计算机的控制权意味着他们可以每秒进行大约10^15次操作。)他们需要多少时间

  • 找出任何一个用户的密码?
  • 找出给定用户的密码?
  • 找出所有用户的密码?
  • 想办法以用户身份登录吗?
  • 找到以特定用户身份登录的方法吗?
  • 如果密码是盐渍的,这会如何改变?盐渍的方法(前缀,后缀,两者,或更复杂的东西,如xor-ing)重要吗?

    这是我最近的理解,在谷歌搜索之后。如果我误解了什么,请在答案中更正。

    • 如果没有盐,彩虹攻击会立即找到所有密码(非常长的密码除外)。
    • 如果有足够长的随机salt,找出密码的最有效方法就是暴力或字典攻击。冲突和预映像攻击都不能帮助找到实际的密码,因此对sha-1的加密攻击在这里没有帮助。使用什么算法都不重要-甚至可以使用MD5或MD4,密码也同样安全(因为计算SHA-1哈希速度较慢,所以有一点不同)。
    • 为了评估"同样安全"的安全性,我们假设一次sha1运行需要1000个操作,密码包含大写、小写和数字(即60个字符)。这意味着攻击者可以每天测试1015*60*60*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存储密码似乎非常安全。我错过什么了吗?

    更新:马塞洛指出了一篇文章提到了2106年行动中的第二次图像前攻击。(编辑:正如托马斯所解释的,这种攻击是一种假设性的构造,不适用于现实场景。)不过,我仍然不明白使用sha-1作为关键派生函数有多危险。是否有充分的理由认为碰撞攻击或第二次图像前攻击最终会变成第一次图像前攻击?


    对你的问题的简短回答是: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字节;即一百万兆兆字节——注意106+60如何超过160;这就是权衡中没有什么魔力的地方)。好的。

    此消息的其余部分假定您使用的散列函数(例如sha-1)是一个"黑匣子",没有攻击者可能使用的特殊属性。这就是您现在所拥有的,即使使用了"坏掉的"散列函数md5和sha-1。好的。

    关于彩虹桌:好的。

    "彩虹攻击"实际上是一个字典的成本共享或蛮力攻击。它是从1980年赫尔曼首次描述的时间记忆权衡中衍生出来的。假设您有n个可能的密码(这是您的字典的大小,或者2n,如果您考虑使用n位的输出强行执行哈希函数),那么会有一个分时攻击,在这种攻击中,您预计算n个哈希密码并将其存储在一个大表中。如果对散列输出进行排序,则可以在一次查找中获取密码。彩虹桌是一种聪明的方法来存储空间大大减少的桌子。您只存储N/T散列密码,并使用O(t2)查找来破解密码。彩虹表允许您实际处理比实际存储大得多的预计算表。好的。

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

  • 暴力/字典攻击破解每个密码需要花费N。
  • 通过一个预先计算的表,攻击者只需支付一次N的费用,然后就可以用每个密码很少的额外费用攻击许多密码。
  • 如果预先计算的表是一个彩虹表,那么n可以稍微大一些,因为存储成本降低了。N上的瓶颈变成了攻击者可以聚集的CPU能力,而不是他的硬盘大小。
  • 如果n足够大以至于哈希n密码的CPU成本是荒谬的,那么这样的攻击是不可行的,不管是否使用彩虹表。这意味着输出为80位或更多的(抗预映像)哈希函数足以使暴力攻击不可行。好的。

    关于盐:好的。

    盐是一种击败预先计算的方法。在上面的描述中,salt使攻击者回到步骤1:salt防止攻击者在几个被攻击的密码之间共享O(N)成本。预计算表,fortiori彩虹表,不再可行。好的。

    你想要加盐是因为当散列的数据包含在密码中时,也就是说,一些符合随机人类大脑的东西,那么n可能很低:人类在选择和记忆密码方面真的很差。这就是"字典攻击"的目的:即在假设许多用户密码都将在这个特别选定的空间中的情况下,使用一个减少的潜在密码空间("字典")。好的。

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

    此外,腌制有利于公共关系。好的。

    关于SHA-1成本:好的。

    sha-1的基本开销是散列一个64字节的块。这就是sha-1的工作原理:数据被填充,然后分成64个字节的块。在英特尔酷睿2系统上,处理单个数据块的成本大约是500个时钟周期,这是针对单个核心的。MD5和MD4速度更快,分别为400和250个周期。不要忘记大多数现代的CPU都有几个核心,所以要相应地增加。好的。

    有些盐渍方案规定了大量的盐;例如,进入hash函数的实际上是一个128位盐的40000个连续副本,然后是密码本身。这使得合法用户和攻击者的密码散列开销更大(在我的示例中是10000倍)。这是否是一个好主意取决于设置。对于在桌面系统上登录,这是很好的:用户甚至不会注意到密码散列需要10毫秒,而不是1微秒;但是攻击者的成本增加了一个非常明显的因素10000。在每秒拥有数千个客户机的共享服务器上,总成本可能会变得令人望而却步。从概念上讲,为合法用户和攻击者提高相同的安全系数并不是很好的安全性;但在某些特定情况下,这可能是一个有价值的想法。好的。

    关于在线攻击:好的。

    所有这些都是关于击败离线攻击。离线攻击是指攻击者拥有"测试"密码所需的所有数据的攻击;例如,攻击者可以获取包含哈希密码的数据库副本。在离线攻击中,攻击者仅受其计算资源的限制。相反,在线攻击是一种攻击,攻击者的每个猜测都必须经过一个诚实的验证程序(例如,攻击者只需尝试登录受攻击的系统)。通过限制每秒可以尝试多少密码,在线攻击被阻止。极端的例子是智能卡,它在三个错误的插脚后关闭。好的。

    通常,对于密码安全性来说,安排系统不让攻击者构建离线攻击会带来更多回报。这就是Unix系统所做的:哈希密码以前在世界可读的/etc/password文件中,现在在/etc/shadow文件中,除少数特权应用程序外,该文件不受读访问保护。这里的假设是,如果攻击者可以读取/etc/shadow,那么他可能对系统有足够的控制,他不再真正需要密码了……好的。好啊。


    前面的答案没有提到GPU,它可以并行地执行sha-1散列操作,即使密码已经过盐渍处理,整个数据库现在也可以在几分钟或几小时内而不是几天或几周内被强制执行。

    现代密码散列算法(如bcrypt或scrypt)是专门为在GPU上运行而设计的,因为它们是具有更高内存需求的块密码(GPU中的内存访问不能在相同程度上并行化)。它们还有一个"工作功能",随着技术的进步,可以使它们在飞行中变慢。

    简而言之,你应该只使用最好的工具来完成这项工作。沙河一号远远落后于最先进的技术水平。

    进一步阅读:

    • https://crypto.stackexchange.com/questions/400/why-cant-one-implement-bcrypt-in-cuda
    • http://codahale.com/how-to-safety-store-a-密码/
    • http://www.codingsurror.com/blog/2012/04/speed-hashing.html
    • https://security.stackexchange.com/questions/4781/do any security expert recommended bcrypt for password storage/6415 6415


    你的描述听起来很准确,符合目前的技术水平。

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

    但是,理想情况下,您应该使用现有的密码存储原语,例如这里描述的那些原语。


    sha1是一个消息摘要,它从来就不是密码散列(或密钥派生)函数。(尽管它可以用作kdf的构建块,例如在hmac-sha1的pbkdf2中。)

    密码散列函数应该防止字典攻击和彩虹表。为了实现这一目标,设计了几种算法。

    目前,最好的选择可能是argon2。这个密码散列函数家族在2015年赢得了密码散列比赛。

    如果argon2不可用,那么唯一的标准化密码散列或密钥派生函数是pbkdf2,这是一个老式的NIST标准。其他选择,如果不需要使用标准,包括bcrypt和scrypt。

    维基百科有这些功能的页面:

    • https://en.wikipedia.org/wiki/argon2网站
    • https://en.wikipedia.org/wiki/bcrypt网站
    • https://en.wikipedia.org/wiki/scrypt网站
    • https://en.wikipedia.org/wiki/pbkdf2

    截至2017年2月,SHA-1不再被视为安全。谷歌报告称,针对完整、未减少的sha-1轮(链接至报告)的碰撞攻击取得了成功。如需谷歌的公告,请点击此处。

    编辑:正如其他人指出的,密码不易受到哈希冲突攻击。但是,作为一般准则,我不会为安全相关的应用程序选择SHA-1。有更好的选择。


    在sha-1中发现了严重的漏洞,使得搜索比暴力搜索快得多。这在很大程度上仍然是难以解决的,但预计这种情况不会持续太久;偏执的程序员喜欢来自sha-2家族的东西。

    从这篇关于2005年原始结果的文章中可以看出:

    "It's time to walk, but not run, to the fire exits. You don't see smoke, but the fire alarms have gone off."

    目前的密码分析并不是让sha-1不安全,而是加密社区担心更坏的消息可能就在眼前。这种担心也适用于sha-2,它显示出与sha-1相同的缺陷,尽管在更大的搜索空间上,因此对sha-3的持续探索。

    简言之,sha-1目前是安全的,可能会有一段时间,但加密社区对预后不满意。


    如果您存储了salted密码,那么sha-1就可以用于实际目的。sha-2被认为更安全,但是sha-1不是一个问题,除非你有理由真正偏执。

    以下是NIST的说法:

    The results presented so far on SHA-1
    do not call its security into
    question. However, due to advances in
    technology, NIST plans to phase out of
    SHA-1 in favor of the larger and
    stronger hash functions (SHA-224,
    SHA-256, SHA-384 and SHA-512) by
    2010.