MD5哈希值为何不可逆?


91

我一直想知道的一个概念是使用加密哈希函数和值。我知道这些函数可以生成唯一且几乎无法逆转的哈希值,但这是我一直想知道的:

如果在服务器上,则在PHP中产生:

md5("stackoverflow.com") = "d0cc85b26f2ceb8714b978e07def4f6e"

通过MD5函数运行相同的字符串时,在PHP安装中会得到相同的结果。一个过程正在被用来从某个初始值中产生一些价值。

这是否意味着有某种方法可以解构正在发生的事情并反转哈希值?

这些函数使生成的字符串无法回溯是什么原因?


54
不可逆值的一个简单示例是模。例如10%3 = 1,但您不能将1反转为10,因为它也可能是4
Gab Royer

57
如果您可以重建数据,那么您将拥有有史以来最有效的无损压缩算法:)
Dan Diplo 2009年

Answers:


204

输入材料可以是无限长,输出总是128位长。这意味着无限数量的输入字符串将产生相同的输出。

如果您选择一个随机数并将其除以2,但只写下其余部分,则会分别得到0或1-偶数或奇数。是否可以取0或1来获得原始数字?


4
也就是说,数字->余数或字符串-> md5都不是“内射函数”。
Federico A. Ramponi”,

费德里科(Federico),您当然不是说双射函数吗?它们都是内射的。
Mihai Limbășan

10
moocha:单指1到1。MD5当然不是1到1,因为域大于范围。另一点值得注意的是,给定MD5校验和,即使找到一个散列到它的字符串也非常困难。可能值得添加答案以进行澄清。
生物锌

4
拥有生成唯一值的哈希函数是不可能的。您正在将无限数量的值映射到有限数量的值,以确保发生冲突。
科迪·布洛西夫

4
我建议您的答案不能解决重点。正如biozinc所述,安全密码哈希的重要之处在于,您找不到任何创建输出的输入,而不是找不到原始输入。关于这一点,MD5不一定像它可能的那样安全(en.wikipedia.org/wiki/MD5#Collision_vulnerabilities)。
Mike Pelley 2010年

53

如果像MD5这样的哈希函数是可逆的,那么这将是数据压缩算法历史上的分水岭事件!不难看出,如果MD5是可逆的,那么任意大小的任意数据块都可以仅用128位表示,而不会丢失任何信息。因此,无论原始消息的大小如何,您都可以从128位数字中重建原始消息。


9
想想如果您能直接得到md5的话,下载Linux发行版将有多快:)
Colin Pickard,2009年

15
@Colin Pickard:我们将不再下载 linux发行版,我们将其记录下来。:)
tzot

29

与此处最受支持的答案相反,由大(可能无限)的输入大小和固定的输出大小之间的差异引起的加密哈希函数的非注入性(即,有多个字符串哈希到相同的值)不是重要的一点 –实际上,我们更喜欢哈希函数,在这些哈希函数中,冲突很少发生。

考虑以下功能(以PHP表示法为问题):

function simple_hash($input) {
     return bin2hex(substr(str_pad($input, 16), 0, 16));
}

如果字符串太短,则会附加一些空格,然后使用字符串的前16个字节,然后将其编码为十六进制。它具有与MD5哈希相同的输出大小(32个十六进制字符,或者如果省略bin2hex部分,则为16个字节)。

print simple_hash("stackoverflow.com");

这将输出:

737461636b6f766572666c6f772e636f6d

此功能也具有与Cody针对MD5的回答所强调的相同的非内射性:我们可以传入任何大小的字符串(只要它们适合我们的计​​算机),并且它只会输出32个十六进制数字。当然不能是内射的。

但是在这种情况下,找到映射到相同哈希的字符串很简单(只需将其应用于hex2bin您的哈希即可)。如果您的原始字符串的长度为16(如我们的示例所示),您甚至会得到此原始字符串。即使您知道输入的长度很短,MD5也不应该有这种情况(除非尝试所有可能的输入,直到找到匹配的输入,例如蛮力攻击)。

密码哈希函数的重要假设是:

  • 很难找到产生给定哈希值(原像电阻)的任何字符串
  • 很难找到产生与给定字符串相同的哈希值的任何其他字符串(第二个像前电阻)
  • 很难找到具有相同散列的任何一对字符串(抗冲突性)

显然,我的simple_hash职能不满足这些条件。(实际上,如果我们将输入空间限制为“ 16字节字符串”,那么我的函数会变得内射,因此甚至可以证明其具有第二原像抗性和抗碰撞性。)

现在存在针对MD5的碰撞攻击(例如,即使有给定的相同前缀,也可能产生具有相同哈希值的一对字符串,需要做很多工作,但不是不可能做很多工作),因此您不应该使用MD5适用于任何关键问题。尚无原像攻击,但攻击会变得更好。

要回答实际问题:

这些函数使生成的字符串无法回溯是什么原因?

MD5(和其他基于Merkle-Damgard构造的哈希函数)有效地执行的工作是,使用所得的密文作为哈希,应用一种加密算法,将消息作为密钥,并将某个固定值作为“纯文本”。(在此之前,将输入填充并拆分为块,每个块用于加密前一个块的输出,并对其输入进行XOR运算,以防止进行反向计算。)

现代加密算法(包括哈希函数中使用的算法)的制作方式使得即使在给定明文和密文(甚至当对手选择其中之一)的情况下也很难恢复密钥。他们通常通过执行许多位混洗操作来做到这一点,即每个输出位由每个关键位(多次)以及每个输入位确定。这样,如果您知道完整的键以及输入或输出,就只能轻松地追溯内部发生的事情。

对于类似MD5的哈希函数和原图像攻击(使用单块哈希字符串,使事情变得更容易),您只有加密函数的输入和输出,而没有密钥(这就是您要寻找的)。


4
是的,我知道这是一个很晚的答案,但是不应让这样接受的答案如此。
2011年

我认为您的批评是有优点的,但是您没有回答实际的问题“这些功能是什么使返回的字符串无法回溯?” 您的答案侧重于加密散列应具有的质量,但对md5如何实现它们的解释为零。您可以在此处说明用于计算MD5和的确切算法,以显示它是不可逆的,但是其他答案的确可以提供更简单的解释,而无需多花钱。
Autodidact

(续...)2.这些解释使用“数学”来显示一个基本问题,由于该问题,此类操作会丢失信息并变得不可逆。
Autodidact 2015年

1
@SandeepDatta我添加了一些有关此的段落。
圣保罗Ebermann

1
尽管此主题中的其他答案在技术上更正确,但此答案最有用。非内射函数f(x)= 1是不可逆的,但没有兴趣。散列的有用之处在于原像电阻,在其中很难找到产生特定输出的任何输入。
贾斯汀·史塔克

18

Cody Brocious的答案是正确的。严格来讲,您无法“反转”哈希函数,因为许多字符串都映射到了同一哈希。但是,请注意,找到一个映射到给定哈希值的字符串,或者找到两个映射到相同哈希值的字符串(即冲撞),对于密码分析器来说都是重大突破。这两个问题的极大困难是为什么良好的哈希函数在密码学中有用的原因。


12

MD5不会创建唯一的哈希值;MD5的目标是根据源的微小变化快速产生一个显着变化的值。

例如,

"hello" -> "1ab53"
"Hello" -> "993LB"
"ZR#!RELSIEKF" -> "1ab53"

(显然,这不是实际的MD5加密)

大多数哈希(如果不是全部)也是不唯一的;相反,它们足够独特,因此碰撞是极不可能的,但仍然是可能的。


8

考虑哈希算法的一种好方法是考虑在Photoshop中调整图像的大小...说您有一个5000x5000像素的图像,然后将其大小调整为32x32。您所拥有的仍然是原始图像的表示形式,但是它要小得多,并且有效地“丢弃”了图像数据的某些部分,以使其适合较小的尺寸。因此,如果将32x32图像的大小调整为5000x5000,您将得到的是一片混乱。但是,由于32x32的图像没有那么大,因此从理论上可以想象可以缩小另一个图像以产生完全相同的像素!

那只是一个类比,但它有助于理解哈希在做什么。


3
虽然调整图像大小是一个有损的过程,但要生成原始5000×5000尺寸的图像仍然很容易,它将(再次应用缩小功能时)缩小为相同的32×32图像。对于良好的哈希函数来说,找到这样的原像应该很困难
圣保罗Ebermann

4

哈希冲突比您想象的要大得多。看看生日悖论,以更深入地了解为什么会这样。


1
共有365个可能的生日值,介于2 ^ 8和2 ^ 9之间。128位哈希具有2 ^ 128个可能的值-是2 ^ 120倍。是的,碰撞的可能性比您直觉的高,但从天文学角度来说,碰撞的可能性仍然很小。
Tim Keating

您将需要大约2 ^ 64个不同的值才能在哈希冲突中获得良好的机会。还是有些。
2011年

4

由于可能的输入文件数大于128位输出的数,因此不可能为每个可能的值唯一地分配MD5哈希。

加密哈希函数用于检查数据完整性或数字签名(为提高效率而对哈希进行签名)。因此,更改原始文档应该意味着原始哈希与更改后的文档不匹配。

有时会使用以下条件:

  1. 图像前阻力:对于给定的哈希函数和给定的哈希,应该很难找到具有该函数的给定哈希的输入。
  2. 第二原像抵抗:对于给定的散列函数和输入,应该很难找到具有相同散列的第二不同输入。
  3. 耐碰撞性:对于给定的具有功能的对象,应该很难找到具有相同哈希值的两个不同输入。

选择这些标准以使其难以找到与给定哈希匹配的文档,否则可以通过将原始文档替换为与哈希匹配的文档来伪造文档。(即使替换的内容很乱,仅替换原始内容也可能会造成损坏。)

3号代表2号。

特别是对于MD5,它已显示出一个缺陷: 如何破坏MD5和其他哈希函数


2

但这就是彩虹桌发挥作用的地方。基本上,它只是大量散列的值,然后将结果保存到磁盘。然后,反转位“只是”在非常大的表中进行查找。

显然,这仅适用于所有可能输入值的子集,但如果您知道输入值的范围,则有可能对其进行计算。


嗯是的 我很喜欢阅读Jeff在哈希表上的帖子(codinghorror.com/blog/archives/000949.html),并且该主题有助于理解该概念。
barfoon's


1

正如大多数人已经说过的那样,MD5是为将可变长度的数据流散列为固定长度的数据块而设计的,因此许多输入数据流共享单个散列。

但是,如果您确实确实需要从校验和中找出原始数据,例如,如果您拥有密码的哈希值并且需要找出原始密码,那么通常,使用谷歌(或您喜欢的任何搜索者)来搜索哈希值通常会更快答案比蛮力吧。我已经成功找到了使用此方法的一些密码。


1

理解所有投票最多的答案意味着什么的最好方法是实际尝试还原MD5算法。我记得几年前我曾尝试过还原MD5crypt算法,不是为了恢复原始消息,因为显然这是不可能的,而只是生成一条将产生与原始哈希相同的哈希的消息。至少从理论上讲,这将为我提供一种使用生成的消息(密码)而不是原始消息登录到将user:password存储在/ etc / passwd文件中的Linux设备的方法。由于这两个消息将具有相同的结果哈希值,因此系统将识别我的密码(从原始哈希值生成)为有效。那根本没有用。几周后,如果我没记错的话,请使用在最初的消息中杀死了我。我不仅要产生一个有效的初始消息,还要产生一个盐化的有效初始消息,而这是我永远做不到的。但是我从这个实验中学到的知识很好。


如果您能够生成以任何合理有效的方式产生给定MD5哈希值的输入,那么这对于加密社区将是一件大事,应该予以发布。这完全与特定输入是否已添加盐无关。
Dave L.

0

顾名思义,哈希(加密哈希)函数:不应是可逆的;不应有冲突(尽可能)。

regd您的问题:这是哈希的一种方法。输入(不考虑长度)将生成固定大小的输出(将基于算法填充(对于MD5为512位边界))。该信息被压缩(丢失),并且实际上不可能从逆变换中生成。

有关MD5的其他信息:它容易受到碰撞的影响。最近浏览了这篇文章, http://www.win.tue.nl/hashclash/Nostradamus/

可以在Mozilla代码中找到用于加密哈希实现(MD5和SHA)的开放源代码。(freebl库)。


0

现在,针对所有可能的字符串预先计算了几天的MD5哈希或任何其他哈希值,并进行了存储以方便访问。尽管从理论上讲MD5是不可逆的,但是使用这种数据库,您可能会发现导致特定哈希值的文本。

例如,尝试在http://gdataonline.com/seekhash.php上使用以下哈希代码,以找出我用来计算哈希的文本

aea23489ce3aa9b6406ebb28e0cda430

嗯,是的,是一个普通的7个字母的单词的哈希。现在,用它找出带有空格和标点符号的11个单词的歌词:9f2c08d4e6158bd4854b15be50c8daa8。几千年后见。
Tim Keating

6fba2bbab8a8366309bf67c7df12c622?提示:它可能是Mac OS X特定版本的OEM版本!
scherand

@Tim Keating,@ scherand:只是指出了散列算法的弱点,因为字符串的散列始终是相同的,所以我们不一定需要破解算法来找出实际的字符串。
巴巴尔(Barbar)2010年

2
但这不是你所说的。您说过,哈希是“针对所有可能的字符串进行预先计算并存储以方便访问的”,这显然是错误的(“所有可能的字符串”的集合是无限的……甚至“所有可能的字符串”的集合也确实非常大) )。恕我直言,这歪曲了对合理的密码短语进行字典攻击有多么容易。
Tim Keating 2010年

0

f(x)= 1是不可逆的。哈希函数不是不可逆的。

实际上,这对于他们执行确定某人是否拥有哈希数据的未损坏副本的功能是必需的。这给蛮力攻击带来了敏感性,而蛮力攻击如今已经非常强大,尤其是针对MD5。

在拥有数学知识但很少破解密码的人们中,这里和其他地方也存在混乱。几个密码只是将数据与密钥流进行异或运算,因此您可以说一个密文对应于该长度的所有明文,因为您可以使用任何密钥流。

但是,这忽略了从种子产生的合理的明文password比由种子产生的另一种可能性要大得多Wsg5Nm^bkI4EgxUOhpAjTmTjO0F!VkWvysS6EEMsIJiTZcvsh@WI$IH$TYqiWvK!%&Ue&nk55ak%BX%9!NnG%32ftud%YkBO$U6o的程度,以至于有人嘲笑声称第二种可能性的人。

同样,如果您要尝试在两个可能的密码password和之间进行选择Wsg5Nm^bkI4EgxUO,这并不像某些数学家所认为的那样难。


仅从哪里获得最简单的密码与密钥流知识进行异或运算?对于流密码,这是正确的,但是也有分组密码,它们不能以这种方式工作。
圣保罗Ebermann

-5

我喜欢所有各种论点。显然,哈希值的真正价值仅仅是为字符串(例如密码)提供人类无法理解的占位符。它没有特定的增强安全性好处。假设攻击者可以使用哈希密码访问表,则他/她可以:

  • 散列自己选择的密码,如果他/她对该表具有写/编辑权限,则将结果放入密码表中。
  • 生成普通密码的哈希值,并测试密码表中是否存在相似的哈希值。

在这种情况下,仅通过散列密码就不能保护弱密码。


“散列值”的真正价值不是要提供人类无法理解的占位符。如果“ password1”散列为“ newval” ,尽管散列是可读且有意义的,这是否仍不会以类似的方式隐藏该值?此外,密码是一个不好的例子,因为永远不要对密码进行哈希处理。假设攻击者具有对该数据库的写访问权,那肯定是有可能的。但是,似乎您只是在丢弃对此类哈希函数的正确使用,上面的许多答案中都概述了一个示例-消息完整性。实际上,这就是我今天在此线程上的原因。
Shane
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.