在我读过的几个地方,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
有人能提供适当的代码来证明这个理论,还是指出我失败的地方?
答案 0 :(得分:6)
CRC在数学意义上是加法的,因为CRC散列只是来自所有数据(被视为一个整数)的无进位除法除以多项式常数的余数值。使用你的例子,它类似于这种事情:
7 mod 5 = 2
6 mod 5 = 1
(7 mod 5)+(6 mod 5)= 3
(7 + 6)mod 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。原因是初始CRC为0允许数据中的任何数量的前导0简单地通过而不改变运行的CRC值,该值保持为0.因此,将CRC初始化为0在数学上是合理的,但是出于实际的计算目的哈希,这是你想要的最后一件事。
答案 1 :(得分:2)
CRC-32算法基于多项式除法,并添加了一些额外的步骤。纯多项式余数是加性的。
由此,我的意思是:mod(poly1 + poly2,poly3)= mod(mod(poly1,poly3)+ mod(poly2,poly3),poly3)
CRC-32算法建立在此基础之上,并且是非加性的。计算字节数组的CRC-32:
纯多项式余数运算在步骤#4中。步骤#1和#6使CRC-32算法不加。因此,如果撤消步骤#1和#6的效果,则可以将CRC-32算法修改为加法。
(另见:Python CRC-32 woes)
答案 2 :(得分:2)
如果a,b和c的长度相同,则CRC(a)xor CRC(b)xor CRC(c)等于CRC(x或b x或c)。回到你的原始公式,这意味着CRC(a xor b)等于CRC(a)xor CRC(b)xor CRC(z),其中z是与其他两个序列长度相同的零序列。
答案 3 :(得分:1)
这意味着CRC结果的每个位位置仅由输入中的等效位位置驱动。考虑一下B == 0的例子。
对于某些原始xor或加性校验和算法,您所描述的关系更可能是正确的。