Algorithm 一种循环冗余校验算法,对具有特定非零值的尾随字节数保持不变

Algorithm 一种循环冗余校验算法,对具有特定非零值的尾随字节数保持不变,algorithm,crc,transport,error-detection,Algorithm,Crc,Transport,Error Detection,假设我有一个任意的字节块。使用CRC-16-CCITT算法在整个块上计算CRC余数终止该块,其中余数按大端字节顺序排列。在块和余数之后,有任意数量的零字节,一直持续到字节流结束 这种安排利用了这种CRC算法的某些特性,这种特性通常被认为是不可取的:它不区分具有不同尾随零数的消息,只要消息以其余数终止(在我的情况下)。这允许接收方断言数据的正确性,而不考虑流中的尾随字节数 以下是一个例子: >>> hex(crc(b'123456789')) #

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

这种安排利用了这种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)编码的介质进行交换:介质层在相同级别的每五个连续数据位之后注入一个填充位,其中填充位的极性与前面的位相反;e、 g.
00000000
的值作为
000001000
传输。位填充非常不受欢迎,因为它会增加开销

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

以下是标准CRC-16-CCITT算法,naive实现,仅供参考:

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

我的问题如下:通过引入这种修改,我是否会损害算法的错误检测特性?我还应该注意到其他缺点吗?

在标准的错误模型(以固定概率独立翻转位)下,没有缺点。很难预料到实际困难

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