校验算法基础:CRC、MD5、SHA-1、SHA-256的原理与对比
做量产烧录的朋友,最怕什么?镜像烧进去,板子跑不起来。查半天,发现是镜像在传输过程中坏了一个 bit。嗯,这时候你就需要校验算法了。
今天咱们就把 CRC、MD5、SHA-1、SHA-256 这四位兄弟拉出来遛遛。我做了十年量产,每种算法都踩过坑,今天一次性说清楚。
CRC:硬件工程师的老朋友
CRC(循环冗余校验)是我最早接触的校验算法。说白了,它就是个多项式除法。把数据当成一个大数,除以一个约定的多项式,余数就是 CRC 值。
为什么量产烧录里 CRC 用得最多?因为它快,硬件实现极其简单。我记得有一次做 STM32 的批量烧录,用 CRC32 校验整个 512KB 镜像,耗时不到 10ms。换 MD5 的话,得 200ms 往上。
CRC 的核心特点:
- 计算速度快,硬件支持好(很多 MCU 内置 CRC 外设)
- 检错能力强,能检测出所有奇数个错误、所有双 bit 错误
- 但它是检错码,不是防篡改码——有人故意改数据,CRC 可以轻松绕过
常见的 CRC 变体有 CRC-8、CRC-16、CRC-32。量产场景下,CRC-32 是主流。你想想看,一个 32 位的校验值,碰撞概率已经很低了。
// 一个简单的 CRC-32 实现(查表法)
uint32_t crc32(const uint8_t *data, size_t len) {
uint32_t crc = 0xFFFFFFFF;
for (size_t i = 0; i < len; i++) {
crc ^= data[i];
for (int j = 0; j < 8; j++) {
if (crc & 1) {
crc = (crc >> 1) ^ 0xEDB88320;
} else {
crc >>= 1;
}
}
}
return crc ^ 0xFFFFFFFF;
}
我的经验:量产烧录时,CRC 适合做快速完整性检查。比如烧录器每烧完一页,立即回读 CRC 对比。但千万别拿 CRC 做安全校验——我曾经见过有人用 CRC 做固件加密验证,结果被轻松破解。
MD5:曾经的王者,现在的弃子
MD5 是 90 年代的明星算法。它把任意长度的数据,压缩成 128 位(16 字节)的摘要。原理上,它通过四轮非线性函数、移位和加法操作,把数据搅得面目全非。
但 MD5 有个致命伤——碰撞。2004 年,中国密码学家王小云团队找到了 MD5 的快速碰撞方法。什么意思?就是你能构造两个不同的文件,但它们的 MD5 值一模一样。
警告:量产场景下,绝对不要用 MD5 做安全相关的校验。我曾经接手过一个项目,前任工程师用 MD5 校验固件签名,结果被攻击者伪造了合法固件。那次事故直接导致产品召回,损失惨重。
那 MD5 现在还能干嘛?说实话,我只在内部调试时偶尔用用。比如对比两个临时文件是否一致,图它快。但正式量产?我建议你直接跳过。
SHA-1:正在退役的老将
SHA-1 是 MD5 的升级版,输出 160 位(20 字节)摘要。它的设计思路和 MD5 类似,但轮数更多、操作更复杂。安全性上,SHA-1 比 MD5 强不少。
但好景不长。2017 年,Google 和 CWI 研究所宣布了 SHAttered 攻击——他们找到了 SHA-1 的碰撞实例。虽然攻击成本很高(需要约 110 年 GPU 计算时间),但理论上已经不安全了。
| 算法 | 输出长度 | 安全性状态 | 量产推荐度 |
|---|---|---|---|
| CRC-32 | 32 bit | 检错,不安全 | ⭐⭐⭐(快速校验) |
| MD5 | 128 bit | 已破解 | ⭐(不推荐) |
| SHA-1 | 160 bit | 理论不安全 | ⭐⭐(过渡期) |
| SHA-256 | 256 bit | 安全 | ⭐⭐⭐⭐⭐(首选) |
我个人习惯,SHA-1 现在只用在一些老旧的 legacy 项目上。新项目?直接上 SHA-256。
SHA-256:量产校验的黄金标准
SHA-256 是 SHA-2 家族的一员,输出 256 位(32 字节)摘要。它的安全性经过十几年考验,至今没有有效的碰撞攻击方法。
为什么量产烧录推荐 SHA-256?三个理由:
- 安全性足够——防篡改、防伪造,满足绝大多数量产场景
- 硬件加速普及——现在主流 MCU(如 STM32H7、i.MX RT 系列)都内置 SHA-256 硬件加速器
- 生态成熟——各种工具链、烧录器原生支持
// 使用 mbedTLS 计算 SHA-256(量产常用方案)
#include "mbedtls/sha256.h"
int compute_sha256(const uint8_t *data, size_t len, uint8_t output[32]) {
mbedtls_sha256_context ctx;
mbedtls_sha256_init(&ctx);
mbedtls_sha256_starts(&ctx, 0); // 0 = SHA-256, 1 = SHA-224
mbedtls_sha256_update(&ctx, data, len);
mbedtls_sha256_finish(&ctx, output);
mbedtls_sha256_free(&ctx);
return 0;
}
避坑指南:我曾经在量产线上遇到过一个问题——SHA-256 计算太慢,导致烧录节拍跟不上。后来发现是软件实现,换成硬件加速后,速度提升了 20 倍。所以,如果你的 MCU 支持硬件 SHA,一定要用起来。
四种算法的核心对比
下面这张图,是我自己总结的算法选型决策流程。你照着走,基本不会出错。
量产场景下的选型建议
说了这么多,到底怎么选?我直接给结论:
- 场景一:烧录过程中的快速校验——用 CRC-32。每烧完一页,回读 CRC 对比,发现错误立即重烧。速度快,不影响产线节拍。
- 场景二:固件完整性验证(无安全要求)——用 CRC-32 或 SHA-256 都行。我个人倾向 SHA-256,因为更通用,万一以后要升级安全策略,不用改代码。
- 场景三:固件签名/防篡改——必须用 SHA-256。配合 RSA 或 ECDSA 签名,确保固件不被篡改。
- 场景四:老项目维护——如果原来用 MD5 或 SHA-1,建议尽快升级。我见过太多因为算法过时导致的安全事故。
我的最终建议:新项目直接上 SHA-256。别纠结。CRC 作为辅助校验可以保留,但主校验算法用 SHA-256。这样既保证了安全性,又兼容了未来的扩展需求。