4. 校验码与完整性:LRC、CRC、Checksum、MAC

各位同学,咱们今天聊一个很实在的话题——校验码。

说白了,就是怎么保证你收到的数据,跟发送方发出来的数据是同一个东西。别小看这个问题,我在金融系统里见过太多因为校验没做好,导致资金对不上的惨案了。

4.1 为什么需要校验码?

你想想看,数据在网络上传输,就像快递在路上跑。可能遇到信号干扰、路由器缓存溢出、甚至黑客篡改。如果没有校验机制,你收到一笔100万的转账,实际到账可能只有10万——这谁受得了?

校验码的核心作用就两个:

  • 检测错误:发现数据在传输过程中是否被破坏
  • 验证完整性:确认数据没有被篡改或丢失

我个人习惯把校验码分成两类:一类是防随机错误的,比如LRC、CRC、Checksum;另一类是防恶意篡改的,比如MAC。这两者的设计思路完全不同,咱们一个一个说。

4.2 LRC纵向冗余校验

LRC是最简单的一种校验方式。它的做法很粗暴:把所有字节按位异或(XOR),得到一个校验字节。

举个例子:

数据:0x31 0x32 0x33 0x34
LRC = 0x31 XOR 0x32 XOR 0x33 XOR 0x34 = 0x04

接收方收到数据后,重新计算一遍LRC,跟发送方带过来的LRC对比。如果一致,说明数据没问题。

注意:LRC的检错能力非常有限。如果数据中同时有两个比特位翻转,LRC可能检测不出来。我在一个老旧的串口通信协议里见过用LRC的,后来升级时果断换掉了。

LRC的优点就是快,计算量极小。适合用在资源受限的嵌入式设备上。但金融系统里,我基本不用它——太容易漏检了。

4.3 CRC循环冗余校验

CRC就比LRC靠谱多了。它的原理是把数据看作一个多项式,然后用一个生成多项式去除,余数就是CRC校验码。

嗯,这里要注意:CRC不是简单的异或,它背后有严谨的数学理论支撑。不同的生成多项式,检错能力天差地别。

CRC类型 生成多项式 校验码长度 典型应用
CRC-8 0x07 8位 传感器数据
CRC-16 0x8005 16位 Modbus协议
CRC-32 0x04C11DB7 32位 以太网、ZIP文件
CRC-64 0x42F0E1EBA9EA3693 64位 大型文件校验

我曾经在一个金融报文交换系统里,遇到过CRC-16碰撞导致报文误判的情况。后来全部升级成CRC-32,再没出过问题。所以我的建议是:金融场景至少用CRC-32,别省那点计算资源。

核心要点:CRC能检测出所有单比特错误、双比特错误、奇数个错误,以及长度不超过生成多项式阶数的突发错误。CRC-32的漏检率大约是2^-32,也就是四十亿分之一。

4.4 Checksum校验和

Checksum是另一种常见的校验方式。它把数据按16位或32位分组,然后求和,取反码或补码作为校验值。

最经典的例子是IP协议头部的Checksum:

// 计算IP头部Checksum的伪代码
uint16_t checksum = 0;
for (int i = 0; i < header_len; i += 2) {
    checksum += header[i] << 8 | header[i+1];
}
checksum = ~checksum;  // 取反码

Checksum的计算比CRC简单,但检错能力也弱一些。它最大的问题是:如果数据中两个16位字同时出错,且错误量相互抵消,Checksum就检测不出来。

我的经验:Checksum适合用在协议头部这种短数据上,比如TCP/UDP的伪头部校验。但如果是大块数据,比如金融报文体,我建议用CRC或者MAC。

4.5 MAC消息认证码

前面说的LRC、CRC、Checksum,都只能防随机错误。如果有人恶意篡改数据,这些校验码形同虚设——因为攻击者可以重新计算校验码。

MAC就不一样了。它引入了一个密钥,只有知道密钥的人才能计算出正确的MAC值。这样既能防随机错误,又能防篡改。

常见的MAC算法有:

  • HMAC:基于哈希函数,比如HMAC-SHA256
  • CMAC:基于分组密码,比如AES-CMAC
  • Poly1305:基于多项式运算,速度极快

举个例子,HMAC的计算过程:

HMAC(K, M) = H((K' XOR opad) || H((K' XOR ipad) || M))

其中:
K 是密钥
M 是消息
H 是哈希函数
opad、ipad 是固定的填充常量

我在设计一个跨境支付系统时,报文完整性校验就用的HMAC-SHA256。密钥通过硬件安全模块(HSM)管理,每次会话动态生成。这样即使报文被截获,攻击者也无法伪造合法的MAC。

重要提醒:MAC只能保证数据没有被篡改,但不能保证发送方的身份。要同时验证身份和完整性,需要用数字签名(非对称加密)。这个咱们后面章节会讲。

4.6 四种校验码的对比

我把这四种校验码放在一起对比一下,方便你选择:

特性 LRC CRC Checksum MAC
检错能力 中等 极强
防篡改
计算速度 极快 较慢
密钥需求
典型场景 简单串口 网络协议 协议头部 金融报文

4.7 知识体系图

下面这张图展示了本章的知识结构,帮你理清思路:

校验码与完整性知识体系 数据完整性校验 LRC纵向冗余校验 简单异或,检错弱 CRC循环冗余校验 多项式除法,检错强 Checksum校验和 求和取反,中等 MAC消息认证码 带密钥,防篡改 核心特性对比 类型 防随机错误 防恶意篡改 计算开销 LRC 极低 CRC Checksum 中等 MAC 极强 较高 金融场景推荐:CRC-32 + HMAC-SHA256

4.8 避坑指南

最后,分享几个我踩过的坑:

  • 别混用大小端:CRC和Checksum的计算结果跟字节序有关。我曾经因为大小端不一致,调试了整整两天。
  • MAC密钥要定期更换:密钥长期不变,被破解的风险会指数级上升。建议每次会话或每天更换一次。
  • 不要只用一种校验:在金融系统里,我通常同时使用CRC和MAC。CRC用来快速过滤随机错误,MAC用来防篡改。双重保险。

好了,关于校验码和完整性,今天就聊到这里。记住一句话:没有校验的数据,就像没有锁的门。在金融系统里,这道门必须锁好。


专注资料整理