Cyclic Redundancy Check, CRC 循环冗余校验,通常用于网络、文件等校验,校验码的长度固定,而且从检错的正确率与速度成本之间比较好的平衡,使其称为当前最常见的数据校验方式。
模二运算
这是针对计算机的算法,其与算术运算相似,支持加减乘除四则运算,不过无进位和借位 (Carry Less),而 CRC 采用的是模二除法,实际计算结果与异或 XOR 相同。
手动计算
假设数据为 0xC2 = b11000010
,对应被除数为 0x1D5 = b 111010101
,那么计算如下。
1100001000000000 --> 通过0补齐长度
111010101.......
--------
001010001.......
111010101.....
--------
010010001.....
111010101.... --> A
---------
011110111....
111010101...
--------
000111011...
111010101 --> B
---------
000001101 --> 0x0D
计算时只需要对齐首位非零即可,可能只需要移动一位,如 A 所示;也可能会移动多个位,如 B 所示。计算结果实际上只关注余数,而除数则不关注。
将上述的校验值添加到消息的末尾,接受方以同样的方式计算。
1100001000001101 --> 数据保存传输时将结果保存
111010101.......
--------
001010001.......
111010101.....
--------
010010001.....
111010101....
---------
011110111....
111010101...
--------
000111010...
111010101
---------
000000000 --> 0x00
如果计算结果为 0 则表示数据传输正常。
也就是说,将实际数据作为除数,根据校验算法确定被除数,余数就作为校验值,不过需要注意,CRC 校验并不是单纯的模二除法,初始值会向左移位,同时不要求最后除尽,只要对齐至最后一位即可,如果长度不满足则前面补零。
多项式表达
计算 CRC 需要先确定参数模型,通常有如下的几个:
- NAME 参数模型名称,通常会表示位数以及部分注解,例如 CRC-8、CRC-8-ATM 等。
- WIDTH 宽度,即生成的 CRC 数据位宽,如上的 CRC-8 生成的 CRC 就是 8 位。
- POLY(Polynomial) 十六进制多项式,一般省略最高位 1,如
x8+x7+x6+x4+x2+1
,二进制对应1 1101 0101
,省略最高位转换为十六进制为0xD5
。 - INIT 初始值,和 WIDTH 位宽一致。
- REFIN (Input Reflected) 计算前原始数据是否翻转,例如原始数据
0x34 = 00110100
翻转后为00101100 = 0x2c
。 - REFOUT (Result Reflected) 运算完成之后,得到的 CRC 值是否进行翻转,注意这里是对整个结果进行翻转。
- XOROUT 计算结果与此参数进行异或运算后得到最终的 CRC 值。
参考
- crccalc.com 在线计算
- Understanding and implementing CRC (Cyclic Redundancy Check) calculation 包括了很多的基本概念,例如 Reversed、Reciprocal 等