数据一致性校验算法
- 数据完整性校验
在 数据录入、通信协议(CAN、LIN、Ethernet) 和 存储(Flash、EEPROM) 领域,数据校验(Error Checking) 是确保 数据完整性和正确性的关键技术
示例:当我们从互联网上下载的软件或者文件是否能打开,是否在传输过程中丢包决定了是否能使用和查看,很多资源站下载文件时会提供一个md5校验码,验证文件是否完整可以通过md5 文件获取到校验码,与下载站提供的校验码一致就能确定文件是完整的。
以下部分将提供几种常用的完整性校验的技术:
· 奇偶校验(Parity Check) - 用于简单错误检测
奇偶校验是一种简单的错误检测机制,它通过计算数据中 1 的个数来检查数据是否发 生错误。
适用于低速数据传输(如 LIN 总线、UART 通信)
常用于加密技术,如:des加密技术
奇偶校验的基本原理:
奇偶校验通过统计数据中1的个数,然后添加一位校验码,使得数据中1的总数为奇数(奇校验)或偶数(偶校验)。当接收方接 收到数据后,再次计算1的个数,并根据校验位的设置验证数据的完整性。如果检测到错误,接收方会要求重新发送数据
代码实现:
计算奇偶校验
uint8_t Compute_Parity(uint8_t data)
{
uint8_t parity = 0;
while (data)
{
parity ^= (data & 1); // 计算 1 的个数
data >>= 1;
}
return parity;
}
发送数据:
uint8_t data = 0x53; // 01010011
uint8_t parity = Compute_Parity(data);
uint8_t frame = (data << 1) | parity; // 生成带校验位的数据
接收数据:
uint8_t received_data = frame >> 1;
uint8_t received_parity = frame & 1;
if (Compute_Parity(received_data) != received_parity)
{
printf("数据错误!\n");
}
以DES技术实现原理为例:
DES特点
对称算法:加密和解密使用同一秘钥
分组加密算法:以64位为分组。64位明文输入,64位密文输出。
有效秘钥长度为56位秘钥通常表示为64位数,但每个第8位用作奇偶校验,可以忽略。
代替和置换DES算法是两种加密技术的组合:混乱和扩散。先替代后置换。
易于实现:DES算法只是使用了标准的算术和逻辑运算,其作用的数最多也只有64 位,因此用70年代末期的硬件技术很容易实现算法的重复特性使得它可以非常理想地用在一个专用芯片中。
可通过多重加密,提高安全等级
入口参数
Key为7个字节共56位,是DES算法的工作密钥
Data为8个字节64位,是要被加密或被解密的数据
Mode为DES的工作方式,有两种:加密或解密
基本原则
DES设计中使用了分组密码设计的两个原则:混淆(confusion)和扩散(diffusion),其目的是抗击敌手对密码系统的统计分析。
混淆是使密文的统计特性与密钥的取值之间的关系尽可能复杂化,以使密钥和明文以及密文之间的依赖性对密码分析者来说是无法利用的。
扩散的作用就是将每一位明文的影响尽可能迅速地作用到较多的输出密文位中,以便在大量的密文中消除明文的统计结构,并且使每一位密钥的影响尽可能迅速地扩展到较多的密文位中,以防对密钥进行逐段破译。
算法描述
输入64位明文数据,并进行初始置换IP
在初始置换IP后,明文数据再被分为L0和R0左右两部分,每部分32位
在秘钥的控制下,经过16轮运算(f)
16轮后,左、右两部分交换,并连接再一起,再进行逆置换
输出64位密文
DES算法过程
子密钥生成流程
DES算法由64位密钥产生16轮的48位子密钥。主要过程如下:
把密钥的奇偶校验位忽略不参与计算,即每个字节的第8位,将64位密钥降至56位,然后根据选择置换表PC-1将这56位分成两块C0(28位)和D0(28位)
将C0和D0进行循环左移变化(注:每轮循环左移的位数由轮数决定),变换后生成C1和D1,然后C1和D1合并,并通过选择置换表PC-2生成子密钥K1(48位)
C1和D1再次经过循环左移变换,生成C2和D2,然后C2和D2合并,通过选择置换PC-2生成密钥K2(48位)
以此类推,得到K16(48位)
· CRC 校验(Cyclic Redundancy Check) - 用于强校验
CRC(Cyclic Redundancy Check,循环冗余校验)是一种强大的错误检测机制,用于检测 数据传输 / 存储中的错误。
广泛应用于 CAN 总线、LIN、FlexRay、Ethernet、Flash 存储。
CRC 校验步骤
发送端计算 CRC 值,并将其附加到数据帧。
接收端重新计算 CRC,如果计算出的 CRC 与收到的 CRC 不一致,则数据错误
Crc-8计算:
uint8_t CRC8_Table[256] = { /* 预计算的 CRC-8 查找表 */ };
uint8_t Compute_CRC8(uint8_t* data, uint8_t len)
{
uint8_t crc = 0xFF;
for (int i = 0; i < len; i++)
{
crc = CRC8_Table[crc ^ data[i]];
}
return crc;
}
发送crc:
uint8_t message[] = {0x12, 0x34, 0x56};
uint8_t crc = Compute_CRC8(message, sizeof(message));
message[3] = crc; // 附加 CRC
接收crc:
uint8_t received_crc = message[3];
if (Compute_CRC8(message, 3) != received_crc)
{
printf("数据错误!\n");
}
· Checksum(校验和) - 用于简单完整性校验
Checksum(校验和) 是一种简单的错误检测方法,它将 所有数据的二进制数值相加,并将 结果的低字节作为校验和。
三种完整性校验对比:
校验方法 | 适用场景 | 优点 | 缺点 |
奇偶校验 | UART、LIN | 计算简单 | 只能检测 1-bit 错误 |
Checksum | EEPROM、Flash | 计算快,适合小数据 | 不能检测位翻转 |
CRC | CAN、Ethernet、UDS | 高精度错误检测 | 计算复杂 |
根据业务具体场景选择使用哪种校验算法
- 数据可靠性传输
Tcp可靠性传输协议
通道的建立——三次握手:
(1)在建立通道时,客户端首先要向服务端发送一个SYN同步信号。
(2)服务端在接收到这个信号之后会向客户端发出SYN同步信号和ACK确认信号。
(3)当服务端的ACK和SYN到达客户端后,客户端与服务端之间的这个“通道”就会被建立起来。
通道的关闭——四次挥手:
(1)在数据传输完毕之后,客户端会向服务端发出一个FIN终止信号。
(2)服务端在收到这个信号之后会向客户端发出一个ACK确认信号。
(3)如果服务端此后也没有数据发给客户端时服务端会向客户端发送一个FIN终止信号。
(4)客户端在收到这个信号之后会回复一个确认信号,在服务端接收到这个信号之后,服务端与客户端的通道也就关闭了。
Tcp保证可靠性策略
· 确认应答机制(核心)
确认应答机制就是由Tcp报头字段中的32位序号和32位确认序号来保证的
注意:确认应答机制不是保证双方的通信的可靠性,而是通过收到对方应答,来保证一方通信的可靠性,但是如果双方都这样搞,就是间接保证了双方通信的可靠性
确认应答机制前面已经大量涉及了,这里不再赘述了,只要记住,确认应答机制是Tcp保证可靠性的核心,或者说是基础,其余绝大部分的保证可靠性机制都是建立在确认应答机制基础上的
· 超时重传机制
定义:双方在进行网络通信时,发送方发出数据,如果在一个特定时间间隔内收不到应答,那么发送方就认为“我发的数据对方没有收到”,就会进行数据重发
附:Tcp保证可靠性一部分是通过Tcp协议报头体现出来的,还有一部分是通过实现Tcp的代码逻辑实现出来的,比如超时重传机制就是在发送方发出数据后开启了一个定时器,这就是通过Tcp的代码逻辑体现出来的,这在Tcp报头中是体现不出来的