【问题标题】:Why is it not possible to reverse a cryptographic hash?为什么无法反转加密哈希?
【发布时间】:2011-09-30 00:53:58
【问题描述】:

为什么不能像反转数学函数一样反转算法?怎么可能做出不可逆的算法?

如果你使用彩虹桌,是什么让使用盐无法破解它?如果您正在使用蛮力制作彩虹表来生成它,那么它会发明每个可能的明文值(到一定长度),最终将包括每个可能密码和每个可能盐的盐(盐和密码/文本将只是作为一个单一的文本组合在一起)。

【问题讨论】:

  • 查看关于cartographic hashes的维基百科文章
  • @mru:制图哈希?你的意思是像地理散列?
  • @Nemo aeh 错字,我不能再编辑我的评论了。我的意思是加密:/至少链接是正确的
  • 听说hash很难破解是因为CPU的限制。每次出现更好的 CPU 时,它都可以计算出更高的素数。因此,通过将巨大的素数相乘,得到一个大数,将需要一个更快(不存在)的 CPU 来破译它。这是一个循环游戏,每当 CPU 强大到足以破解旧哈希时,它同时强大到足以创建无法破解的哈希。

标签: hash cryptography md5 cryptographic-hash-function reversing


【解决方案1】:

MD5 设计为cryptographically irreversible。在这种情况下,最重要的属性是在计算上找到哈希的反向是不可行的,但是很容易找到任何数据的哈希。例如,让我们考虑只对数字进行操作(毕竟二进制文件可以解释为一个很长的数字)。

假设我们有数字“7”,我们想要获取它的哈希值。也许我们作为散列函数尝试的第一件事是“乘以 2”。正如我们将看到的,这不是一个很好的散列函数,但我们会尝试一下,以说明一点。在这种情况下,数字的哈希值将是“14”。这很容易计算。但是现在,如果我们看看扭转它有多难,我们会发现它也一样容易!给定任何哈希值,我们只需将其除以 2 即可得到原始数字!这不是一个好的哈希,因为哈希的全部意义在于计算逆比计算哈希要困难得多(至少在某些情况下,这是最重要的属性)。

现在,让我们尝试另一个哈希。对于这一点,我将不得不介绍时钟算法的概念。在时钟上,没有无限数量的数字。事实上,它只是从 0 到 11(请记住,时钟上的 0 和 12 是相同的)。因此,如果您在 11 上“加一”,您将得到零。您可以将乘法、加法和求幂的概念扩展到时钟。例如,8+7=15,但时钟上的 15 真的只是 3!所以在时钟上,你会说 8+7=3! 6*6=36,但在时钟上,36=0!所以 6*6=0!现在,对于权力的概念,你可以做同样的事情。 2^4=16,但 16 就是 4。所以 2^4=4!现在,这是它与散列的关系。我们试试散列函数 f(x)=5^x 怎么样,但是使用时钟算法。正如您将看到的,这会导致一些有趣的结果。让我们尝试像以前一样取 7 的哈希值。

我们看到 5^7=78125,但在时钟上,这只是 5(如果你算一下,你会发现我们已经在时钟上绕了 6510 次)。所以我们得到 f(7)=5。现在,问题是,如果我告诉你我的号码的哈希是 5,你能算出我的号码是 7 吗?嗯,在一般情况下,实际上很难非常计算这个函数的倒数。比我聪明得多的人已经证明,在某些情况下,反转这个函数比向前计算要困难方式(编辑:Nemo 指出这实际上还没有被“证明”;事实上,你得到的唯一保证是很多聪明人已经尝试了很长时间来找到一种简单的方法,并且没有一个成功。) 反转这个操作的问题被称为“Discrete Logarithm Problem”。查找它以获得更深入的报道。这至少是 good 散列函数的开始。

对于现实世界的哈希函数,想法基本相同:您会发现一些难以反转的函数。比我聪明得多的人设计了 MD5 和其他哈希值,使它们很难被证明是逆向的。

现在,您可能更早地想到了:“计算倒数很容易!我只需对每个数字进行哈希处理,直到找到匹配的那个!”现在,对于数字都小于十二的情况,这将是可行的。但是对于现实世界的哈希函数的模拟,想象所有涉及的数字都是巨大的。这个想法是,计算这些大数的散列函数仍然相对容易,但是搜索所有可能的输入变得更快更难。但是您偶然发现的仍然是一个非常重要的想法:在输入空间中搜索将提供匹配输出的输入。彩虹表是这个想法的一个更复杂的变体,它以智能的方式使用预先计算的输入输出对表,以便快速搜索大量可能的输入。

现在假设您正在使用哈希函数在您的计算机上存储密码。这个想法是这样的:计算机只存储正确密码的哈希值。当用户尝试登录时,您将输入密码的哈希值与正确密码的哈希值进行比较。如果它们匹配,则假定用户具有正确的密码。这是有利的原因是因为如果有人窃取了您的计算机,他们仍然无法访问您的密码,只能访问它的哈希值。因为哈希函数是由聪明人设计的,很难反其道而行之,所以他们不能轻易地从中取回您的密码。

攻击者的最佳选择是暴力攻击,他们会尝试使用一堆密码。就像您可能会尝试上一个问题中小于 12 的数字一样,攻击者可能会尝试所有仅由长度小于 7 个字符的数字和字母组成的密码,或者字典中出现的所有单词。这里重要的是他不能尝试所有可能的密码,因为有太多可能的16字符密码,例如,永远测试。因此,关键是攻击者必须限制他测试的可能密码,否则他将永远不会检查其中的一小部分。

现在,至于盐,想法是这样的:如果两个用户有相同的密码怎么办?它们将具有相同的哈希值。如果您考虑一下,攻击者实际上并不需要单独破解每个用户的密码。他只是简单地检查所有可能的输入密码,并将哈希值与所有哈希值进行比较。如果它与其中一个匹配,那么他已经找到了一个新密码。我们真正想要强迫他做的是为他想要检查的每个用户+密码组合计算一个新的哈希值。这就是盐的想法,就是你让每个用户的哈希函数略有不同,所以他不能为所有用户重用一组预先计算的值。最直接的方法是在获取哈希之前为每个用户的密码添加一些随机字符串,其中每个用户的随机字符串不同。因此,例如,如果我的密码是“shittypassword”,我的哈希可能会显示为 MD5(“6n93nshittypassword”),如果您的密码是“shittypassword”,那么您的哈希可能会显示为 MD5(“fa9elshittypassword”)。这一点“fa9el”被称为“盐”,每个用户都不同。例如,我的盐是“6n93n”。现在,附加在您密码上的这一点也只是存储在您的计算机上。当您尝试使用密码 X 登录时,计算机可以计算 MD5("fa9el"+X) 并查看它是否与存储的哈希匹配。

所以登录的基本机制保持不变,但对于攻击者来说,他们现在面临着更艰巨的挑战:他们面临的不是 MD5 哈希列表,而是 MD5 和和盐的列表。他们基本上有两种选择:

  1. 他们可以忽略哈希被加盐的事实,并尝试使用他们的查找表来破解密码。但是,他们实际破解密码的可能性大大降低。例如,即使“shittypassword”在他们要检查的输入列表中,很可能“fa9elshittypassword”不在。为了使破解密码的概率达到他们之前的一小部分,他们需要测试更多可能的密码数量级。

  2. 他们可以根据每个用户重新计算哈希值。因此,他们不是计算 MD5(passwordguess),而是为每个用户 X 计算 MD5(Salt_of_user_X + passwordguess)。这不仅迫使他们为他们想要破解的每个用户计算一个新的哈希值,而且最重要的是,它阻止了他们使用预先计算好的表(例如彩虹表),因为他们不知道什么Salt_of_user_X 在手头,因此他们无法预先计算要测试的哈希值。

因此,基本上,如果他们尝试使用预先计算的表格,那么有效地使用盐会大大增加他们为了破解密码而必须测试的可能输入,即使他们没有使用预先计算的表格,它仍然会使它们减慢 N 倍,其中 N 是您存储的密码数量。

希望这能回答你所有的问题。

【讨论】:

  • 哇,这些都是你自己写的吗?还是你抄的?那是相当长。我现在就继续阅读。哈哈。谢谢!
  • 好的,我读了。忽略我上面写的。这是我的新信息:哇,这是一个超级长的事情。是的,我相信你确实回答了我所有的问题。但是对于 MD5 来说,是获取每个字母并将其转换为数字,然后执行一些复杂的数学算法吗?另外,我认为盐对每个用户来说都是一样的。因为(请查看我对 Flyff 体验的不同答案的其他评论),他们使用了一种盐,“kikugalanet”。另外,我不明白,如果每个人都有自己的盐,它怎么知道用什么盐。如果那是存储在数据库中的,黑客不能随便使用..
  • ...在为一个人生成蛮力时也是如此(如果他们访问了整个密码数据库)?非常感谢您花这么多时间写这篇文章!
  • 1.是的,我自己写的。有时我只是有心情写长篇大论。它有助于我自己更好地理解它们。 2. 是的,MD5 将每个字母解释为一个数字(实际上,它基本上只是从字母=>ascii 码进行转换。3. 盐可以保持不变,但没有那么强大一种保护技术,如每用户加盐。如果您为整个网站使用一个盐,它会阻止预先计算的表有效地处理哈希,但它仍然允许攻击者使用 every 测试相同的密码用户一次。所以你不会得到额外的减速
  • 因此,每个网站的加盐基本上意味着您正在为您的网站使用独特的哈希函数,因此它们不能重用其他表。然而,每用户加盐意味着你给每个用户他们自己的哈希函数,所以攻击者必须为他想要的每个用户投入大量额外的工作裂缝。至于存储盐,是的,您必须将其与哈希一起存储在数据库中。因此,如果黑客有哈希值,他就有了盐。然而,关键是他在得到盐之前不能预先计算任何东西。每个用户或每个网站的盐都可以有效地阻止这种情况。
【解决方案2】:

想出从 1 到 9999 的 2 个数字。将它们相加。现在告诉我最后一个数字。

我无法从这些信息中推断出您最初想到的数字。这是一个非常简单的单向哈希示例。

现在,我可以想出两个给出相同结果的数字,这就是这个简单示例与 MD5 或 SHA1 等“正确”加密哈希的不同之处。使用这些算法,想出一个产生特定散列的输入在计算上应该是困难的。

【讨论】:

  • 哇,现在我明白了。这是一种非常好的和简单的表达方式。谢谢!
【解决方案3】:

您无法反转哈希函数的一个重要原因是数据丢失。

考虑一个简单的示例函数:'OR'。如果将其应用于 1 和 0 的输入数据,它会产生 1。但是现在,如果您知道答案是“1”,那么如何回退原始数据?你不能。可能是 1,1,也可能是 0,1,或者可能是 1,0。

至于盐渍桌和彩虹桌。是的,理论上,您可以拥有一个包含所有可能的盐和密码的彩虹表,但实际上,这太大了。如果您尝试了小写字母、大写字母、数字和 12 个标点符号的所有可能组合,最多 50 个字符,则有 (26+26+10+12)^50 = 2.9 x 10^93 种不同的可能性。这比可见宇宙中的原子数量还要多。

彩虹表背后的想法是提前计算一堆可能的密码的哈希值,而密码比 50 个字符短得多,所以这样做是可能的。这就是为什么要在前面添加盐的原因:如果在密码前面添加“57sjflk43380h4ljs9flj4ay”。虽然有人可能已经计算出“pa55w0rd”的哈希值,但没有人会计算出“57sjflk43380h4ljs9flj4aypa55w0rd”的哈希值。

【讨论】:

  • 哇,我明白了。我习惯于看到盐(对于一个名为 Flyff 的 MMO,我曾经为了好玩而花一些时间做私人服务器工作)超级短,就像 Flyff 是相对短的“kikugalanet”。但是感谢有关制作长且完全随机的哈希的提示。关于数据如何丢失的答案的第一部分,我仍然有点困惑。如果它是 1 或 0 中的任何一个,它如何匹配散列?不过,感谢您的出色回答!
【解决方案4】:

我不认为 md5 能给你完整的结果 - 所以你不能向后工作来找到 md5-ed 的原始东西

【讨论】:

  • 就算是1对1,倒也不一定容易。考虑取两个大素数的乘积,例如...... MD5 很难反转,但它与多对一无关。
【解决方案5】:

md5 是 128bit,即 3.4*10^38 组合。

八字长密码总数:

  • 仅小写字符和数字:36^8 = 2.8*10^12
  • 大小写和数字:62^8 = 2.18*10^14

您必须为密码存储 8 个字节,为 md5 值存储 16 个字节,即每个条目总共 24 个字节。

因此,您的彩虹桌需要大约 67000G 或 5200000G 的存储空间。 实际上可以找出密码的唯一原因是人们使用显而易见的密码。

【讨论】:

  • 不完全。这就是您必须预先计算的数据量。彩虹表不是一个简单的查找表。关键是它是时间和空间存储之间的权衡。因此,例如,如果您有长度为 1,000,000 的链,它将占用您建议的空间的 1,000,000 倍,但需要的时间是简单查找的 1,000,000 倍(这仍然相对较快)。对于您上面引用的数字,那将只有 67 MB 或 5.2 GB。还不错吧?但同样,有两个警告:1. 计算表格的时间仍然很长 2.(续)
  • 2.彩虹表实际上是统计的。所以你不会得到 any 密码是“小写和大写和数字”,而是统计它们的百分比,比如 99.8 或其他东西,这取决于减少函数冲突的可能性,大小填充你给彩虹表,您希望它们需要多大才能获得更好的概率。
  • 是的,我的意思是链接,但是不,您不需要存储每个密码。这个想法是你有一个归约函数,它接受一个散列输出并将其带回密码域。所以对于每个链,我存储(初始密码,最终哈希)现在,如果链的长度为 1,000,000,这意味着最终哈希是我在获取哈希然后连续减少函数 1,000,000 次后得到的。现在,为了检查密码,我将哈希值与每条链的末尾进行比较。如果没有,我会减少哈希,然后再次哈希,再次比较,等等,最多 1,000,000 次。
  • 如果在任何时候我在其中一个链上得到匹配,那么我从该链的初始密码开始,并继续获取哈希,然后是归约函数,直到找到匹配的哈希我正在寻找的 original 哈希。现在我只记得我提供给哈希函数以获得该输出的输入,并且我有正确的密码。关键是我链接了 1,000,000 次,所以如果我在这 1,000,000 次迭代中的任何地方生成原始密码,我可以从原始密码沿着链接找到值和哈希。
  • 谢谢!这应该如何使用加盐密码?在重新应用散列函数之前,你需要对散列值加盐,对吧?
猜你喜欢
  • 2017-09-19
  • 2021-04-25
  • 2016-03-20
  • 2015-05-01
  • 2016-09-17
  • 1970-01-01
  • 1970-01-01
  • 2012-01-08
  • 2018-01-02
相关资源
最近更新 更多