增量校验和

时间:2009-07-23 18:04:41

标签: checksum

我正在寻找校验和算法,对于大块数据,校验和等于来自所有较小组件块的校验和之和。我发现的大部分内容来自RFC 1624/1141,它们确实提供了这项功能。有没有人对这些校验和技术有类似的经验?

3 个答案:

答案 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算法快速计算此功率。

建议阅读:Painless Guide to CRC Error Detection Algorithms

答案 1 :(得分:9)

我只使用了Adler / Fletcher校验和,可以按照您的描述工作。

对crypto ++ hash / checksum实现进行了很好的比较here

答案 2 :(得分:4)

要回答Amigable Clark Kent的赏金问题,出于文件标识的目的,你可能想要一个加密哈希函数,它试图保证任何两个给定文件产生相同值的概率极低,而不是校验和。通常仅用于错误检测,并且可以为两个非常不同的文件提供相同的值。

许多加密哈希函数(例如MD5SHA-1)使用Merkle–Damgård construction,其中有计算将数据块压缩为固定大小,然后组合具有前一个块的固定大小值(或第一个块的初始化向量)。因此,他们能够以流模式工作,随着他们的进行逐步计算。