校验原理概述:哈希算法、CRC与校验和

做固件这么多年,我遇到过最头疼的问题之一,就是镜像烧进去之后设备跑飞了。到底是传输过程中数据变了,还是存储介质坏了?这时候,校验机制就是你手里最趁手的工具。说白了,校验就是给数据算一个「指纹」,用这个指纹来判断数据有没有被篡改或损坏。

这一章,我把三种最常用的校验方法掰开揉碎了讲。你不需要成为密码学专家,但得知道它们各自能干什么、不能干什么。

哈希算法:MD5 与 SHA 家族

哈希算法,也叫散列算法。它的核心思想是:不管输入多长,输出固定长度。而且输入稍微变一点点,输出就天翻地覆。你想想看,这特性用来做固件校验再合适不过了。

MD5:老将,但已退役

MD5 输出 128 位,也就是 16 个字节,通常用 32 个十六进制字符表示。我在早期项目里用过很多次,但后来发现它有个致命问题——碰撞。什么意思?就是你能找到两个不同的文件,算出来的 MD5 值一模一样。

⚠️ 注意:MD5 已经不再安全。在安全敏感的场景下(如 OTA 升级包签名验证),绝对不要只用 MD5。我见过有人因为偷懒继续用 MD5,结果被攻击者伪造了镜像,整批设备都得召回。

SHA 家族:更可靠的替代者

SHA 系列是 MD5 的升级版。目前主流的是 SHA-256,输出 256 位,32 个字节。碰撞概率极低,目前还没有实际可行的攻击方法。

算法 输出长度 安全性 典型应用
MD5 128 位 已破解,不推荐 旧系统兼容、非安全校验
SHA-1 160 位 理论可碰撞,逐步淘汰 Git 版本控制(内部使用)
SHA-256 256 位 安全,推荐 固件签名、OTA 升级
SHA-512 512 位 更安全,但计算开销大 高安全等级设备
💡 我的建议:新项目直接上 SHA-256。资源受限的 MCU 可以用硬件加速模块,很多 Cortex-M 系列芯片都内置了 SHA 引擎,算起来很快。

CRC 校验原理

CRC(循环冗余校验)跟哈希算法不一样。它不是用来防攻击的,而是用来检测传输或存储中的随机错误。比如 UART 通信、Flash 读取、网络包传输,这些场景下 CRC 是标配。

CRC 的原理,说白了就是多项式除法。发送方把数据当作一个巨大的二进制数,除以一个约定的多项式,余数就是 CRC 值。接收方用同样的方法算一遍,如果余数不为零,说明数据出错了。

我记得有一次排查一个 SPI Flash 读取偶尔出错的问题,就是靠 CRC 定位到的。数据在读取路径上被时钟抖动干扰了,CRC 值对不上,一查一个准。

常见 CRC 标准

标准 多项式 宽度 应用场景
CRC-8 0x07 8 位 1-Wire、SMBus
CRC-16-Modbus 0x8005 16 位 Modbus 协议、串口通信
CRC-32 0x04C11DB7 32 位 以太网、ZIP、固件校验

关键点:CRC 能检测出所有奇数个错误、所有突发长度小于等于 CRC 宽度的错误。对于随机比特翻转,CRC-32 的漏检率大约是 2-32,非常可靠。

校验和(Checksum)的概念

校验和是最简单粗暴的校验方式。就是把所有数据字节加起来,取低 8 位或 16 位作为校验值。实现起来几行代码就搞定,但它的检错能力也是最弱的。

举个例子,如果两个字节同时出错,一个加 1,一个减 1,总和不变,校验和就检测不出来。我在一个早期项目中用过校验和做 Bootloader 的镜像校验,结果有一次 Flash 的某条数据线虚焊,导致连续两个字节都错了,校验和愣是没发现。从那以后,我再也不敢在关键路径上只用校验和了。

什么时候可以用校验和?

  • 非关键数据,比如日志文件的完整性检查
  • 资源极度受限的 8 位 MCU,RAM 和 ROM 都紧张
  • 作为多层校验中的第一道快速过滤

什么时候绝对不能用?

  • 固件升级包的安全验证
  • 需要防篡改的场景
  • 数据可靠性要求高的工业控制

三种校验方式的对比

我把它们放在一起对比一下,你一眼就能看出区别。

特性 校验和 CRC 哈希(SHA-256)
输出长度 8/16 位 8/16/32 位 256 位
计算速度 极快 快 较慢
检错能力 弱 强 极强
抗碰撞 无 有限 强
典型用途 简单完整性检查 传输错误检测 安全校验、签名

知识体系框架图

下面这张图把三种校验方式的关系和适用场景梳理清楚了。

固件校验方法体系 固件校验方法 校验和 (Checksum) CRC 校验 哈希算法 特性 • 实现简单 • 检错能力弱 • 适合非关键场景 特性 • 检错能力强 • 硬件支持广泛 • 适合传输校验 特性 • 抗碰撞性强 • 计算开销大 • 适合安全校验 日志、非关键数据 通信、Flash 读取 OTA 升级、签名 实际项目中常组合使用:CRC + SHA-256

实际项目中的选择策略

讲完了原理,说说我在实际项目中怎么选。

  1. 先看场景:是防随机错误,还是防恶意篡改?前者用 CRC,后者用哈希。
  2. 再看资源:MCU 有没有硬件 CRC 模块?有没有硬件 SHA 引擎?有就用硬件,没有就评估软件实现的时间开销。
  3. 最后看安全等级:消费类产品用 SHA-256 就够了。军工、金融级别的,可能需要 SHA-512 甚至国密 SM3。
💡 一个实用技巧:在 Bootloader 里,我通常先用 CRC 快速校验整个镜像,确认没有传输错误。然后再用 SHA-256 校验签名,确认镜像没有被篡改。两层校验,各司其职,既不慢又安全。

嗯,校验原理这块就讲这么多。你把这些基础打牢了,后面排查校验异常的时候,才能一眼看出问题出在哪个环节。