我正在寻找校验和算法,对于大块数据,校验和等于来自所有较小组件块的校验和之和。我发现的大部分内容来自RFC 1624/1141,它们确实提供了这项功能。有没有人对这些校验和技术有类似的经验?
答案 0 :(得分:10)
如果只是快速组合较小块的校验和以获得较大消息的校验和(不一定是简单求和),则可以使用CRC类型(或类似)算法执行此操作。 / p>
CRC-32算法就像这样简单:
uint32_t update(uint32_t state, unsigned bit)
{
if (((state >> 31) ^ bit) & 1) state = (state << 1) ^ 0x04C11DB7;
else state = (state << 1);
return state;
}
数学上,状态表示字段GF2上的多项式,该多项式总是以生成多项式为模。给定一个新位b
,旧状态将转换为新状态,如此
state --> (state * x^1 + b * x^32) mod G
其中G是生成多项式,并且在GF2(xor)中完成加法。这个校验和是线性,因为您可以将消息M
写为消息A,B,C的总和(xor)......就像这样
10110010 00000000 00000000 = A = a 00000000 00000000
00000000 10010001 00000000 = B = 00000000 b 00000000
00000000 00000000 11000101 = C = 00000000 00000000 c
-------------------------------------------------------------
= 10110010 10010001 11000101 = M = a b c
具有以下属性
M = A + B + C
checksum(M) = checksum(A) + checksum(B) + checksum(C)
同样,我的意思是GF2中的+
,您可以使用二进制XOR实现。
最后,可以根据checksum(B)
计算checksum(b)
,并根据b
计算子块B
的位置。简单的部分是前导零。前导零根本不影响校验和。因此checksum(0000xxxx)
与checksum(xxxx)
相同。如果要在给定非填充消息的校验和的情况下计算零填充(向右 - >尾随零)消息的校验和,则它会更复杂一些。但不是那么复杂:
zero_pad(old_check_sum, number_of_zeros)
:= ( old_check_sum * x^{number_of_zeros} ) mod G
= ( old_check_sum * (x^{number_of_zeros} mod G) ) mod G
因此,获取零填充消息的校验和只是将非填充消息的“校验和多项式”与仅取决于零的数量的其他多项式(x^{number_of_zeros} mod G
)相乘的问题。你想要添加。您可以在表格中预先计算它,或使用square-and-multiply算法快速计算此功率。
答案 1 :(得分:9)
答案 2 :(得分:4)
要回答Amigable Clark Kent的赏金问题,出于文件标识的目的,你可能想要一个加密哈希函数,它试图保证任何两个给定文件产生相同值的概率极低,而不是校验和。通常仅用于错误检测,并且可以为两个非常不同的文件提供相同的值。
许多加密哈希函数(例如MD5和SHA-1)使用Merkle–Damgård construction,其中有计算将数据块压缩为固定大小,然后组合具有前一个块的固定大小值(或第一个块的初始化向量)。因此,他们能够以流模式工作,随着他们的进行逐步计算。