一种循环冗余码校验算法,该算法与具有特定非零值的尾随字节数不变

时间:2018-06-25 09:30:35

标签: algorithm crc transport error-detection

假设我有一个任意的字节块。该块以使用CRC-16-CCITT算法在整个块上计算出的CRC余数终止,其中余数按big-endian字节顺序排列。在该块和其余部分之后,有任意数量的零字节一直持续到字节流结束。

这种安排利用了通常被认为是不受欢迎的CRC算法的某些特性:如果消息以其剩余部分终止(在我的情况下),它不会区分具有不同尾随零数字的消息。 。这使接收器可以断言数据的正确性,而与流中的尾随字节数无关。

这里是一个例子:

>>> hex(crc(b'123456789'))                 # Computing the remainder
'0x29b1'
>>> hex(crc(b'123456789\x29\xb1'))         # Appending the remainder in the big-endian order
'0x0'                                      # If the remainder is correct, the residual value is always zero
>>> hex(crc(b'123456789\x29\xb1\x00\x00')) # ...and it is invariant to the number of trailing zeros
'0x0'
>>> hex(crc(b'123456789\x29\xb1\x00\x00\x00'))
'0x0'

这是我所希望的行为。但是,在我的应用程序中,数据是通过使用非归零(NRZ)编码的介质交换的:介质层在相同级别的每五个连续数据位之后注入一个填充位,填充位与前面的位相反;例如00000000的值作为000001000发送。填充位是非常不希望的,因为它会增加开销。

为了利用CRC算法对尾随数据的不变性(用于填充)并避免位填充,我打算将每个数据字节与0x55进行异或运算(尽管它可以是任何其他位模式)这样可以避免填充),然后再更新CRC余数,然后将最终的余数与0x5555进行异或。

作为参考,这是标准的CRC-16-CCITT算法,朴素的实现:

def crc16(b):
    crc = 0xFFFF
    for byte in b:
        crc ^= byte << 8
        for bit in range(8):
            if crc & 0x8000:
                crc = ((crc << 1) ^ 0x1021) & 0xFFFF
            else:
                crc = (crc << 1) & 0xFFFF
    return crc

这是我的修改,它使用0x55对输入和输出进行异或:

def crc16_mod(b):
    crc = 0xFFFF
    for byte in b:
        crc ^= (byte ^ 0x55) << 8
        for bit in range(8):
            if crc & 0x8000:
                crc = ((crc << 1) ^ 0x1021) & 0xFFFF
            else:
                crc = (crc << 1) & 0xFFFF
    return crc ^ 0x5555

简单检查即可确认修改后的算法的行为符合预期:

>>> print(hex(crc16_mod(b'123456789')))         # New remainder
0x954f
>>> print(hex(crc16_mod(b'123456789\x95\x4f'))) # Appending the remainder; residual is 0x5555
0x5555
>>> print(hex(crc16_mod(b'123456789\x95\x4f\x55\x55\x55'))) # Invariant to the number of trailing 0x55
0x5555
>>> print(hex(crc16_mod(b'123456789\x95\x4f\x55\x55\x55\x55'))) # Invariant to the number of trailing 0x55
0x5555

我的问题如下:通过引入此修改是否会损害算法的错误检测属性?我还有其他需要注意的缺点吗?

1 个答案:

答案 0 :(得分:1)

在错误的标准模型下(位以固定的概率独立翻转),没有不利之处。很难预见实际困难。