如何应用 xmodem CRC 生成和校验

How to apply xmodem CRC on generating and checking

我已经迭代了很多文章 - 出于某种原因,我找不到任何描述必须是一个简单过程的文章:如何将计算出的 CRC 与原始消息结合起来,以便再次计算 CRC 结果0(=检查正确)?我确实找到了几个使用 'longhand' 计算的示例(仅 2 位或 3 位 CRC),但没有使用库函数的示例,例如 [crcmod][1](Python 库)。

这是我编写的一个简单程序来检查它:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#

import crcmod

def test_cycle():
    test_str = b"123456789"
    orig_msg = test_str
    print("Original message: {:s}".format(orig_msg.hex()))

    #~ crc_calc = crcmod.predefined.Crc('xmodem')
    crc_calc = crcmod.Crc(
                0x11021,
                rev = False,
                initCrc = 0x0000,
                xorOut = 0x0000)

    crc_calc.update(orig_msg)
    print("CRC: {:04x}".format(crc_calc.crcValue))

    lo = crc_calc.crcValue & 0xff
    hi = crc_calc.crcValue >> 8
    new_msg = test_str + bytes((hi, lo))
    print("Crc appended: {:s}".format(new_msg.hex()))

    crc_calc.update(new_msg)
    print("CRC: {:04x}".format(crc_calc.crcValue))


def main(args):
    test_cycle()
    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

有一些注释行,来自不同字节顺序的实验。该程序的结果是:

Original message: 313233343536373839
CRC: 31c3
Crc appended: 31323334353637383931c3
CRC: 00ef

第一个 CRC (31C3) 似乎符合 the expected values for xmodem-CRC。我尝试了很多方法,将获得的 CRC 与原始字符串结合起来,但从未获得 '0'。我在这里遗漏了什么吗?

crc_calc.update(new_msg)new_msg 的全部内容添加到 CRC。由于 crc_calc 已经包含 313233343536373839 的结果,您实际上是在计算 31323334353637383931323334353637383931c3 的 CRC,这确实是 00ef.

要仅将两个字节添加到计算中,请使用

crc_calc.update(bytes((hi, lo)))

或者,使用 crcmod.Crc() 的新实例,或者在进行新计算之前重置现有实例的 crcValue

crc_calc.crcValue = 0
crc_calc.update(new_msg)

两者都会给你结果 0

对于那些想知道附加 CRC 的人的一些背景知识。

如果 CRC 正确地 附加到作为 CRC 的消息,并且消息或 CRC 中没有引入错误,则整个 CRC将是一个常量,仅取决于该 CRC 的定义。

正确追加 CRC,需要注意位排序。对于 crcmod 提供的通用 CRC 定义,如果 rev 为假,则必须首先附加 most 有效位。如果 rev 为真,则必须首先附加 least 位。对于面向字节的消息,这首先意味着 CRC 的宽度必须是八位的倍数(顺便说一句,这是 crcmod 所允许的),并且 CRC 附加在大端顺序或小端顺序。

结果 常数 并不总是零,这取决于 CRC 的定义。如果 CRC 的 xorOut 值为零,则 零。否则常数是 n 零位的 CRC,其中 n 是 CRC 的宽度,并且提供的初始 CRC 值为零( 不是initCrc)。例如,对于标准 CRC-32,以小端顺序附加 CRC-32 的消息的 CRC-32 总是 0x2144df1c.

对于这个特定问题,CRC 以大端顺序附加,因此 31 c3,结果消息的 CRC + CRC 为零。