Validation 将任意数量的零添加到缓冲区的特定位置赢得';请不要更改CRC

Validation 将任意数量的零添加到缓冲区的特定位置赢得';请不要更改CRC,validation,math,crc,Validation,Math,Crc,我们刚刚发现了CRC算法中的一个主要缺陷,而我在网上找不到任何提到它的文章 简而言之,当前一个字节的crc结果为零时,缓冲区中每一个值为零的后续字节只会触发crc上的一个“移位位”,该移位位将保持为零且不会改变 我们使用CRC16 CCITT算法,起始值为0xFFFF,多项式为0x8408(等效代码),但我认为它适用于任何CRC算法 ex: FF FF = 0xFFFF FF FF 00 = 0xFFFF FF FF 00 00 00

我们刚刚发现了CRC算法中的一个主要缺陷,而我在网上找不到任何提到它的文章

简而言之,当前一个字节的crc结果为零时,缓冲区中每一个值为零的后续字节只会触发crc上的一个“移位位”,该移位位将保持为零且不会改变

我们使用CRC16 CCITT算法,起始值为0xFFFF,多项式为0x8408(等效代码),但我认为它适用于任何CRC算法

ex:
FF FF                 = 0xFFFF
FF FF 00              = 0xFFFF
FF FF 00 00 00        = 0xFFFF

FF FF BB              = 0xA7F4
FF FF 00 00 00 00 BB  = 0xA7F4
但是,在其他任何地方添加额外的零将改变结果:

FF FF BB 00           = 0x3921
这是一个简单的示例,但它可能发生在前一个字节的结果crc为0的任何数据缓冲区中(在进行最终反转之前),以下零字节将不计入结果值

幸运的是,我们的应用程序数据包总是以FF 00开始,有时(在数千个数据包之后)硬件级别(RS-485通信)的00被切断,这在我们的应用程序中造成了一些重大问题,但CRC是有效的,所以我们不认为这是可能的

  • 这是一个众所周知的问题吗
  • 有什么简单的方法可以防止这种情况吗?我知道我们可以添加缓冲区长度并验证它,但我很好奇人们通常会做什么

将缓冲区长度也添加到CRC中如何?可能比单独传递要简单一些。此外,在我维护的固件更新程序上,我们使用CRC和版本号进行比较,这有助于我们处理冲突。显然,您的用例是不同的……不清楚您实际上指的是什么CRC。链接到的CRC使用的多项式形式为
0x1021
,而不是
0x8408
。您命名的CRC CRC-16 CCITT使用
0x8408
,但将寄存器初始化为零。您描述的CRC听起来像X-25,它使用
0x8408
,将初始化为
0xffff
,并使用
0xffff
对结果进行异或。这是三个不同的CRC。那么您实际使用的是什么呢?我不确定他是从哪里得到CRC 0xA7F4的,但是他提供的字节序列可以重现这个问题。无论插入多少个零字节,CRC总是
0x16B0
。事实上,以
0x1D0F
开头的序列会导致0x1D0F CRC显示相同的行为。Dark Falcon(第一条评论):将长度添加到CRC计算中不会解决零的问题。版本号也不会。无论如何,您都需要单独验证长度。马克·阿德勒:你可以使用任意多边形/起始数字来计算CRC,只要两个设备使用相同的数字。以FFFF开头的CCITT反转实际上非常常见,谷歌it。问题是任何东西都会再生。黑暗猎鹰(第二条评论):谢谢,至少你看到了问题所在。我真的很想知道这是否是一个已知的行为,请参阅相关文章。哦,您得到了0x16B0,因为该站点使用的是正常的0x1021多项式,而不是反向的0x8408(请参阅)。