Validating CRC32 checksum

0

I am able to successfully generate a CRC32 that matches the expected output. However, when I try to plug the message M with checksum C (generated by the CRC32 function) back into that same CRC32 generator, I'm not able to get the expected output of 0x00000000.

My CRC32 generator is basically just the code here (https://lxp32.github.io/docs/a-simple-example-crc32-calculation/), with an additional function argument for the checksum, since the message and checksum in my case are in separate memory locations upon receipt.

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 Input 1: 0x61 0x62 0x63 0x64 0x00 0x00 0x00 0x00

CRC32 Output 1: 0x87988EF9

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

CRC32 Output 2: 0x5D19F7CF

I feel like I'm not understanding something right here...

c
crc
crc32
asked on Stack Overflow Jul 29, 2020 by Brett Koenig

1 Answer

2
  1. When you do it right, you won't get zero. You get the same constant every time, but it isn't zero for this CRC. For this one, the constant is 0x2144df1c. (It's not zero because there is a final exclusive-or with a non-zero value.)
  2. You're not doing it right. First, you do not need to and should not append four zeros. Just calculate the CRC of the message. Second, append the CRC in little-endian order. Not big-endian order. (Because this is a reflected CRC that shifts down.)
  3. There is little point in checking the CRC this way. Just compute the CRC on the message, and then compare the result of that to the CRC that was sent. That is far easier, more transparent to someone reading your code, and avoids an unnecessary calculation of the CRC on four more bytes. The compare is much faster than a CRC calculation on four bytes.
  4. Why are you sticking an extra zero in there for odd-length messages?
answered on Stack Overflow Jul 29, 2020 by Mark Adler • edited Jul 29, 2020 by Mark Adler

User contributions licensed under CC BY-SA 3.0