3、密码学基础回顾:哈希算法、非对称加密、数字签名原理
各位同学,咱们今天聊聊安全启动链的基石——密码学。说实话,很多工程师一听到“密码学”三个字就头大,觉得全是数学公式和抽象概念。但在我十几年的嵌入式安全开发经历中,我越来越觉得,搞懂这几个核心算法,比背一堆协议管用得多。
安全启动链说白了,就是让芯片从第一行代码开始,每一步都“验明正身”。怎么验?靠的就是哈希、非对称加密和数字签名这三板斧。咱们一个一个来拆解。
3.1 哈希算法:数据的“指纹”
哈希算法,我习惯叫它“数据指纹”。你给它任意长度的数据,它吐出一个固定长度的摘要。这个摘要就像人的指纹——理论上独一无二,而且你没法从指纹反推出人的长相。
核心特性:
- 单向性:从哈希值无法还原原始数据。这是安全的基础。
- 抗碰撞性:很难找到两个不同的输入,产生相同的哈希值。
- 雪崩效应:输入改一个比特,输出就面目全非。
在安全启动里,我们常用的是 SHA-256 和 SHA-384。SHA-256 输出 32 字节,SHA-384 输出 48 字节。选哪个?我个人习惯看安全等级和性能的平衡。ARM Cortex-M4 这类 MCU,跑 SHA-256 大概每 MB 数据要几十毫秒,SHA-384 会慢 30% 左右。
我的经验: 有一次做车规级芯片的启动验证,发现 SHA-256 的碰撞概率虽然极低,但客户要求必须用 SHA-384。为什么?因为他们的安全策略里,哈希值要作为 ECDSA 签名的输入,而 ECDSA 对哈希长度有匹配要求。所以别光看算法本身,还得看上下游怎么用。
代码实现上,我建议直接用硬件加速器。现在的安全芯片基本都集成了 SHA 引擎。你只需要配置寄存器,丢数据进去,等中断或者轮询拿结果。纯软件实现?嗯,除非你在做教学或者资源极度受限的场景,否则别折腾。
// 伪代码:使用硬件 SHA-256 引擎
sha256_context_t ctx;
uint8_t hash[32];
sha256_hw_init(&ctx);
sha256_hw_update(&ctx, bootloader_data, bootloader_len);
sha256_hw_final(&ctx, hash);
// 此时 hash 数组里就是 bootloader 的指纹
// 接下来要跟预存的指纹比对
3.2 非对称加密:公钥和私钥的“夫妻档”
非对称加密,说白了就是一对钥匙:公钥公开,私钥保密。公钥加密的数据只能用私钥解密,反过来私钥签名的数据只能用公钥验证。这个特性,简直是安全启动的天选之子。
主流方案有两个:RSA 和 ECC。
| 特性 | RSA | ECC |
|---|---|---|
| 密钥长度 | 2048 / 4096 位 | 256 / 384 位 |
| 签名速度 | 慢(私钥操作) | 快 |
| 验签速度 | 快(公钥操作) | 较快 |
| 同等安全强度 | 2048 位 ≈ | 256 位 |
| 资源消耗 | 大 | 小 |
你想想看,在安全启动的场景里,芯片只需要验签,不需要签名。验签用的是公钥,而公钥是公开的。所以 RSA 的验签速度快这个优势就很香。但 ECC 的密钥短,占用存储空间小,在 IoT 设备里越来越流行。
避坑指南: 我曾经在一个项目里,把 RSA 私钥直接编译进了固件。结果固件被反编译,私钥泄露,整个产品线的安全体系瞬间崩塌。记住:私钥永远不应该出现在设备端!公钥可以烧死在 OTP 或者 eFuse 里,私钥必须留在产线或 HSM 中。
3.3 数字签名:给固件“盖个章”
数字签名,就是把哈希和非对称加密结合起来。流程很简单:
- 对固件做哈希,得到摘要。
- 用私钥对摘要加密,得到签名。
- 把签名附加在固件后面。
- 芯片启动时,用公钥解密签名,得到摘要 A。
- 芯片对固件做哈希,得到摘要 B。
- 比较 A 和 B,一致则通过。
为什么不能直接加密整个固件?因为非对称加密太慢了。你想想看,一个 1MB 的固件用 RSA 加密,得等到猴年马月。所以先哈希压缩,再签名,这是工程上的最优解。
核心逻辑图:
这个流程,就是安全启动链的核心。你想想看,攻击者想篡改固件,他得先过哈希这一关——改了数据,哈希值就变了。然后他得伪造签名——没有私钥,他做不到。所以只要公钥是安全的,整个链条就是安全的。
3.4 我的实践建议
说了这么多理论,我给大家几个落地建议:
- 哈希算法选型:如果芯片有硬件加速器,优先用硬件支持的算法。没有的话,SHA-256 的软件实现也够用,但要注意 ROM 和 RAM 开销。
- 密钥长度:RSA 至少 2048 位,ECC 至少 256 位。别为了省那几百字节的存储空间,把安全等级降下来。我在一个智能电表项目里见过用 RSA-1024 的,后来被强制升级,折腾了半年。
- 签名方案:推荐使用 RSASSA-PSS 或者 ECDSA。PKCS#1 v1.5 虽然简单,但有一些已知的攻击面。嗯,这里要注意,PSS 的随机数填充在嵌入式里要小心处理,别因为随机数质量不好导致签名可预测。
- 公钥存储:必须烧死在一次性可编程存储器里,比如 eFuse 或者 OTP。而且建议烧录后熔断编程接口,防止被回读。
我的一个小技巧: 在产线烧录公钥时,可以同时烧录一个公钥的哈希值。启动时先验证公钥的完整性,再验签。这样能防止公钥被物理篡改。虽然多了一步操作,但安全性提升了一个量级。
好了,密码学基础就回顾到这里。这些概念是安全启动链的根基,后面讲具体实现时,你会发现每一步都离不开它们。记住:哈希是“指纹”,非对称加密是“锁和钥匙”,数字签名是“盖章”。搞懂这三样,安全启动你就入门了。