一、数据通信和安全
计算机的威力在于处理各种数据然后执行各种工作,而计算机本身和人一样,它不但能处理内部的数据也能够从外部各种接或硬件设施获取数据。而后者往往是数据获取的主要来源,比如常见的网络、USB接口(U盘等)设备以及老掉牙的串口数据等。
大家都知道,现实世界中人和人通过声音可以传递信息,但往往由于各种原因导致声音传递出现问题,比如没听清或干脆没听见。这就需要其它的方式来补救一下,比如没听清就要求对方再发一次。而没听清,其实就可以认为是人体进行了一次安全校验,但数据通信没有通过。
同样,计算机也存在着这种风险。比如数据传递的过程出现了丢失或增加(丢失可能是大多数,但在某些被攻击的场景下也会增多,比如注入)。那么同样需要通信的双方需要对数据增加一种安全的处理机制,防止出现非法数据(有恶意或无恶意的)的处理导致的各种意外。
二、数据校验和算法
上面提到的这种处理机制中,数据校验就是一种非常普遍的方式。所谓数据校验,就是对数据通过指定的算法进行分析,确保发送的收发的数据的完整性和一致性。它主要包括三个方面:数据的完整性;数据的一致性和错误检测及纠正。
一般来说,搞硬件开发和搞网络开发的,可能对这种数据校验比较熟悉。毕竟这两种环境都是相对来说数据传输风险比较大的。数据校验的算法在学通信的相关书籍中非常多,搞计算机的反而不是很普遍,不过也有相关的介绍。
数据校验的相关算法可以分成两大类,一类是专门检测错误;另外一类还可以在一定范围内对错误进行纠正。但对于大多数的开发人员来说都不会专门从事数据通信,所以遇到的大多与数据错误检测相关。常见的数据检验的算法有:
- 校验和
比较好理解,就是发送方以某个单位(比如字节或字)进行相加,然后将其结果追加在数据的末端即可。接收方接收到数据后做同样的运算然后与末端的结果比对,一致为正确,否则数据有问题。它的优势在于实现简单,计算速度快,容易实现。缺点是校验错误的能力较低,假如两个不同位置的数据的改变能够互相抵消,则错误就无法发现。 - 奇偶校验
可以简单理解成位的和校验,就是在数据位增加一个数据整体单元(包括校验位本身)中1的数量,奇数为奇校验;反之为偶校验。它的优点是实现非常简单且效率极高;缺点是校验错误的能力非常低。简单想一下,如果奇偶位成对错误则无法正常检测相关的错误。 - CRC校验
CRC检验是一种非常强大的错误检测算法,但它的成本也相对要高很多。它采用多项式的处理方式来进行工作。优点是校验错误的能力极强,但一般情况下需要使用硬件实现才会效率很高。缺点是只能检测错误,并在某种程度上依赖硬件。
当然,具体的哪种算法有什么特点?如何实现的?大家可以参看相关的书籍,这都是非常成熟的技术,没有什么门槛。除了上面提到的三种算法,其实还有一些算法,如书上提到的海明码等,都是比较专业的用法,平时是不容易遇到的。
三、实际应用
上面的这些算法应用的场景其实也是非常多的,下面简单说明一下:
- 校验和
和的校验一般在一些低速的硬件通信,如串口中应用非常多。另外在网络协议的头部校验中也经常看。其它一些对数据校验不太严格的地方,如网络的应用层上,都推荐使用。 - 奇偶校验
奇偶校验其实如果不是搞硬件的可能用到的真不多,它主要是用在低速的硬件通信中,特别是串口通信中。 - CRC校验
CRC校验应用就非常多了,比如常见的网络通信、数据的磁盘存储和压缩文件以及图像处理等中都应用非常广泛。
四、例程
根据这些算法,看一个CRC校验简单的应用:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
// CRC32
uint32_t crc32(const uint8_t *checkData, size_t len) {
uint32_t crc = 0xFFFFFFFF;
for (size_t i = 0; i < len; i++) {
crc ^= checkData[i];
for (int j = 0; j < 8; j++) {
if (crc & 1) {
crc = (crc >> 1) ^ 0xEDB88320;
} else {
crc >>= 1;
}
}
}
return crc ^ 0xFFFFFFFF;
}
// CRC32_table
uint32_t crc32Table(const uint8_t *checkData, size_t len) {
static int init = 0;
static uint32_t crcTable[256];
if (!init) {
for (int i = 0; i < 256; i++) {
uint32_t c = i;
for (int j = 0; j < 8; j++) {
if (c & 1) {
c = (c >> 1) ^ 0xEDB88320;
} else {
c >>= 1;
}
}
crcTable[i] = c;
}
init = 1;
}
uint32_t crc = 0xFFFFFFFF;
for (size_t i = 0; i < len; i++) {
crc = (crc >> 8) ^ crcTable[(crc ^ checkData[i]) & 0xFF];
}
return crc ^ 0xFFFFFFFF;
}
这类算法一般都是使用现成的,极少有人去手写。所以这里只展示了关键的部分,大家如果真正应用到处可以找到相关的算法和实例。
五、总结
如果是从事通信开发特别是底层通信开发,如硬件通信或信号处理时,这种校验机制要复杂的多,也会更多的使用一些错误纠正的算法。不过,一般情况下,这些算法都会在通信的底层被处理掉,对上层来说是透明的。所以对大多数的开发者来说,明白就可以了,不必非要学得非常通透。


被折叠的 条评论
为什么被折叠?



