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碰撞)