问题
我有一个文本文件,每行包含一个字符串(linebreak\r\n)。该文件通过两种不同的方式使用CRC16进行保护。
- 4096字节块的CRC16
- 32768字节块的CRC16
现在我必须修改这4096字节块中的任何一个,所以它(块)
- 包含特定字符串
- 不会更改文本文件的大小
- 具有与原始块相同的CRC值(与包含此4k块的32k块相同)
脱离这些限制,我可以对块进行任何修改,只要文件本身不破坏其格式,就可以完全填充它。我认为最好使用任何一个完全填充的4k块,而不是最后一个块,因为它可能很短。
问题
我应该如何开始解决这个问题?我首先想到的是某种残酷,但不是需要很长时间才能找到导致两个CRC值保持不变的变化吗?可能有数学方法可以解决这个问题吗?
应该在几秒钟或几分钟内完成。
有数学方法可以解决这个问题,但我不知道。我提出了一个蛮力解决方案:
一个块看起来像这样:
SSSSSSSMMMMEEEEEEE
每个字符代表一个字节。S=起始字节,M=可以修改的字节,E=结束字节。
在将每个字节添加到CRC之后,它具有一个新的内部状态。您可以重复使用校验和状态,直到您修改的位置。您只需要重新计算修改后的字节和以下所有字节的校验和。因此,只计算一次S
-部分的CRC。
您也不需要重新计算以下字节。您只需要在修改后检查CRC状态是相同还是不同。如果它是相同的,那么整个块也将是相同的。如果不同,整个区块可能会不同(不能保证,但你应该中止试验)。因此,只计算S+M'
部分的CRC(M'
是修改后的字节)。如果它等于CRC(S+M)
的状态,则您获胜。
这样一来,您要处理的数据就少得多,而且最近的台式机或服务器可以在几分钟内完成所需的2^32
测试。使用并行性。
看看恶搞.c。这将直接解决4K块的CRC问题。然而,您需要修改代码,以同时解决4K块的CRC和封装的32K块的CRC的问题。这只是一个添加更多方程来求解的问题。该代码非常快,在O(log(n))时间内运行,其中n是消息的长度。
基本思想是,你需要在32个或更多的未知数中求解GF(2)上的32个线性方程,其中每个未知数都是你允许改变的一个位置。提供超过32个未知数来解决问题是很重要的,因为如果你恰好选择了32个未知数,那么你最终得到一个奇异矩阵而没有解的可能性就很大。欺骗代码将自动从您提供的>32个位置中找到32个未知位位置的非奇异选择。