Adler32滚动校验和的计算差异-python

Lij*_*hew 1 python adler32

在计算运行的校验和时需要澄清。

假设我有这样的数据。

data = 'helloworld'
Run Code Online (Sandbox Code Playgroud)

假设块大小为5,我需要计算运行校验和。

>>> zlib.adler32('hello')
103547413
>>> zlib.adler32('ellow')
105316900
Run Code Online (Sandbox Code Playgroud)

根据Python文档(Python版本2.7.2)

zlib.adler32(data[, value])
Run Code Online (Sandbox Code Playgroud)

“计算数据的Adler-32校验和。(Adler-32校验和几乎与CRC32一样可靠,但是可以更快地计算出来。)如果存在value,则将其用作校验和的起始值;否则,使用固定的默认值。这允许在多个输入的串联上计算运行中的校验和。”

但是当我提供这样的东西时,

>>> zlib.adler32('ellow', zlib.adler32('hello'))
383190072
Run Code Online (Sandbox Code Playgroud)

输出完全不同。

我尝试创建一个自定义函数以生成rsync算法中定义的滚动校验和。

def weakchecksum(data):
    a = 1
    b = 0

    for char in data:
        a += (ord(char)) % MOD_VALUE
        b += a % MOD_VALUE



    return (b << 16) | a



def rolling(checksum, removed, added, block_size):
    a = checksum
    b = (a >> 16) & 0xffff
    a &= 0xffff

    a = (a - ord(removed) + ord(added)) % MOD_VALUE
    b = (b - (block_size * ord(removed)) + a) % MOD_VALUE

    return (b << 16) | a
Run Code Online (Sandbox Code Playgroud)

这是我从运行这些功能获得的值

Weak for hello: 103547413
Rolling for ellow: 105382436
Weak for ellow: 105316900
Run Code Online (Sandbox Code Playgroud)

如您所见,就价值而言,我的滚动校验和和python的实现存在巨大差异。

在计算滚动校验和时哪里出错了?我在正确使用python adler32函数的rolling属性吗?

Mar*_*ler 5

adler32()功能不提供“滚动”功能。文档正确使用了“运行”(不是“滚动”)一词,这意味着它可以按块而不是一次计算adler32。您需要编写自己的代码来计算“滚动” adler32值,该值将是数据上滑动窗口的adler32。


Jas*_*ong 5

在您的方法“滚动”中,

b = (b - (block_size * ord(removed)) + a) % MOD_VALUE
Run Code Online (Sandbox Code Playgroud)

应该

b = (b - (block_size * ord(removed)) + a - 1) % MOD_VALUE
Run Code Online (Sandbox Code Playgroud)

根据Wikipedia 中adler32算法的说明,我们可以看到:

A = 1 + D1 + D2 + ... + Dn (mod 65521)
B = (1 + D1) + (1 + D1 + D2) + ... + (1 + D1 + D2 + ... + Dn) (mod 65521)
  = n×D1 + (n?1)×D2 + (n?2)×D3 + ... + Dn + n (mod 65521)

Adler-32(D) = B × 65536 + A
Run Code Online (Sandbox Code Playgroud)

滚动校验和时,将具有以下等式:

A1 = (1 + D2 + D3 + … + Dn + Dn+1)(mod 65521)
= (1 + D1 + D2 + D3 + … + Dn) – D1 + Dn+1(mod 65521)
= A – D1 + Dn+1(mod 65521)
B1 = (1 + D2) + (1 + D2 + D3) + … + (1 + D2 + D3 + … + Dn + Dn+1)(mod 65521)
= (1 + D1) – D1 – 1 + (1 + D1 + D2) – D1 + ... +(1 + D1 + D2 + … + Dn) – D1 + (1 + D1 + D2 +      … + Dn + Dn+1) – D1(mod 65521)
= B – nD1 – 1 + A1 + D1 – D1(mod 65521)
= B – nD1 + A1 – 1(mod 65521)
Run Code Online (Sandbox Code Playgroud)