python 中没有库的自定义 crc32 计算

custom crc32 calculation in python without libs

我一直在寻找可以生成 crc32 和的简单 python 代码。它适用于 stm32,我找不到一个很好的例子,它是 adjustable.

为了获得正确的计算设置,我使用了以下方面。

http://www.sunshine2k.de/coding/javascript/crc/crc_js.html

设置如下:

多项式:0x4C11DB7, 初始值:0xFFFFFFFF 并且没有异或值或 0x00,也没有反映输入和结果。

有人知道我在哪里可以获得简单的 adjustable 算法或者我可以在哪里学习如何编写一个算法吗?

编辑: 我使用这个函数来创建 table

def create_table():
    a = []
    for i in range(256):
        k = i
        for j in range(8):
            if k & 1:
                k ^= 0x4C11DB7
            k >>= 1
        a.append(k)
    return a

和以下用于生成 crc-sum

def crc32(bytestream):
    crc_table = create_table()


    crc32 = 0xffffffff

    for byte in range( int(len(bytestream)) ):
        lookup_index = (crc32 ^ byte) & 0xff
        crc32 = (crc32 >> 8) ^ crc_table[lookup_index]

    return crc32

并用这个

调用函数
print(hex(crc32(b"1205")))

结果是:0x9f8e7b8c

但是网站给我:0xA7D10A0A

有人可以帮助我吗?

首先,您拥有的是反射 CRC,而不是 non-reflected CRC。尽管您的 table 构造有误。这个:

if k & 1:
    k ^= 0x4C11DB7
k >>= 1

错了。 exclusive-or 必须在轮班后完成。所以它需要是(对于反映的情况):

k = (k >> 1) ^ 0xedb88320 if k & 1 else k >> 1

请注意,在这种情况下也需要反映多项式。

代码中的另一个错误是使用 range 生成整数 0、1、...,并使用 those 而不是实际数据字节来计算CRC 上!你想要的 for 循环很简单:

for byte in bytestream:

使用 table 的全部意义在于使 CRC 计算更快。您不想每次执行 CRC 时都重新生成 table。您希望在程序启动时生成一次 table ,然后多次使用它。或者您可以从您的程序中单独生成 table,然后将 table 本身放入您的程序中。这就是通常所做的。

无论如何,要进行 反映的情况,您需要翻转一下。所以要使 table:

def create_table():
    a = []
    for i in range(256):
        k = i << 24;
        for _ in range(8):
            k = (k << 1) ^ 0x4c11db7 if k & 0x80000000 else k << 1
        a.append(k & 0xffffffff)
    return a

要使用 table:

def crc32(bytestream):
    crc_table = create_table()
    crc = 0xffffffff
    for byte in bytestream:
        lookup_index = ((crc >> 24) ^ byte) & 0xff
        crc = ((crc & 0xffffff) << 8) ^ crc_table[lookup_index]
    return crc

现在它正确地实现了您的规范,恰好是 MPEG-2 32 位 CRC 规范(来自 Greg Cook's CRC catalogue):

width=32 poly=0x04c11db7 init=0xffffffff refin=false refout=false xorout=0x00000000 check=0x0376e6e7 residue=0x00000000 name="CRC-32/MPEG-2"

对于上面的代码,如果我这样做:

print(hex(crc32(b'123456789')))

得到0x376e6e7,与目录中的校验值匹配

同样,您需要将 create_table()crc32() 例程中取出并在其他地方执行一次。