12

在几个地方,我读到 crc32 是加法的,因此:CRC(A xor B) = CRC(A) xor CRC(B)。

我写的以下代码反驳了上述说法:

import zlib
def crc32(data):
        return zlib.crc32(data) & 0xffffffff

print crc32(chr(ord("A") ^ ord("B")))
print crc32("A") ^ crc32("B")

程序输出:

1259060791
2567524794

有人可以提供一个正确的代码来证明这个理论或指出我失败的地方吗?

4

4 回答 4

6

CRC 在数学意义上是加法的,因为 CRC 哈希只是所有数据(被视为大整数)的无进位除以多项式常数的余数。使用您的示例,它类似于这种事情:

7 模 5 = 2

6 模 5 = 1

(7 模 5) + (6 模 5) = 3

(7 + 6) 模 5 = 3

在那个类比中,“5”是我们的 CRC 多项式。

这是一个可以使用的示例(基于 gcc):

#include <stdio.h>
#include <x86intrin.h>

int main(void)
{
        unsigned int crc_a = __builtin_ia32_crc32si( 0, 5);
        printf( "crc(5) = %08X\n", crc_a );
        unsigned int crc_b = __builtin_ia32_crc32si( 0, 7);
        printf( "crc(7) = %08X\n", crc_b );
        unsigned int crc_xor = crc_a ^ crc_b;
        printf( "crc(5) XOR crc(7) = %08X\n", crc_xor );
        unsigned int crc_xor2 = __builtin_ia32_crc32si( 0, 5 ^ 7);
        printf( "crc(5 XOR 7) = %08X\n", crc_xor2 );

        return 0;
}

输出如预期:

plxc15034> gcc -mcrc32 -Wall -O3 crctest.c
plxc15034> ./a.out
crc(5) = A6679B4B
crc(7) = 1900B8CA
crc(5) XOR crc(7) = BF672381
crc(5 XOR 7) = BF672381

因为此代码使用 x86 CRC32 指令,它只能在 Intel i7 或更新版本上运行。内在函数将运行的 CRC 哈希作为第一个参数,将要累积的新数据作为第二个参数。返回值是新运行的 CRC。

上述代码中初始运行的 CRC 值 0 至关重要。使用任何其他初始值,CRC 在实际意义上不是“加法”,因为您已经有效地丢弃了有关您要划分的整数的信息。这正是您的示例中正在发生的事情。CRC 函数从不将初始运行的 CRC 值初始化为零,但通常是 -1。原因是 0 的初始 CRC 允许数据中任意数量的前导 0 简单地通过而不改变运行的 CRC 值,该值保持为 0。因此,将 CRC 初始化为 0 在数学上是合理的,但出于计算的实际目的哈希,这是你想要的最后一件事。

于 2011-08-09T04:47:01.097 回答
3

CRC-32 算法基于多项式除法,增加了一些额外的步骤。纯多项式余数是加法的。

我的意思是: mod(poly1 + poly2, poly3) = mod(mod(poly1, poly3) + mod(poly2, poly3), poly3)

CRC-32 算法建立在此之上,并且是非加法的。要计算字节数组 m 的 CRC-32:

  1. 将前 4 个字节与 0xFFFFFFFF 异或。
  2. 将较早的字节视为较高的多项式幂,将较低的位视为较高的多项式幂。例如,字节 0x01 0x04 将是多项式 x^15 + x^3。
  3. 将多项式乘以 x^32。
  4. 取这个多项式的余数除以 CRC-32 多项式 0x104C11DB7。余数多项式的次数 < 32。
  5. 将低功率视为高阶位。例如,多项式 x^2 将是 32 位整数 0x40000000。
  6. 将结果与 0xFFFFFFFF 异或。

纯多项式余数运算在步骤#4。是步骤 #1 和 #6 使 CRC-32 算法不加性。因此,如果您撤消步骤 #1 和 #6 的效果,则可以将 CRC-32 算法修改为可加法。

(另见:Python CRC-32 问题

于 2011-08-10T04:09:08.767 回答
2

如果 a、b 和 c 的长度相同,则 CRC(a) xor CRC(b) xor CRC(c) 等于 CRC(a xor b xor c)。回到您的原始公式,这意味着 CRC(a xor b) 等于 CRC(a) xor CRC(b) xor CRC(z),其中 z 是与其他两个序列长度相同的零序列。

于 2012-02-23T23:59:58.050 回答
1

这意味着 CRC 结果的每个位位置仅由输入中的等效位位置驱动。以 B == 0 为例。

对于某些原始异或或加法校验和算法,您所描述的关系更可能是正确的。

于 2011-08-08T07:39:29.443 回答