3、密码学基础回顾:哈希函数、非对称加密、数字签名、证书链
做安全启动,说白了就是跟「信任」打交道。你得让芯片相信,它加载的每一段代码都是你写的,没人动过手脚。而支撑这套信任体系的,就是密码学里的几个老朋友:哈希、非对称加密、数字签名,还有证书链。
我刚开始做嵌入式安全那会儿,总觉得这些概念太理论,离底层太远。直到有一次,我在一个 IoT 项目里因为签名验证少了一步,导致设备被刷入了恶意固件……嗯,从那以后,我再也不敢小看这些基础了。
3.1 哈希函数:数据的「指纹」
哈希函数,你可以把它理解成一个单向的榨汁机。你塞进去一个西瓜(任意长度的数据),它给你榨出一杯固定大小的果汁(固定长度的哈希值)。而且,你没法从果汁里把西瓜还原出来。
在安全启动里,哈希函数主要干三件事:
- 完整性校验:检查固件有没有被篡改。哪怕只改了一个 bit,哈希值都会变得面目全非。
- 数据摘要:对一段很长的固件做哈希,得到一个短摘要。签名的时候,我们只签这个摘要,而不是整个固件——效率高得多。
- 防碰撞:好的哈希算法,几乎不可能找到两个不同的输入,却得到相同的输出。
我常用的哈希算法对比
| 算法 | 输出长度 | 安全性 | 嵌入式适用性 |
|---|---|---|---|
| SHA-1 | 160 bit | 已废弃(有碰撞攻击) | 不推荐 |
| SHA-256 | 256 bit | 安全(当前主流) | 广泛支持,性能适中 |
| SHA-384 | 384 bit | 安全 | 资源充裕时使用 |
| SHA-512 | 512 bit | 安全 | 性能开销较大 |
避坑指南:我曾经在一个老项目里看到有人还在用 SHA-1 做固件校验。当时觉得「反正也没人攻击我们」,结果后来发现 SHA-1 的碰撞攻击成本已经低到个人电脑就能跑。赶紧换 SHA-256,别犹豫。
3.2 非对称加密:公钥与私钥
非对称加密,就是一对钥匙:一把公开(公钥),一把私藏(私钥)。公钥加密的数据,只有私钥能解开;反过来,私钥签名的数据,公钥能验证。
在安全启动场景里,我们几乎不用非对称加密来做数据加密(太慢了),而是用它来做身份认证和密钥交换。
常见的算法有:
- RSA:老牌算法,2048 位以上才安全。嵌入式里做签名验证还行,但生成签名很慢。
- ECC(椭圆曲线):同样的安全强度,密钥比 RSA 短得多。比如 256 位的 ECC 相当于 3072 位的 RSA。我个人更推荐 ECC,尤其是在资源受限的 MCU 上。
- Ed25519:一种基于 Curve25519 的签名算法,速度快,实现简单,而且抗侧信道攻击。我最近几个项目都在用这个。
注意:非对称加密的私钥是安全启动的「命根子」。私钥一旦泄露,整个信任链就崩塌了。我见过有厂商把私钥硬编码在编译脚本里,结果被逆向工程扒了出来……嗯,那场面相当尴尬。
3.3 数字签名:给固件「盖个章」
数字签名,就是哈希函数 + 非对称加密的组合拳。流程很简单:
- 签名方:对固件做哈希,然后用私钥加密这个哈希,得到签名。
- 验证方:对收到的固件做同样的哈希,然后用公钥解密签名,得到原始的哈希。两个哈希一比对,一致就通过。
你想想看,只要私钥没丢,任何人想伪造一个合法的固件,都得先破解私钥——这在计算上是不可行的。
在安全启动里,签名验证通常发生在 BootROM 或第一级 bootloader 中。代码量要极小,不能依赖复杂的操作系统。
// 伪代码:签名验证流程(简化版)
hash = SHA256(firmware_image);
decrypted_hash = RSA_Decrypt(signature, public_key);
if (hash == decrypted_hash) {
// 签名验证通过,启动固件
} else {
// 签名验证失败,进入错误处理
halt();
}
我踩过的坑:有一次,我在验证签名时忘了检查哈希长度。攻击者伪造了一个超长的哈希值,导致缓冲区溢出,直接跳过了验证逻辑。从那以后,我写签名验证代码时,一定会先检查输入长度是否合法。
3.4 证书链:信任的传递
单靠一个公钥,你只能信任一个签名者。但在实际产品中,固件可能由多个团队开发,甚至由第三方提供。这时候就需要证书链了。
证书链,说白了就是一层一层的信任传递:
- 根证书:自签名,是信任的锚点。通常烧死在芯片的 OTP(一次性可编程)存储器里,不可更改。
- 中间证书:由根证书签发,用于授权不同的部门或产品线。
- 终端证书:由中间证书签发,直接用于签名固件。
验证时,芯片从终端证书开始,逐级向上验证,直到根证书。只要根证书可信,整条链就可信。
下面这张图展示了典型的证书链结构:
我的经验:证书链不是越长越好。每多一级,验证时间就多一分,代码复杂度也增加。对于大多数嵌入式设备,两级(根证书 + 终端证书)就足够了。三级以上,除非你有复杂的多部门协作需求,否则纯属给自己找麻烦。
3.5 小结:这些基础怎么用在安全启动上?
好了,我们把这几样东西串起来,看看它们在安全启动里是怎么配合的:
- 哈希函数:对固件做摘要,确保完整性。
- 非对称加密:提供公钥/私钥对,私钥签名,公钥验证。
- 数字签名:用私钥签名固件的哈希,防止固件被篡改或伪造。
- 证书链:把公钥包装成证书,逐级授权,形成信任链。
说白了,安全启动就是一场「信任的接力赛」。从芯片出厂时烧录的根公钥开始,一级一级验证下去,直到最终加载的操作系统。任何一环断了,系统就拒绝启动。
我见过不少开发者,觉得密码学太复杂,就随便找了个开源库,复制粘贴几行代码完事。结果呢?要么是哈希算法选错了,要么是签名验证没做边界检查,要么是证书链验证跳过了根证书检查。每一个坑,都可能导致设备被攻破。
嗯,基础不牢,地动山摇。把这些基础打扎实了,后面的防回滚策略才能站得住脚。