关于密码学:为什么MD5哈希值不可逆?

How come MD5 hash values are not reversible?

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

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

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

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

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

这些功能是什么使返回的字符串无法回溯?


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

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


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


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

考虑以下函数(以PHP表示法为问题):

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

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

1
print simple_hash("stackoverflow.com");

这将输出:

1
737461636b6f766572666c6f772e636f6d

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

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

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

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

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

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

要回答实际问题:

What is it about these functions that makes the
resulting strings impossible to retrace?

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

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

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


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


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

例如。,

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

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

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


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

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


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


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

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

有时会使用以下条件:

  • 图像前阻力:对于给定的哈希函数和给定的哈希,应该很难找到具有该函数的给定哈希的输入。
  • 第二原像抵抗:对于给定的哈希函数和输入,应该很难找到具有相同哈希的第二不同输入。
  • 防冲突性:对于给定的具有功能的对象,应该很难找到具有相同哈希值的两个不同输入。
  • 选择这些标准以使其难以找到与给定哈希匹配的文档,否则可以通过将原始文档替换为与哈希匹配的文档来伪造文档。 (即使替换的内容很乱,仅替换原始内容也可能会造成损坏。)

    3代表2。

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


    中国科学家发现了一种称为"选择前缀冲突"的方式,可以在两个不同的字符串之间产生冲突。

    这是一个示例:http://www.win.tue.nl/hashclash/fastcoll_v1.0.0.5.exe.zip
    源代码:http://www.win.tue.nl/hashclash/fastcoll_v1.0.0.5_source.zip


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

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


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


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

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


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

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

    1
    aea23489ce3aa9b6406ebb28e0cda430


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

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

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

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


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

    实际上,这对于他们执行确定某人是否拥有哈希数据的未损坏副本的功能是必需的。这使蛮力攻击容易受到影响,而蛮力攻击如今已经非常强大,尤其是针对MD5。

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

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

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


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

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

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