CRC32 碰撞

Posted

技术标签:

【中文标题】CRC32 碰撞【英文标题】:CRC32 Collision 【发布时间】:2010-12-03 16:59:29 【问题描述】:

我试图找出两条消息之间的冲突,这将导致相同的 CRC 哈希。 考虑到我正在使用 CRC32,有什么方法可以缩短我在进行暴力攻击时必须尝试的可能消息列表?

任何指向带有此提示的网站的链接都会有所帮助。我已经有一个蛮力算法可以做到这一点,但它只是增加整数并查看它是否会匹配其他哈希。

【问题讨论】:

【参考方案1】:

这完全取决于您所说的“消息”是什么意思。如果您可以在其中一条消息中附加四个字节的乱码。 (即在消息的上下文中没有任何意义的四个字节。)然后它就变成了真正意义上的微不足道。

考虑位在 CRC32 状态机中的移动。

CRC32 基于 galois 反馈移位寄存器,其状态中的每个位将被替换为从有效负载数据中提取的 32 位。在每个位的归纳中,多项式所指示的位置将与从移位寄存器末尾观察到的序列进行异或。在移位寄存器被填满之前,这个序列不受输入数据的影响。

例如,假设我们有一个移位寄存器,其中填充了初始状态 10101110、多项式 10000011,并填充了未知位 X。

Polynomial *     **  |feedback (End of SR.)
State      10101110     0
State      X1010111     1
State      XX101000     0
State      XXX10100     0
State      XXXX1010     0
State      XXXXX101     1
State      XXXXXX01     1
State      XXXXXXX1     1
State      XXXXXXXX     0

在 SR 被填满之前,反馈不是 X 的形式! 因此,为了生成具有预定校验和的消息,您需要获取新消息,生成它的 CRC 并计算出它的下一个 32 位反馈。这可以在 CRC 函数的 32 个步骤中完成。然后,您需要计算此反馈对移位寄存器内容的影响。

这样做的捷径是用四个零字节填充您的消息,然后查看校验和。 (校验和是SR最后的状态,如果填充四个零字节是反馈和空字节的影响。)

影响您想要的校验和值的异或,用该计算值替换四字节尾部并重新生成校验和。您可以使用任何生成 CRC32 的程序、十六进制编辑器和可以处理十六进制的计算器来执行此操作。

如果您想生成两条完全有意义且不包含尾随垃圾的消息,事情会变得有些困难。找出一些你可以写出合理的替代方案的部分,长度完全相同。

以英文散文为例。 “我认为这可行” 和 “我相信这种方法” 含义大体相似,长度完全相同。

在您的消息中识别足够多的示例是一个棘手的问题(除非您想用空格作弊!)如果数据在消息中具有正确的偏移量,CRC 32 是线性的。所以 CRC([messagea][padding])^CRC([padding][messageb])=CRC([messagea][messageb]) 您需要处理一些关于单词对齐的注意事项,作为一般提示,您希望将段落扩展到消息的“固定”部分。作为一般规则,您希望有 n*1.5 段落的替代方案,其中 n 是 CRC 的大小。

您现在可以计算骨架信息具有的 CRC,每个替代段落对其的印象,然后绘制一个表格来比较每个段落的每个替代方案可能产生的影响。然后,您需要选择将修改骨架 CRC 以匹配所需 CRC 的替代方案。这个问题实际上解决起来很有趣,首先找到任何唯一修改位的替代方案,如果该位需要针对您的 CRC 进行更改,请选择该替代方案并将其影响折叠到 CRC 中,然后再循环。这应该会减少您随后需要搜索的解决方案空间。

编写代码是一件相当困难的事情,但它会在很短的时间内产生碰撞。

【讨论】:

【参考方案2】:

我的微积分没有缺陷,在 N 次试验后没有发现一次碰撞的概率近似于下表:

N 概率 -------- ----------- 50,000 74.7% 77,000 50.1% 78,000 49.2% 102,000 29.8% 110,000 24.5% 128,000 14.8% 150,000 7.3% 200,000 0.95%

换句话说,必须计算超过 200,000 个 CRC32 值之前找到重复值的概率小于 1%,或者,之前找到重复值的概率> 102,000 次尝试是 70.2% 顺便说一句,这很了不起,因为在第 200,000 次尝试中发现一次碰撞的概率仍然是 1% 的 1/1000 ((4M - 200,0000) / 4M) ,但可能在第 200,000 次尝试之前 发现了一次碰撞是准确定的(好吧,无论如何都高于 99%)。 这表明了保存迄今为止计算的 CRC 数据库的兴趣

我们当然可以花一些时间研究 CRC32 算法及其基础数学,以尝试找到 更有可能产生 CRC32 冲突的消息,但真正随机尝试的次数相对较少找到至少一个准确定性的碰撞,使得这种密码分析方法几乎不值得付出努力。例如,假设我们可以找到一种方法来选择相互碰撞可能性高 10 倍的消息,我们仍然需要尝试大约 63,000 次才能达到至少发生一次碰撞的 99% 的可能性(优于 200,000,但仍需要大致相同类型的应用程序。) 在这方面,我们唯一需要考虑的是避免长度小于 4 字节的消息(我在某处读到 CRC32 在该消息空间中是双射的),并避免过于相似的消息(即仅相差一两个字符),因为 CRC32 的最初目的是检测(并且可能自动更正)消息中如此小的差异。

因此,任务的难度似乎并不在于找到以极快的速度计算 CRC32 的方法(尽管我们也不应该太慢),而是快速管理- 多达 200,000 条消息的可搜索数据库(或消息“密钥”,下文将详细介绍)及其相关的 CRC32 值。

实现这一切的一些想法

需要一个简单的 ISAM 库,或者更好的正式 DBMS 接口,例如 mysql 甚至 SqlLite。 通过使用伪随机数生成器 (PRNG) 来生成消息,我们可以保存消息 keys(即我们提供给 PRNG 以生成给定消息的任何内容),而不是存储整个消息。这将使数据库插入和搜索更有效,但有错误选择 PRNG(或者更确切地说是基于消息生成器的 pm 随机数)的风险,即会产生(起初)不太可能出现 CRC32 的消息的风险-碰撞... 分批工作可能更好,即生成 1,000 个新的 CRC,然后检查冲突并存储它们,而不是一次只为一个 CRC 做​​所有这些事情。如果我们使用现成的 DBMS,则尤其如此

【讨论】:

【参考方案3】:

就在昨天有this question here on SO,那里提到的几个指针可能会对您有所帮助。

【讨论】:

【参考方案4】:

对于大小为 N 的哈希,您需要关于 sqrt(6N) 随机长度消息的蛮力,以获得 95% 的碰撞概率。例如。 CRC32 , N = 2^32 ,你需要大约 160 000 条消息

【讨论】:

【参考方案5】:

我假设您的意思是“消息”而不是“密钥”。

如果允许您选择两个“键”,那么由于生日悖论,蛮力无论如何都会相当快。选择随机消息,计算它们的 CRC,记住所有这些消息和相关的 CRC,随着它们的积累,每个新消息都有越来越多的机会与现有消息发生冲突。坦率地说,我希望这种方法在现代计算机上比查找已知方法来使 CRC32 冲突更快。

【讨论】:

【参考方案6】:

我相信 CRC 是线性的,因此如果您修改(就地,不改变长度)文件的两个不同部分,应该将 CRC 中的差异异或在一起。

-- 更正:似乎没有那么简单。然而,这仍然是我在尝试构建碰撞时会采用的策略——你需要比我今晚更详细地遵循数学......

【讨论】:

好的,但是我发现您所说的“就地”修改很有趣。我原以为 CRC 是为在更大的文件/字符串中检测这些较小的修改而设计的,因为它用于检查完整性。 这就是重点。 CRC 的计算速度非常快,并且擅长检测随机变化,而不是经受密码分析。【参考方案7】:

spoof 正是这样做的。它不需要蛮力。

【讨论】:

以上是关于CRC32 碰撞的主要内容,如果未能解决你的问题,请参考以下文章

MISC:压缩包取证(zip爆破明文攻击伪加密CRC32碰撞)

MISC:压缩包取证(zip爆破明文攻击伪加密CRC32碰撞)

MISC:压缩包取证(zip爆破明文攻击伪加密CRC32碰撞)

完美 32 位 crc 的预期冲突

使用 32 位散列时的冲突概率

MySql crc32&&crc64函数提高字符串查询效率