简体   繁体   中英

CRC32 of already CRC32 treated data with the CRC data appended

I use the following C algo to calculate a CRC32 on data:

#define CRC32_POLYNOM_REVERSED   0xEDB88320

uint32 calcCrc32(uint8* buffer, uint32 bufferSize) {
    return accumulateCrc32(0, buffer, bufferSize);
}

uint32 accumulateCrc32(uint32 accumulatedCrc32, uint8* buffer, uint32 bufferSize) {
    uint32 i, j;
    uint32 crc, mask;

    crc = accumulatedCrc32 ^ 0xFFFFFFFF;

    for (i = 0; i < bufferSize; i++) {
        crc ^= buffer[i];
        for (j = 8; j > 0; j--) {
            mask = -(crc & 1);
            crc = (crc >> 1) ^ (CRC32_POLYNOM_REVERSED & mask);
        }
    }

    return crc ^ 0xFFFFFFFF;
}

When I apply it to any data and concatenate the resulting 4 bytes of CRC32 to the data and run it through this routine again, it always ends up with the result

crc32 = 0x2144DF1C

Anybody having an idea, why it is behaving like this?

This is a mathematical property of CRCs. If a "pure" CRC without pre or post-processing, is appended to the message, then the CRC of the whole thing will always be zero. In fact this simplifies the checking of messages with CRCs in hardware, since you can just run the entire message and CRC through the CRC register, and check that the result at the end is zero.

In the mathematics of CRC, you can consider a division operation, where the dividend is the message, the divisor is the CRC polynomial, and the remainder of the division is the CRC. If you append the CRC to the message, it is effectively subtracting the remainder. Then when you divide that message by the polynomial, you get a zero remainder. In the realm of integers, 137 % 7 == 4. I subtract 4 from 137, I get 133. Then 133 % 7 == 0.

In this case there is pre and post-processing (the ^ 0xFFFFFFFF s). Then the result is not zero, but a different constant. That constant is simply the CRC of the message "00 00 00 00".

It should always end up with crc32 = 0x2144DF1C because of these two lines:

    crc = accumulatedCrc32 ^ 0xFFFFFFFF;

    return crc ^ 0xFFFFFFFF;

So when regenerating the crc again on data that contains the original data + crc, check for the value 0x2144DF1C . If those two lines had been:

    crc = 0;

    return crc;

then you would get a crc of zero if you ran the crc again on data + crc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM