用crcmod在Python中重建C-CRC32算法

2024-09-28 15:31:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试用Python解码Novatel GPS流,并且已经对sync、header和payload的所有组件进行了排序,但是我不能复制作为消息一部分使用的CRC32。用于生成附加在消息上的CRC的算法用c编写如下:

#include <iostream>
#include <string>

using namespace std;

#define CRC32_POLYNOMIAL 0xEDB88320L
//#define CRC32_POLYNOMIAL 0x04C11DB7L

unsigned long CRC32Value(int i)
{
    int j;
    unsigned long ulCRC;
    ulCRC = i;
    for (j = 8; j > 0; j--)
    {
        if (ulCRC & 1)
            ulCRC = (ulCRC >> 1) ^ CRC32_POLYNOMIAL;
        else
            ulCRC >>= 1;
    }
    return ulCRC;
}
unsigned long CalculateBlockCRC32(
    unsigned long ulCount,
    unsigned char *ucBuffer)
{
    unsigned long ulTemp1;
    unsigned long ulTemp2;
    unsigned long ulCRC = 0;
    while (ulCount-- != 0)
    {
        ulTemp1 = (ulCRC >> 8) & 0x00FFFFFFL;
        ulTemp2 = CRC32Value(((int)ulCRC ^ *ucBuffer++ ) & 0xff );
        ulCRC = ulTemp1 ^ ulTemp2;
    }
    return(ulCRC);
}

int main()
{
    unsigned char buffer[] = {0xaa, 0x44, 0x12, 0x1c, 0x2a, 0x00, 0x02, 0x20, 0x48, 0x00, 0x00, 0x00, 0x90, 0xb4, 0x93, 0x05, 0xb0, 0xab, 0xb9, 0x12, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xbc, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x50, 0xb3, 0xf2, 0x8e, 0x49, 0x40, 0x16, 0xfa, 0x6b, 0xbe, 0x7c, 0x82, 0x5c, 0xc0, 0x00, 0x60, 0x76, 0x9f, 0x44, 0x9f, 0x90, 0x40, 0xa6, 0x2a, 0x82, 0xc1, 0x3d, 0x00, 0x00, 0x00, 0x12, 0x5a, 0xcb, 0x3f, 0xcd, 0x9e, 0x98, 0x3f, 0xdb, 0x66, 0x40, 0x40, 0x00, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03};

    unsigned long crc = CalculateBlockCRC32(sizeof(buffer), buffer);
    cout << hex << crc << endl;
}

结果是0x42、0xdc、0x4c、0x48—这与手册中给出的示例相匹配,因此这是一个不错的开始。在

虽然我可能会在我正在编写的代码中使用这个算法,但我更希望尽可能使用Python,因此在这一点上,我觉得我有两个选择。我可以自己将其翻译成Python,也可以希望有一个内置的Python函数或模块能够为我实现这一点,这正是我一直在寻找的。到目前为止,我发现了三个功能/模块:

  • 在比纳西.crc32在
  • 在zlib.crc32型在
  • crcmod模块

其中前两个给出了同样的错误结果,我无法告诉任何可能会对其产生积极影响的设置或指定参数的方法。在

另一方面,crcmod有过多的设置和预定义的功能,我认为应该能够做我正在寻找的。创建CRC函数的格式如下:

^{pr2}$

我发现的一个关键问题是有预定义的CRC函数,CRC32版本与binascii和zlib的结果相匹配:

Name    Polynomial  Reversed?   Init-value  XOR-out Check
crc-32  0x104C11DB7 True    0x00000000  0xFFFFFFFF  0xCBF43926

因此,至少这有助于我理解zlib和binascii变体从所用多项式的来源。在

因此,我确信我应该能够使用这个函数生成与C算法相同的结果,但是由于不精通C,我不确定我是如何做到这一点的。在C算法中使用的多项式是多项式的反向表示,所以这意味着上面的设置应该有效,但是它们不会按照C代码生成上面的答案。在

我在寻找什么来确定这些设置?是否有一个模块/函数可以完成这一任务,但我还没有看到,或者这不起作用,我应该自己开始将C语言翻译成Python?在


Tags: 模块函数算法bufferlongintcrczlib
1条回答
网友
1楼 · 发布于 2024-09-28 15:31:02

对于crcmod,你需要在多项式前面加上1,因为第33位必须是1,否则你会得到一个例外,说次数必须是8、16、24或32。这似乎产生了您的预期输出:

import crcmod
crc = crcmod.mkCrcFun(0x104C11DB7, 0, True, 0)

下面的示例应该可以在Python 2和Python 3上正常工作:

^{pr2}$

印刷品

^{3}$

它是八位元0x42, 0xdc, 0x4c, 0x48的小端有序值。在

相关问题 更多 >