【问题标题】:Incremental Checksums增量校验和
【发布时间】:2009-07-23 18:04:40
【问题描述】:

我正在寻找一种校验和算法,其中对于大块数据,校验和等于所有较小组件块的校验和之和。我发现的大部分内容来自提供此功能的 RFC 1624/1141。有人对这些校验和技术或类似技术有任何经验吗?

【问题讨论】:

  • 它是否需要具体等于较小块的校验和的算术和,或者您只是更一般地希望能够从更小的块?
  • 在我看来,校验和问题今天被认为是“大部分已解决”,并且经常被视为“IO 限制”,因此从算法性能的角度来看并不有趣。但是好的,“IO 绑定”是,我们可以对 IO 做些什么呢?好吧,如果我们可以在 IO 在缓存中仍然很热的时候计算哈希值,那就太好了。
  • @Amigable Clark Kent 也许最好根据您的确切要求提出一个新问题,而不是捎带现有的已回答问题。您是否只是在寻找校验和来检测错误?您在寻找加密哈希函数吗?是否要求校验和由每个块的校验和的某种组合组成,正如原始问题所问的那样,还是只需要您可以在数据流上增量计算校验和,并为整个流提供一次校验和完成了吗?
  • @Brian Campbell,出于文件身份的目的,我更喜欢哈希。对我和我当前的项目来说,最重要的是校验和可以增量计算。但我认为最初的问题本身就很有趣,我希望其他有很多线索的人会写一些有趣的东西。 :-)
  • @Amigable Clark Kent 看起来你在我设法完成发布我的答案之前授予了你的赏金。希望无论如何我都能帮助你。

标签: checksum


【解决方案1】:

如果只是快速组合较小块的校验和以获得较大消息的校验和(不一定通过简单的求和),您可以使用 CRC 类型(或类似)算法来做到这一点。

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、... 的总和(异或),就像这样

  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) 和子块b 相对于B 的位置来计算checksum(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) 相乘加上。您可以在表格中预先计算,或使用平方和乘法算法快速计算此幂。

推荐阅读:Painless Guide to CRC Error Detection Algorithms

【讨论】:

    【解决方案2】:

    我只使用了如您所描述的那样工作的 Adler/Fletcher 校验和。

    对 crypto++ 哈希/校验和实现 here 进行了很好的比较。

    【讨论】:

    • 我一直在尝试和 Adler 一起玩,但我似乎无法得到预期的结果,你的意思是:adler('wiki') + adler('pedia') 应该产生与 adler('wikipedia') 相同的摘要,还是我错过了什么?
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2020-06-21
      • 1970-01-01
      • 2015-06-29
      • 2020-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-31
      • 1970-01-01
      相关资源
      最近更新 更多