2. 固件签名基础:数字签名原理与常见算法

各位工程师好,我是老周。这一章我们聊聊固件签名的核心——数字签名。说实话,我在量产烧录这行干了十几年,见过太多因为签名没做好导致产品被抄板、被植入后门的案例。数字签名这东西,说白了就是给固件贴上一张「防伪标签」,让设备能认出来:这固件到底是不是我亲生的。

2.1 数字签名原理:哈希 + 非对称加密

数字签名不是凭空变出来的。它靠两个技术组合在一起:哈希算法和非对称加密。我习惯把哈希比作「指纹提取」,把非对称加密比作「私章盖章」。

2.1.1 哈希算法——提取固件指纹

哈希算法能把任意长度的固件数据,压缩成固定长度的摘要。比如 SHA-256,输出永远是 256 位。这个摘要就是固件的「数字指纹」。

  • 不可逆:从摘要反推原始数据,计算上不可能。
  • 抗碰撞:找不到两个不同的固件有相同的哈希值。
  • 雪崩效应:固件改一个比特,摘要面目全非。
我的经验:量产时千万别用 MD5 或 SHA-1。我在 2017 年接手过一个项目,前任工程师用 MD5 做固件校验,结果被攻击者伪造了碰撞固件,整批产品需要召回重烧。从那以后,我团队所有项目最低要求 SHA-256。

2.1.2 非对称加密——私钥签名,公钥验签

非对称加密有一对密钥:私钥和公钥。私钥只有签名者持有,公钥可以公开分发。签名时用私钥加密哈希值,验签时用公钥解密比对。

为什么会这样设计?你想想看,如果签名和验签用同一个密钥,那密钥一旦泄露,任何人都能伪造签名。非对称加密把这两个角色分开了——私钥藏在产线服务器里,公钥烧死在芯片 ROM 中,谁也拿不走。

核心逻辑:
  1. 固件 → 哈希算法 → 摘要(指纹)
  2. 摘要 + 私钥 → 签名(加密后的指纹)
  3. 固件 + 签名 → 打包分发
  4. 设备收到后:固件 → 哈希 → 新摘要;签名 + 公钥 → 解密出原摘要
  5. 两个摘要比对:一致则通过,不一致则拒绝

下面这张图把整个流程串起来了,我建议你多看两眼,后面讲烧录校验时会反复用到这个模型。

数字签名与验签流程 数字签名与验签流程 签名方(产线) 固件二进制 SHA-256 哈希 摘要(256位) 私钥 RSA/ECDSA 签名 签名值 验签方(设备) 固件二进制 SHA-256 哈希 新摘要 签名值 公钥 比对:通过 / 拒绝 传输 私钥签名,公钥验签。私钥泄露 = 全线崩溃,务必物理隔离保管

2.2 常见的签名算法:RSA 与 ECDSA

目前量产烧录领域主流的签名算法就两种:RSA 和 ECDSA。我两个都用过,各有各的脾气。

对比项 RSA ECDSA
安全基础 大整数分解难题 椭圆曲线离散对数难题
密钥长度(等效 128 位安全) 3072 位 256 位
签名速度 较慢(尤其私钥操作) 快(尤其私钥操作)
验签速度 快 较快
签名大小 与密钥长度相同(如 256 字节) 固定较短(如 64 字节)
硬件资源消耗 高(大数运算) 低(适合 MCU)
成熟度 极高,标准完善 高,但曲线参数需谨慎选择

2.2.1 RSA——老牌可靠,但吃资源

RSA 从 1977 年用到现在,经过了几十年的密码分析考验。我个人习惯在性能充裕的场景用 RSA-2048 或 RSA-3072。不过要注意,RSA 的私钥操作(签名)比公钥操作(验签)慢得多。量产烧录时,签名在 PC 端完成,速度不是瓶颈;但验签在设备端,如果 MCU 没有硬件加速器,RSA-3072 验签可能要几百毫秒。

避坑指南:我曾经遇到一个客户,在 Cortex-M0 上用纯软件做 RSA-4096 验签,每次启动要等 3 秒。用户投诉说开机太慢。后来我建议换成 ECDSA P-256,验签时间降到 200 毫秒以内。选算法一定要看目标芯片的算力。

2.2.2 ECDSA——短小精悍,现代首选

ECDSA 用更短的密钥提供同等安全强度。256 位的 ECDSA 密钥,安全性和 3072 位的 RSA 相当。签名长度只有 64 字节,对固件包大小敏感的场景非常友好。

但 ECDSA 有个坑:曲线参数必须选标准曲线。我见过有人用自己生成的「自定义曲线」,结果曲线参数有后门,签名被轻松伪造。量产项目只推荐 NIST P-256(secp256r1)或 Curve25519。

我的建议:新项目直接上 ECDSA P-256。除非你的芯片只有 RSA 硬件加速器,否则 ECDSA 在签名大小、验签速度、密钥存储三方面都占优。我在近三年的量产项目中全部切到了 ECDSA,没有再换回去。

2.3 签名与验签流程详解

理论讲完了,咱们看看实际代码怎么写。下面是一个完整的签名和验签流程,用 OpenSSL 命令行演示。

2.3.1 生成密钥对

# 生成 ECDSA P-256 私钥
openssl ecparam -genkey -name prime256v1 -out private.pem

# 导出公钥
openssl ec -in private.pem -pubout -out public.pem

2.3.2 签名固件

# 计算固件哈希并签名
openssl dgst -sha256 -sign private.pem -out firmware.sig firmware.bin

# 查看签名内容(二进制)
xxd firmware.sig | head -4

2.3.3 验签固件

# 设备端验签
openssl dgst -sha256 -verify public.pem -signature firmware.sig firmware.bin

# 输出:Verified OK 或 Verification Failure
量产烧录中的实际流程:
  1. 产线服务器持有私钥,对固件进行签名
  2. 签名值附加在固件尾部,或单独存储
  3. 烧录器将固件 + 签名写入芯片 Flash
  4. 芯片首次启动时,BootROM 读取公钥(预烧在 OTP/efuse)
  5. BootROM 对固件做哈希,用公钥验签
  6. 验签通过 → 跳转到固件执行;失败 → 进入恢复模式或停机

2.4 量产中的关键注意事项

  • 私钥保护:私钥必须存储在硬件安全模块(HSM)中,不能以明文文件形式出现在产线 PC 上。我曾经见过一个工厂,私钥就放在共享文件夹里,结果被离职员工拷贝,导致产品被大量仿造。
  • 公钥烧写:公钥必须烧录在芯片的一次性可编程(OTP)区域或 efuse 中,防止被篡改。如果公钥存在 Flash 里,攻击者可以替换公钥,用自己的私钥签名恶意固件。
  • 哈希算法选择:至少 SHA-256。不要用 SHA-1,不要用 MD5。这是底线。
  • 签名算法选择:新项目优先 ECDSA P-256。如果芯片只支持 RSA,用 RSA-2048 以上。
  • 防回滚:签名中应包含固件版本号,设备验签时检查版本不低于当前运行版本。否则攻击者可以用旧版本固件(含已知漏洞)降级攻击。
血的教训:我 2019 年帮一个客户做安全审计,发现他们的验签代码只检查了签名是否有效,但没有检查公钥是否来自可信源。攻击者通过替换 Flash 中的公钥,成功加载了恶意固件。记住:公钥的完整性比签名本身更重要。公钥被篡改,签名校验形同虚设。

嗯,这一章的内容就到这里。数字签名是固件安全的第一道防线,也是量产烧录校验机制的基石。搞懂了哈希和非对称加密的组合逻辑,后面讲安全启动、安全更新、防伪认证时,你就能快速上手了。