验证CRC32校验和

时间:2020-07-29 01:17:19

标签: c crc crc32

我能够成功生成与预期输出匹配的CRC32。但是,当我尝试将带有校验和C(由CRC32函数生成)的消息M插入相同的CRC32生成器时,我无法获得预期的输出0x00000000。

我的CRC32生成器基本上只是此处的代码(https://lxp32.github.io/docs/a-simple-example-crc32-calculation/),带有用于校验和的附加函数参数,因为在我的情况下,消息和校验和在收到后就位于单独的内存位置。

uint32_t crc32(const char* s, size_t n, uint32_t checksum) {
    uint32_t crc = 0xFFFFFFFF;
    size_t i; size_t j;

    for (i = 0; i < n; i++) {
        char ch = s[i];
        uint32_t t = (ch ^ crc) & 0xFF;
        crc = (crc >> 8) ^ crc32_table[t];
    }

    if (i & 1) { // if i ended odd, write a 0x00 pad bit
        uint32_t t = (0x00 ^ crc) & 0xFF;
        crc = (crc >> 8) ^ crc32_table[t];
    }

    // include checksum bits if not 0
    if (checksum) {
        for (j = 0; j < 4; j++) {
            char ch = (checksum & 0xFF);
            uint32_t t = (ch ^ crc) & 0xFF;
            crc = (crc >> 8) ^ crc32_table[t];
            checksum >>= 8;
        }
    }
    else {
        // append 32-bits of 0's
        for (j = 0; j < 4; j++) {
            uint32_t t = (0x00 ^ crc) & 0xFF;
            crc = (crc >> 8) ^ crc32_table[t];
        }
    }
    return ~crc;
}

bool validate_crc32(const char* msg, size_t n, uint32_t checksum) {
    uint32_t res = crc32(msg, n, checksum);
    return res == 0;
}

CRC32输入1:0x61 0x62 0x63 0x64 0x00 0x00 0x00 0x00

CRC32输出1:0x 87988EF9

CRC32输入2:0x61 0x62 0x63 0x64 0x87 0x98 0x8E 0xF9

CRC32输出2:0x5D19F7CF

我觉得我对这里的东西不了解...

1 个答案:

答案 0 :(得分:2)

  1. 正确执行操作不会得到零。您每次都会得到相同的常数,但是对于此CRC来说它不是零。为此,常数为0x2144df1c。 (它不为零,因为存在最终的“异或”值或非零值。)
  2. 您做错了。首先,您不需要也不应附加四个零。只需计算消息的CRC。其次,以 -endian顺序附加CRC。不是大端顺序。 (因为这是向下移动的反射CRC。)
  3. 以这种方式检查CRC毫无意义。只需计算消息的CRC,然后将其结果与发送的CRC进行比较。这对于读取您的代码的人来说更容易,更透明,并且避免了在另外四个字节上不必要地计算CRC。这种比较比对四个字节进行CRC计算要快得多。
  4. 为什么要在其中为奇数长度的消息添加一个额外的零?