C zlib crc32 和 Python zlib crc32 不匹配



我在Python和C中尝试了crc32,但我的结果不匹配。

C:
#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>
#define NUM_BYTES 9
int
main(void)
{
  uint8_t bytes[NUM_BYTES] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
  uint32_t crc = crc32(0L, Z_NULL, 0);
  for (int i = 0; i < NUM_BYTES; ++i) {
    crc = crc32(crc, bytes, 1);
  }
  printf("CRC32 value is: %" PRIu32 "n", crc);
}

提供输出CRC32 value is: 3136421207

In [1]: import zlib
In [2]: int(zlib.crc32("123456789") + 2**32)
Out[2]: 3421780262

在 python 中,我添加 2**32 以"投射"到无符号的 int。

我在这里错过了什么?

[编辑1]

现在我已经尝试过

In [8]: crc = 0;
In [9]: for i in xrange(1,10):
   ...:     crc = zlib.crc32(str(i), crc)
   ...:     
In [10]: crc
Out[10]: -873187034
In [11]: crc+2**32
Out[11]: 3421780262

int
main(void)
{
  uint32_t value = 123456789L;
  uint32_t crc = crc32(0L, Z_NULL, 0);
  crc = crc32(crc, &value, 4);
  printf("CRC32 value is: %" PRIu32 "n", crc);
}

结果还是不一样。

原始的 C 和 Python 代码片段中存在问题。至于你的第二个 C 片段,我还没有尝试编译它,但它不是可移植的,因为 int 中的字节顺序取决于平台。因此,它会根据 CPU 的字节序给出不同的结果。

正如Serge Ballesta所提到的,一个问题是{1, 2, 3, 4, 5, 6, 7, 8, 9}{'1', '2', '3', '4', '5', '6', '7', '8', '9'}之间的差异。另一个问题是,原始 C 代码中的循环实际上并没有扫描数据,因为正如 bav 提到的,你没有在循环中使用i

CRCTEST.c

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>
#define NUM_BYTES 9
// gcc -std=c99 -lz -o crctest test.c
void do_crc(uint8_t *bytes)
{
    uint32_t crc = crc32(0L, Z_NULL, 0);
    for (int i = 0; i < NUM_BYTES; ++i)
    {
        crc = crc32(crc, bytes + i, 1);
    }
    printf("CRC32 value is: %lun", crc);
}
int main(void)
{
    uint8_t bytes0[NUM_BYTES] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    uint8_t bytes1[NUM_BYTES] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
    do_crc(bytes0);
    do_crc(bytes1);
}

输出

CRC32 value is: 1089448862
CRC32 value is: 3421780262

crctest.py

#! /usr/bin/env python
import zlib
def do_crc(s):
    n = zlib.crc32(s)
    return n + (1<<32) if n < 0 else n
s = b'x01x02x03x04x05x06x07x08x09'
print `s`, do_crc(s)
s = b'123456789'
print `s`, do_crc(s)

输出

'x01x02x03x04x05x06x07x08t' 1089448862
'123456789' 3421780262

编辑

以下是在 Python 中处理转换的更好方法:

def do_crc(s):
    n = zlib.crc32(s)
    return n & 0xffffffff

有关此主题的更多信息,请参阅此处的答案:如何在 python 中将有符号整数转换为无符号整数。

根据 www.lammertbies.nl 对CRC计算和C例程的详细参考,ASCII字符串的CRC32 123456789 0xCBF43926,即3421780262为十进制形式的无符号32整数。

这意味着你的Python计算是正确的,但是要在C中获得相同的结果,你应该写

uint8_t bytes[NUM_BYTES] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
uint32_t crc = crc32(0L, Z_NULL, 0);

或者,如果你想要的确实是 crc 32 for uint8_t bytes[NUM_BYTES] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; ,你必须在python 2.x中使用:

s = ''
for i in range(10):
    s += chr(i)
s

输出 : 'x00x01x02x03x04x05x06x07x08t'

然后

zlib.crc32(s)

输出 : 1164760902

Nota:在python 3.x中,你会写: s = bytes(range(10))

第一个 c-snippet 的精确副本给出相同的结果:

>>> bytes = [chr(i) for i in range(1, 10)]
>>> crc = zlib.crc32('', 0)
>>> for _ in range(9):
...     crc = zlib.crc32(bytes[0], crc)
>>> crc + 2**32
3136421207

请注意,不要在循环中使用i变量。

这是因为CRC32是在位级别计算的。

您正在用 C(数据大小为 9 字节)和 python 中单独计算每个数字的 CRC,用于整数(可能只需要 4 或 8 个字节来表示)。

字节数可能不同,并将导致不同的CRC。

尝试在 C 中计算123456789的 CRC。

编辑:关于str(i),编码可能不同,而且是ASCII值。由于 1 和"1"不同,因此您不会获得相同的 CRC。尝试

crc = zlib.crc32(int(str(i)), crc) # or simply i

在 C 代码中,数字只有 4 个字节,而在 python 中,它是字符串。32 位整数和数组将给出不同的结果。

请注意,对于位级的相同表示(具有相同位数),您将获得相同的CRC。即使一个位不同或额外或更少,你也会得到完全不同的CRC。

最新更新