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?
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
User contributions licensed under CC BY-SA 3.0