CRC(Cyclic Redundancy Check)
CRC(循环冗余校验)
【参考资料】
https://en.wikipedia.org/wiki/Cyclic_redundancy_check
https://zh.wikipedia.org/wiki/循環冗餘校驗
https://info.support.huawei.com/info-finder/encyclopedia/zh/CRC.html
https://segmentfault.com/a/1190000018094567
1.字节序
字节序:https://zh.wikipedia.org/wiki/字节序
字节顺序,又称端序或尾序(英语:Endianness),在计算机科学领域中,指电脑内存中或在数字通信链路中,组成多字节的字的字节的排列顺序。
在几乎所有的机器上,多字节对象都被存储为连续的字节序列。例如在C语言中,一个类型为int
的变量x
地址为0x100
,那么其对应地址表达式&x
的值为0x100
。且x
的四个字节将被存储在电脑内存的0x100, 0x101, 0x102, 0x103
位置。[1]
1.1 大小端
字节的排列方式有两个通用规则。例如,将一个多位数的低位放在较小的地址处,高位放在较大的地址处,则称小端序;反之则称大端序。在网络应用中,字节序是一个必须被考虑的因素,因为不同机器类型可能采用不同标准的字节序,所以均按照网络标准转化。
变量x类型为int值为0x01234567
小端序 大端序
0x100 0x67 0x01
0x101 0x45 0x23
0x102 0x23 0x45
0x103 0x01 0x67
0x0A0B0C0D
大端序:
---------> 地址增长方向
....|0x0A|0x0B|0x0C|0x0D|....
小端序:
---------> 地址增长方向
....|0x0D|0x0C|0x0B|0x0A|....
<--------- 地址增长方向
....|0x0A|0x0B|0x0C|0x0D|....
最低有效位(LSB)是0x0D 存储在最低的内存地址处
混合序:32bit在PDP-11的存储方式
---------> 地址增长方向
....|0x0B|0x0A|0x0D|0x0C|....
高16bit和低16bit以大端序存储,但16bit内部以小端存储
1.2 处理器体系
x86、MOS Technology 6502、Z80、VAX、PDP-11等处理器为小端序;
Motorola 6800、Motorola 68000、PowerPC 970、System/370、SPARC(除V9外)等处理器为大端序;
ARM、PowerPC(除PowerPC 970外)、DEC Alpha、SPARC V9、MIPS、PA-RISC及IA64的字节序是可配置的。
1.3 网络序
网络传输一般采用大端序,也被称之为网络字节序,或网络序。IP协议中定义大端序为网络字节序。
Berkeley套接字定义了一组转换函数,用于16和32bit整数在网络序和本机字节序之间的转换。htonl,htons用于本机序转换到网络序;ntohl,ntohs用于网络序转换到本机序。
1.4 位序
小端序(先传低位)的串行协议
大端序(先传高位)的串行协议
2.循环冗余校验
https://zh.wikipedia.org/wiki/循環冗餘校驗
循环冗余校验( CRC )是一种错误检测代码,常用于数字网络和存储设备,用于检测数字数据的意外更改。进入这些系统的数据块会根据其内容的多项式除法的余数附加一个短校验值。在检索时,重复计算,如果检查值不匹配,则可以采取纠正措施来防止数据损坏。CRC 可用于纠错(请参阅位过滤器)。[1]
之所以称为 CRC,是因为校验(数据验证)值是一种冗余(它在不添加信息的情况下扩展消息)并且该算法基于循环码。CRC 很受欢迎,因为它们易于在二进制硬件中实现,易于进行数学分析,并且特别擅长检测由传输通道中的噪声引起的常见错误。因为校验值的长度是固定的,所以生成它的函数偶尔会被用作哈希函数。
当其校验值是n位长时,CRC 称为n位 CRC 。对于给定的n,可能有多个 CRC,每个都有不同的多项式。这样的多项式具有最高次数n,这意味着它有n + 1项。换句话说,多项式的长度为n + 1;它的编码需要n + 1位。请注意,大多数多项式规范会丢弃MSB或LSB,因为它们始终为 1。
最简单的错误检测系统,即奇偶校验位,实际上是一个 1 位的 CRC:它使用生成多项式 x + 1(两项),[3]并命名为 CRC-1。
2.1 数据完整性
CRC 专门设计用于防止通信通道上的常见错误类型,它们可以为所传递消息的完整性提供快速和合理的保证。但是,它们不适用于防止故意更改数据。
首先,由于没有身份验证,攻击者可以编辑消息并重新计算 CRC,而不会检测到替换。当与数据一起存储时,CRC 和加密哈希函数本身并不能防止对数据的故意修改。任何需要防止此类攻击的应用程序都必须使用密码身份验证机制,例如消息身份验证代码或数字签名(通常基于密码哈希函数)。
2.2 计算
In this example, we shall encode 14 bits of message with a 3-bit CRC, with a polynomial x3 + x + 1. The polynomial is written in binary as the coefficients; a 3rd-degree polynomial has 4 coefficients (1x3 + 0x2 + 1x + 1). In this case, the coefficients are 1, 0, 1 and 1. The result of the calculation is 3 bits long, which is why it is called a 3-bit CRC. However, you need 4 bits to explicitly state the polynomial.
Start with the message to be encoded:
11010011101100
This is first padded with zeros corresponding to the bit length n of the CRC. This is done so that the resulting code word is in systematic form. Here is the first calculation for computing a 3-bit CRC:
11010011101100 000 <--- input right padded by 3 bits
1011 <--- divisor (4 bits) = x³ + x + 1
------------------
01100011101100 000 <--- result
The algorithm acts on the bits directly above the divisor in each step. The result for that iteration is the bitwise XOR of the polynomial divisor with the bits above it. The bits not above the divisor are simply copied directly below for that step. The divisor is then shifted right to align with the highest remaining 1 bit in the input, and the process is repeated until the divisor reaches the right-hand end of the input row. Here is the entire calculation:
11010011101100 000 <--- input right padded by 3 bits
1011 <--- divisor
01100011101100 000 <--- result (note the first four bits are the XOR with the divisor beneath, the rest of the bits are unchanged)
1011 <--- divisor ...
00111011101100 000
1011
00010111101100 000
1011
00000001101100 000 <--- note that the divisor moves over to align with the next 1 in the dividend (since quotient for that step was zero)
1011 (in other words, it doesn't necessarily move one bit per iteration)
00000000110100 000
1011
00000000011000 000
1011
00000000001110 000
1011
00000000000101 000
101 1
-----------------
00000000000000 100 <--- remainder (3 bits). Division algorithm stops here as dividend is equal to zero.
每一次Xor都是固定不动的生成项与其对应的数据首位“消1”。
那我们就可以假想出一个与生成项长度一致的“盒子”,取出一部分的数据出来若首位是1时就进行一次Xor,遇到0则左移到1为止,左移造成的右端的空缺用0补充。而这里0希望理解为一种“存储”,它“存储” 生成项中未和数据进行计算的那一部分,按顺序先后附加被计算数据的后面,当先一部分的数据全部计算之后,实际上“盒子”中剩下都是未和数据计算的部分的“和”11011 xor 10110 = 11011 xor ( 10000 xor 00100 xor 00010)(这里实际上就是Xor的交换律到后面就会体会到他的强大)
2.3 数学公式
CRC为校验和的一种,是两个字节数据流采用二进制除法(没有进位,使用XOR来代替减法)相除所得到的余数。其中被除数是需要计算校验和的信息数据流的二进制表示;除数是一个长度为的预定义(短)的二进制数,通常用多项式的系数来表示。在做除法之前,要在信息数据之后先加上个0。
CRC是基于有限域GF(2)(即除以2的同余)的多项式环。简单的来说,就是所有系数都为0或1(又叫做二进制)的多项式系数的集合,并且集合对于所有的代数操作都是封闭的。例如:
2会变成0,因为对系数的加法运算都会再取2的模数。乘法也是类似的:
同样可以对多项式作除法并且得到商和余数。例如,如果用x3 + x2 + x除以x + 1。会得到:
也就是说,
等价于
这里除法得到了商x2 + 1和余数-1,因为是奇数所以最后一位是1。
字符串中的每一位其实就对应了这样类型的多项式的系数。为了得到CRC,首先将其乘以,这里n是一个固定多项式的阶数,然后再将其除以这个固定的多项式,余数的系数就是CRC。
在上面的等式中,表示了本来的信息位是111
, 是所谓的钥匙,而余数1也就是就是CRC. key的最高次为1,所以将原来的信息乘上来得到,也可视为原来的信息位补1个零成为1110
。
一般来说,其形式为:
这里M(x)是原始的信息多项式。K(x)是阶的“钥匙”多项式。表示了将原始信息后面加上个0。R(x)是余数多项式,即是CRC“校验和”。在通信中,发送者在原始的信息数据M后附加上�位的R(替换本来附加的0)再发送。接收者收到M和R后,检查是否能被整除。如果是,那么接收者认为该信息是正确的。值得注意的是就是发送者所想要发送的数据。这个串又叫做codeword.
CRCs经常被叫做“校验和”,但是这样的说法严格来说并不是准确的,因为技术上来说,校验“和”是通过加法来计算的,而不是CRC这里的除法。
2.4 CRC8
https://github.com/QLiwei/Embedded/tree/main/components/crc/crc8