Verification of a CRC checksum against zero

2

I had some contact with the CRC-16 checksum in the past and was accustomed to verifying it by recalculating the CRC-16 checksum over the file I want to verify, plus the 2 bytes of the CRC-16 itself. If the result was zero, then the file integrity was valid, otherwise not.

This can be coded very efficiently like with the following pseudo-C:

if (recalculated_crc16_checksum != 0) // Error: file integrity is corrupt else // Success: file integrity is valid

I recently wanted to use the CRC-32 checksum for a file integrity check and tried to verify it the same way, but it seems like this "Compare-Against-Zero-Trick" is not possible here?!

For example if I use the 32-Bit value 0xDEADBEEF on the CRC online calculator:

CRC-16-Modbus(0xDEADBEEF) = 0xC19B (Same input value but with appended checksum 0xC19B in reversed byte ordering) CRC-16-Modbus(0xDEADBEEF9BC1) = 0x0000

But:

CRC-32(0xDEADBEEF) = 0x7C9CA35A (I tried both: big and little endian byte ordering for the appended checksum) CRC-32(0xDEADBEEF7C9CA35A) = 0x01F92292 != 0x00000000 CRC-32(0xDEADBEEF5AA39C7C) = 0x2144DF1C != 0x00000000

Can someone please explain me, why this "Compare-Against-Zero-Trick" does not work for CRC-32?

c
checksum
crc
crc32
crc16
asked on Stack Overflow Oct 15, 2019 by user9564464 • edited Oct 15, 2019 by user9564464

1 Answer

9

The issue is not that the CRC is 32 bit, but that the CRC is post-complemented, xorout = 0xffffffff. If you append the CRC (little endian), to the message and then compute the CRC again, if there are no errors, the CRC will always be 0x2144DF1C. So in this case you verify the CRC against 0x2144DF1C.

You might find this online CRC calculator a bit more informative, since it shows the parameters: polynomial, xorin, xorout.

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

To explain what is going on, normally if you calculate and append a non-complemented CRC to a message, then calculate the CRC of the message + CRC, the resulting CRC is zero (if there are no errors). Let CRC32X = a custom CRC32 with initial value = 0 and xorout = 0. You can copy and paste the data below with the online CRC calculator I posted a link to.

CRC32X{0x31 0x32 0x33 0x34} = 0xBAA73FBF

appending the CRC and calculating again:

CRC32X{0x31 0x32 0x33 0x34 0xBF 0x3F 0xA7 0xBA} = 0x00000000

Now consider a simpler case:

CRC32X{0x00 0x00 0x00 0x00} = 0x00000000
CRC32X{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} = 0x00000000

Then to see the effect of complementing the CRC and appending it:

CRC32X{0x00 0x00 0x00 0x00 0xFF 0xFF 0xFF 0xFF} = 0xDEBB20E3

and taking the complement (using ~ for not):

~CRC32X{0x00 0x00 0x00 0x00 0xFF 0xFF 0xFF 0xFF} = ~0xDEBB20E3 = 0x2144DF1C

The initial value is XOR'ed with the first 4 bytes of the message. So for CRC32() with initial value of 0xFFFFFFFF, and post complemented CRC:

 CRC32(0x00 0x00 0x00 0x00) = 0x2144DF1C 
~CRC32X(0xFF 0xFF 0xFF 0xFF) = ~0xDEBB20E3 = 0x2144DF1C
answered on Stack Overflow Oct 15, 2019 by rcgldr • edited Oct 16, 2019 by rcgldr

User contributions licensed under CC BY-SA 3.0