【问题标题】:is there a way to reverse a hash without rainbow tables? [duplicate]有没有办法在没有彩虹表的情况下反转哈希? [复制]
【发布时间】:2011-11-23 07:54:55
【问题描述】:

可能重复:
md5 decoding. How they do it?

this page 建议由于我们现在拥有的巨大处理能力,可以反转像 md5() 和 sha1() 这样的哈希算法。在这一点上,我认为只有 Rainbow Tables 才有可能。我错了吗?

如果 Rainbow Tables 是唯一的出路,那么有人如何反转用盐制成的哈希?

【问题讨论】:

  • 不准确。 md5 和 sha1 不是一对一的。这就是哈希与加密的区别。你无法反转算法,但你可以找到另一个输入,它会给你相同的结果
  • 加盐是为了确保散列之前的值不是彩虹表将包含的标准值
  • 如果你用谷歌搜索这样的 md5:73868cb1848a216984dca1b6b0ee37bc 你会得到一些 md5 破解网站
  • 盐还用于“加强”哈希以抵抗蛮力或彩虹表攻击。如果用户拥有密码“test”,但您添加了盐“yT8cpj^34”,那么他们现在会从一个不可接受的短密码变为更安全的密码,然后再进行哈希处理。
  • 盐的价值不在于它使密码更长!就是它在散列之前添加到文本中,这需要一个新的彩虹表。在@tttony 的示例中,我们知道MD5("stackoverflow") = 73868cb1848a216984dca1b6b0ee37bc,但我们不仅需要碰撞,还需要以盐开始(或以盐结束或以其他方式混合)的碰撞。

标签: php security hash rainbowtable password-hash


【解决方案1】:

首先,一般来说,不可能“反转”加密哈希函数。这是因为这些函数通常需要比输出更多的输入数据。

例如,MD5 采用 512 位输入(64 字节)并产生 128 位输出(16 字节)。因此,输入中根本没有足够的信息来重建输出。事实上,大约有 2^384(一个真正很大的数字)具有完全相同的输出哈希的不同输入。

相反,密码学家谈论了三种不同类型的哈希攻击:

  • 第一次原像攻击:给定一个哈希 h,找到 any 消息 m 使得 hash(m) = h
  • 第二次原像攻击:给定一条固定消息 m1,找到任何其他消息 m2,使得 hash(m1) = hash(m2)
  • 碰撞攻击:找到任意两条消息 m1 和 m2 使得 hash(m1) = hash(m2)

现在回到这个“逆转”业务。当你想“破解一个 MD5 密码”时,你真正想做的是第一次原像攻击:找到 any “密码” m 使得 hash(m) 匹配存储的哈希 h。通常这需要通过蛮力进行大约 2^128 次猜测(比地球上所有计算机在一个世纪内所能处理的还要多)。 MD5 中存在已知的弱点,将其降低到 ~2^123,这仍然太难以实用。

但由于密码通常是由字母和数字组成的短字符串,因此人们实际上可能使用的密码远少于 2^128 个。更像是 2^40(即大约一万亿)。这仍然很多,但如果你有一年左右或很多 PS3,就不可能全部尝试。但是,如果您知道要破解大量密码怎么办?您可以将所有可能密码的哈希值存储在磁盘上以备将来使用,而不是每次进行 2^40 次猜测。这(或多或少)是彩虹表:有人已经完成了所有工作,因此您只需查找答案并跳过大部分工作。

你是对的,使用盐会破坏这一点。现在你又回到了 2^40 次猜测和满屋的 PS3。使用更好的哈希函数(如 SHA512 或 SKEIN)并不会真正改变这一点,因为它不会改变您需要尝试的可能密码的数量。教训:你需要使用一个很难猜到的密码!

好的,但 MD5 和 SHA1 是否仍被视为已损坏?是的,但不是在这里(还)真正重要的方式。该领域令人振奋的消息都是关于冲突攻击,这与破坏部分 SSL 安全性和数字签名有关,但与破坏存储的密码无关。密码学家预计这项工作很快就会导致更好的攻击,因此在新程序中使用 MD5 或 SHA1 可能不是一个好主意,但使用 MD5/SHA1 + 适当的加盐来存储密码的程序仍然可以。

【讨论】:

    【解决方案2】:

    嗯,这个问题通常与This Question 重复。但是,要回答您的确切问题:

    在这一点上,我认为只有 Rainbow Tables 才有可能。我错了吗?

    从技术上讲,是的,你错了。只要有足够的处理能力,没有哈希函数是不可恢复的。关键是它需要多少处理能力,在大多数情况下,这远远超出你的想象。原因是可能值的数量在散列周期的每个阶段呈指数增长。对于 MD5,每个阶段(有 64 个)会将可能性的数量乘以 10^77(很多零)。因此,要成功反转 MD5,您必须尝试 真正 大量可能的排列(信封后计算显示大约 10^4932 次尝试)。使用当今创造的最快的超级计算机(大约 8 petaflops,或每秒 8x10^15 次浮点运算),您需要大约 10^4908 来扭转它。顺便说一下,现在是宇宙年龄的 2.5x10^4898 倍。真的,这是一个超出我们人类理解能力的庞大数字......

    这绝对是最好的情况。

    所以技术上是可以逆转的。但实际上,不,不是。

    如果 Rainbow Tables 是唯一的出路,那么有人如何反转用盐制成的哈希?

    问题是没有人需要来扭转它。他们只需要找到一个碰撞。基本上,冲突是导致相同输出的两个输入。所以如果hash(a) = xhash(b) = xab 是相互冲突的。所以,我们需要做的就是找到一个冲突(不管你信不信,这比找到确切的输入更容易,因为从技术上讲,有无限数量的输入可以提供特定的输出)。输入密码的大小,通常碰撞的是原始密码。

    找到这种冲突的最简单方法是使用预先计算的哈希列表(通常称为彩虹表)。基本上,您需要做的就是查找表中的哈希值,看看是否有原始值。如果是这样,你就完成了(就这么简单)。

    盐通常用于对抗彩虹桌。这是因为如果用户输入1234 作为他们的密码,并且您使用abcdefghijklmnop 作为盐,那么原始值将是1234abcdefgjhijklmnop,它出现在彩虹表中的可能性要小得多。因此,添加强盐可以防止预计算彩虹表。

    暴力破解

    但是,如果您只执行hash(pass + salt),则存在重大问题。它不易受预先计算的彩虹表的影响,但易受暴力破解的影响。原因是加密散列函数(如 sha1、md5、sha256 等)被设计为快速。他们的传统角色是Signing,所以他们需要快速才能有用。但是,在密码存储中,这是弱点。使用现代 GPU,攻击者可以在几个小时内暴力破解(尝试所有可能的密码排列)一个简单的盐哈希(有关更多详细信息,请参阅我的 blog post)...

    最好的预防

    最好的预防有两个特点:

    1. 预先计算值表(彩虹表)并不容易

    2. 散列单个值并不快(不容易暴力破解)。

    事实证明,有一种使用哈希函数的简单方法。简单地对其进行迭代并使输出依赖于大量的哈希函数:

    var result = password + salt;
    for (var i = 0; i < 10000000; i++) {
        result = hash(result + salt);
    }
    

    关键在于,通过人为地减慢速度并使用盐,您可以使其抵抗预计算和暴力破解。

    事实证明,有 2 种标准算法可以做到这一点(好吧,使用原理)。

    最好的是 Blowfish 散列 (bcrypt),它并不真正使用散列原语函数,而是使用 Blowfish 密码的密钥派生循环。它可以通过crypt() 在 PHP 中使用。要使用它:

    $hash = crypt($password, '$2a$07$' . $salt . '$');
    

    并用

    验证它
    $hash == crypt($password, $hash);
    

    另一种方法(不太受欢迎)是PBKDF2。用 PHP 编程:

    function pbkdf2($hashFunc, $password, $salt, $iterations, $length = 32) {
        $size   = strlen(hash($hashFunc, '', true));
        $len    = ceil($length / $size);
        $result = '';
        for ($i = 1; $i <= $len; $i++) {
            $tmp = hash_hmac($hashFunc, $salt . pack('N', $i), $password, true);
            $res = $tmp;
            for ($j = 1; $j < $iterations; $j++) {
                $tmp  = hash_hmac($hashFunc, $tmp, $password, true);
                $res ^= $tmp;
            }
            $result .= $res;
        }
        return substr($result, 0, $length);
    }
    

    注意:

    这些都不能保护用户免受非常弱密码的影响。如果他们输入字典单词或通用密码,攻击者仍有可能破解它。然而,它们将增加对中等强度密码的防御......

    更多阅读:

    【讨论】:

    • @ircmaxwell :你说哈希函数是可逆的。这怎么可能?多个字符串可以生成相同的哈希,因为哈希的输出是固定的(至少在 md5 中),但输入可以任意大。你怎么知道产生哈希的字符串是哪个?
    【解决方案3】:

    从技术上讲,任何标准哈希算法都是不可逆的!因此,一旦您获得消息的哈希,就应该无法从其哈希字符串中获取原始消息。人们试图破解它的唯一方法是使用蛮力攻击。暴力破解是你能做的最愚蠢的事情,尝试所有可能的密钥!这就解释了为什么安全密码算法的特征之一是拥有大的密钥空间。但是,如果您在某些情况下使用该过程,它可能是实用的,这正是彩虹表的作用。

    彩虹表是针对所有可能组合的预先计算的表,最长可达一定长度。这意味着您可以创建字符(大写和小写)、数字和特殊字符的所有可能组合,直到一定长度。据我所知,最完整的彩虹表可以破坏最多 10 个字符的字符串散列,其中包括数字、大写和特殊字符,因此,如果您的字符串长于该长度,则不应该担心破坏散列本身的任何安全问题。正如您所看到的here,最多可以破解 8 个字符的 vista 密码的表的大小超过 100GB,而且这个数字呈指数增长,这使得不可能再超过 10 或 12 个字符。

    只要你的字符串不容易被猜到,足够长并且包含大写字母、数字和特殊字符,就不用担心:)

    【讨论】:

      【解决方案4】:

      也许您可以使用以下攻击,采用用于制作哈希的技术是一个简单的计算。

      例如,如果使用 100 的模散列进行计算,我们有:

      示例输入: 8379547378 输出哈希: 78

      哈希值 78 的一般公式是 78 +100*k(k 个属于整数)。因此,可以尝试所有可能的序列。请注意,这会将搜索空间从 100% 减少到 1%,在这种情况下是模块 100。如果可以建立这个数字是 10 位的预感,我们可以使搜索进一步减少到 78 +100 k (10 ^7

      另一种方法是用许多非常棒的哈希值及其入口填充数据库,然后在这个数据库中搜索。

      希望我能帮上一点忙。

      【讨论】:

        【解决方案5】:

        彩虹表“只是”一个预先计算的散列值的大表,其中包含一些技巧来仅存储表的一小部分并且仍然能够查找所有值。详细地说,可以“反转”N 个可能值的彩虹表(即有 N 个哈希输出,该表将为其产生相应的输入)需要大约 N 个哈希输出em>1.7*N 来构建 - 所以构建表实际上 比“只是”尝试 N 输入并查看是否匹配给定哈希输出。表格的优势是当您有 几个 散列输出并希望为其找到匹配的输入时。

        【讨论】:

        • 但是既然我的盐可以是任何东西,我可以以我想要的疯狂方式将它推入我的字符串,为什么有人只是猜测输入?我的盐可能是“$%$@%*&¨%$GFNGBFDSGBTDY$@$%Kyhrdgrsgfds\f\+9ds851496s516”并推到第四个字母的前面。它不是让我的 sha1() 足够安全吗?这不是要花几千年才能猜到吗?
        • 因为盐值的安全性是建立在对盐值保密的基础上的。如果盐被泄露,理论上,有可能让计算机进行暴力攻击,测试组合,直到它们命中生成相同哈希键的组合。因此,仅当盐值在物理上得到保证时,盐才有帮助。但在使用 javascript 或 php 等脚本语言编写的程序中,加密并不容易,因此任何可以访问源代码的人都会知道 salt 值。
        • 盐不需要保密,只要用于创建哈希的算法是强大的。当然,如果知道盐,暴力破解会更容易,但只要你使用强大的算法,它仍然很困难。如果您依靠盐的保密性来保护哈希,那么当秘密泄露时您就有麻烦了......
        【解决方案6】:

        该页面正在讨论的暴力破解基本上是动态生成彩虹表。

        【讨论】:

        • 但有人怎么能这样做呢?我看不到不需要数千年才能做到这一点的方法=/
        猜你喜欢
        • 2017-07-16
        • 1970-01-01
        • 2020-12-20
        • 2016-05-27
        • 2016-07-27
        • 1970-01-01
        • 2016-01-10
        • 2016-01-19
        • 1970-01-01
        相关资源
        最近更新 更多