How to get ethernet magical number 0xC704DD7B from zlib crc32 calculator

0

I took a python snippet from this answer (slightly modified) to calculate an ethernet crc32 frame check sequence:

msg = '00'
data = bytes.fromhex(msg)
print(data)
print(msg)
crc = zlib.crc32(data)&0xFFFFFFFF
for i in range(4):
    b = (crc >> (8*i)) & 0xFF
    print('{:02X}'.format(b))

For the message 00 it outputs 8D EF 02 D2, which is the bit-reverse solution from this answer. So far so good.

Now it is said here, that

Running the CRC algorithm over the received frame data including the CRC code will always result in a zero value for error-free received data, because the CRC is a remainder of the data divided by the polynomial. However, this technique can fail to detect errors, in which data with trailing zeroes will also result in the same zero remainder. To avoid this scenario, the FCS is complemented (each bit is negated) by the sender before it is attached to the end of the payload data. This way, the algorithm result will always be a CRC32 residue of 0xC704DD7B when data has been received correctly.

But if I input 00 8D EF 02 D2 into the calculator, the result is 1C DF 44 21, not the said residue. I also tried other combinations, because oftentimes the bits in bytes have to be reversed or whatever (I am actually really confused about all this reversing stuff, but I hoped, a good result after trial several possibilities would guide me to the right reversals), but without any success:

00 D8 FE 20 2D -> 66 40 C3 4A
00 D2 02 EF 8D -> DF 42 14 03
00 2D 20 FE D8 -> CB 50 00 AE

So, can anyone tell me, where I am wrong?

python
zlib
ethernet
crc
crc32
asked on Stack Overflow Jan 28, 2020 by Peter Lehnhardt • edited Jan 28, 2020 by rcgldr

1 Answer

2

The 0xC704DD7B that was in the Wiki article is the bit reversed and complement of 0x2144DF1C, which is the value you are getting and the value you should get.

In the case of CRC32, since the CRC is post complemented, a "good" CRC recalculation performed on data + a previously calculated CRC will be a non-zero constant, in this case, 0x2144DF1C. It's not a "magic number", the non-zero constant value for a good CRC is the consequence of post-complementing the CRC (otherwise a good recalculated CRC would be zero).


What makes this confusing is that the IEEE standard uses the left shifting CRC32 BZIP2 (non reversed) CRC to create the CRC, then states data is transmitted least significant bit first, while the CRC (called FCS (Frame Check Sequence)) is transmitted most significant bit (bit 31) first. Using the right shifting CRC32 (reversed) CRC produces the same CRC but bit reversed, and transmitting both data and CRC least significant bit first results in identical transmission. So depending on the actual implementation, the CRC may be reversed or not, and may or may not be complemented if using the "residue" in a hardware register.

The wiki article is now updated to include these issues.

answered on Stack Overflow Jan 28, 2020 by rcgldr • edited Jan 31, 2020 by rcgldr

User contributions licensed under CC BY-SA 3.0