使用 binascii.crc32() 验证校验和

Validating the checksum using binascii.crc32()

我正在从 MCU 向我的计算机发送多条消息,我想使用 32 位循环冗余校验来验证消息是否正确。从我读过的内容来看,应该可以将 CRC 余数附加到最后一条消息,然后 运行 通过 CRC 函数。如果消息没有错误,那么它应该 return 为零(我说的对吗?) 然而,我使用 binascii 库函数 binascii.crc32().

未能成功实现此功能

例如,假设我想从 Python 文档中给出的示例内部检查消息(我使用的是 Python 3.5)。我将如何继续检查消息是否没有错误(在本例中当然是错误的)?

crc = binascii.crc32(b"hello")
crc = binascii.crc32(b" world", crc)

check_for_error() # <--- ?

简单的方法是将字节形式的 CRC 附加到消息中。然后,当您收到消息时,计算除消息的最后 4 个字节以外的所有字节的 CRC,并将其与附加的 CRC 字节进行比较。当然,这比您想做的要复杂一些,但是您可以将该策略应用于加密哈希,例如 MD5 或 SHA 系列。

但是,要执行您要求的操作,您需要通过从 0xffffffff 中减去它来反转 CRC32,然后再将其转换为字节并附加它。 CRC32 实际上是一个反向 CRC,它可以防止全零字节的消息具有零 CRC。在解码时,如果数据的 CRC + CRC 等于 0xffffffff,则消息 可能 有效。

Python CRC32 文档建议您使用

crc32(data) & 0xffffffff

而不是

crc32(data)

确保您在所有 Python 版本和平台上获得相同的数值。

这是一个快速 Python 3 演示。

import binascii

maxcrc = 0xffffffff

def inverse_crc(data):
    crc = binascii.crc32(data) & maxcrc
    invcrc = maxcrc - crc
    return invcrc.to_bytes(4, 'little')

def check_crc(data):
    return binascii.crc32(data) & maxcrc == maxcrc    

#Test

data = b"Hello, world"
newdata = data + inverse_crc(data)
print(check_crc(newdata))
newdata = b'0x00' + newdata
print(check_crc(newdata))

输出

True
False

请注意,您可能会得到误报:损坏的消息可能具有正确的 CRC。如果您需要更高级别的保护,您应该使用加密散列。这仍然不完美,但如此大的哈希值出现误报的几率 极低 。当然,计算 MD5 或 SHA 散列 比计算 CRC32 慢很多