一、固件签名概述:为什么需要固件签名?

各位做嵌入式开发的同行,咱们先聊个实在问题。

你辛辛苦苦写完了固件,烧录到设备里,设备跑起来了。然后呢?有没有想过,如果有人把你的固件换掉了,换成恶意版本,你的设备会怎样?

我早年做 IoT 网关项目时就吃过这个亏。客户反馈说设备半夜自己重启,查了三天,最后发现是生产线上有人用 U 盘拷了个未签名的测试固件进去。从那以后,我对固件签名这件事再也不敢马虎。

1.1 为什么需要固件签名?

说白了,固件签名要解决三个核心问题:

  • 身份认证——这个固件到底是谁发布的?
  • 完整性校验——固件在传输或存储过程中有没有被篡改?
  • 不可否认性——发布者不能事后抵赖说“这不是我签的”。

你想想看,如果设备没有签名验证,攻击者只需要一个伪造的固件包,就能让你的设备“叛变”。智能门锁被远程开锁、医疗设备被篡改参数、汽车 ECU 被刷写恶意固件……这些都不是科幻片,是真实发生过的事故。

核心原则:固件签名不是可选项,而是安全启动链的第一道锁。没有签名的固件,就像没有锁的门——不是一定会出事,但出事只是时间问题。

1.2 签名与加密的区别

这个问题我面试时经常问,但很多人答不清楚。咱们用一张表说透:

对比维度 固件签名 固件加密
核心目的 验证身份 + 防篡改 防泄密(保密性)
使用密钥 私钥签名,公钥验签 公钥加密,私钥解密
输出结果 原始固件 + 签名值 密文固件(原始内容被隐藏)
能否还原原文 不能(签名不是加密) 能(解密后还原)
典型场景 OTA 升级、启动验证 固件分发、敏感数据保护

我见过有人把签名和加密混为一谈,结果在项目里用 AES 加密当签名用——验签时根本没法确认发布者身份。记住一句话:签名防篡改,加密防偷看。两者可以组合使用,但功能不能互相替代。

我的习惯:在安全要求高的项目中,我会先对固件签名,再对“固件+签名”整体加密。这样既保证了谁发布的,又保证了路上没人能偷看固件内容。

1.3 常见的签名算法

目前主流的有三种:RSA、ECDSA、HMAC。咱们一个一个说。

RSA(Rivest-Shamir-Adleman)

RSA 是最经典的公钥签名算法。它的原理基于大整数分解的数学难题——给你两个大质数的乘积,想反推出原来的质数,计算上几乎不可能。

  • 优点:算法成熟,硬件支持广泛,几乎所有 MCU 都有 RSA 加速引擎。
  • 缺点:密钥越长,签名和验签越慢。2048 位 RSA 签名一次大概要几毫秒到几十毫秒(取决于硬件)。
  • 典型场景:安全启动、固件 OTA 签名。

我记得有一次调试一个 ARM Cortex-M4 项目,RSA 2048 验签花了 80 多毫秒,导致启动时间超标。后来换成 ECDSA,直接降到 5 毫秒以内。

ECDSA(Elliptic Curve Digital Signature Algorithm)

ECDSA 基于椭圆曲线离散对数难题。同样的安全强度下,ECDSA 的密钥长度比 RSA 短得多。

  • 优点:密钥短(256 位 ECDSA ≈ 3072 位 RSA 的安全强度),签名速度快,适合资源受限的嵌入式设备。
  • 缺点:实现复杂度高,随机数质量差时容易泄露私钥(这个坑我后面会细讲)。
  • 典型场景:IoT 设备、车规级 MCU、资源紧张的 SoC。

避坑指南:我曾经在一个项目中用了某厂商的 ECDSA 库,结果随机数生成器有 bug,每次签名用的随机数都一样。攻击者只需要两个签名就能算出私钥。嗯,那次差点把项目搞黄。所以用 ECDSA 时,一定要确认随机数源是硬件真随机数发生器(TRNG),别用软件伪随机。

HMAC(Hash-based Message Authentication Code)

HMAC 不是公钥算法,它用的是对称密钥。签名和验签用的是同一个密钥。

  • 优点:计算极快,实现简单,适合对性能要求极高的场景。
  • 缺点:密钥分发困难——所有验签设备都得持有同一个密钥,一旦泄露,整个系统就完了。
  • 典型场景:设备内部模块间通信验证、轻量级固件校验(不涉及公钥基础设施)。

我个人只在两种情况下用 HMAC:一是设备出厂后不再需要远程升级验签,二是密钥存储在硬件安全模块(HSM)或安全元件(SE)中,物理上无法读出。

1.4 三种算法的对比

特性 RSA ECDSA HMAC
密钥类型 非对称(公钥/私钥) 非对称(公钥/私钥) 对称(共享密钥)
安全强度(等效) 2048 位 256 位(P-256) 取决于哈希算法
签名速度 慢 快 极快
验签速度 慢 快 极快
密钥分发难度 低(公钥公开) 低(公钥公开) 高(密钥需保密分发)
硬件加速支持 广泛 逐渐普及 依赖哈希加速器
推荐场景 高性能设备、传统架构 资源受限设备、新设计 内部通信、轻量校验

1.5 固件签名流程总览

下面这张图展示了固件签名的完整流程,从开发环境到设备端验签:

固件签名与验签流程 固件签名与验签流程 签名端(开发环境 / CI 服务器) 原始固件(.bin / .hex) 哈希计算(SHA-256 / SHA-384) 私钥签名(RSA / ECDSA) 打包:固件 + 签名值 + 证书 OTA / 烧录 验签端(设备端 Bootloader) 接收固件包 提取签名值 + 公钥 计算哈希 → 公钥验签 验签通过 → 启动固件 说明:验签失败时,Bootloader 应拒绝启动并进入恢复模式

流程其实不复杂:开发环境对固件做哈希,然后用私钥对哈希值签名。设备端收到固件后,用公钥验签,确认签名有效才允许启动。整个过程的核心就是——私钥必须保密,公钥可以公开。

我的建议:新项目选签名算法时,优先考虑 ECDSA P-256 或 P-384。RSA 虽然成熟,但密钥太长,在资源受限的设备上性能吃亏。HMAC 只适合封闭环境,别用在需要远程升级的产品上。