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 数字签名:给固件“盖个章”

数字签名,就是把哈希和非对称加密结合起来。流程很简单:

  1. 对固件做哈希,得到摘要。
  2. 用私钥对摘要加密,得到签名。
  3. 把签名附加在固件后面。
  4. 芯片启动时,用公钥解密签名,得到摘要 A。
  5. 芯片对固件做哈希,得到摘要 B。
  6. 比较 A 和 B,一致则通过。

为什么不能直接加密整个固件?因为非对称加密太慢了。你想想看,一个 1MB 的固件用 RSA 加密,得等到猴年马月。所以先哈希压缩,再签名,这是工程上的最优解。

核心逻辑图:

数字签名验证流程(安全启动核心) 固件 (Firmware) SHA-256 哈希 摘要 A 签名 (Signature) 公钥 (Public Key) 解密 → 摘要 B 比较 摘要 A == 摘要 B ? 相等 → 启动通过 | 不相等 → 启动失败

这个流程,就是安全启动链的核心。你想想看,攻击者想篡改固件,他得先过哈希这一关——改了数据,哈希值就变了。然后他得伪造签名——没有私钥,他做不到。所以只要公钥是安全的,整个链条就是安全的。

3.4 我的实践建议

说了这么多理论,我给大家几个落地建议:

  • 哈希算法选型:如果芯片有硬件加速器,优先用硬件支持的算法。没有的话,SHA-256 的软件实现也够用,但要注意 ROM 和 RAM 开销。
  • 密钥长度:RSA 至少 2048 位,ECC 至少 256 位。别为了省那几百字节的存储空间,把安全等级降下来。我在一个智能电表项目里见过用 RSA-1024 的,后来被强制升级,折腾了半年。
  • 签名方案:推荐使用 RSASSA-PSS 或者 ECDSA。PKCS#1 v1.5 虽然简单,但有一些已知的攻击面。嗯,这里要注意,PSS 的随机数填充在嵌入式里要小心处理,别因为随机数质量不好导致签名可预测。
  • 公钥存储:必须烧死在一次性可编程存储器里,比如 eFuse 或者 OTP。而且建议烧录后熔断编程接口,防止被回读。

我的一个小技巧: 在产线烧录公钥时,可以同时烧录一个公钥的哈希值。启动时先验证公钥的完整性,再验签。这样能防止公钥被物理篡改。虽然多了一步操作,但安全性提升了一个量级。

好了,密码学基础就回顾到这里。这些概念是安全启动链的根基,后面讲具体实现时,你会发现每一步都离不开它们。记住:哈希是“指纹”,非对称加密是“锁和钥匙”,数字签名是“盖章”。搞懂这三样,安全启动你就入门了。


专注资料整理