1. 固件签名概述

1.1 为什么需要固件签名?—— 一个让我吃过亏的问题

先说说我个人的经历吧。几年前我参与一个IoT网关项目,设备已经量产了,突然发现有几台设备被植入了恶意固件。查到最后,问题出在固件更新流程上——没有签名校验,谁都能往设备里刷东西。

你想想看,如果设备不验证固件的来源,会发生什么?

  • 恶意固件注入:攻击者可以伪造一个带后门的固件,骗过设备执行
  • 固件篡改:传输过程中被人改了,设备照单全收
  • 回滚攻击:把旧版本(有漏洞的)固件刷回去,绕过安全补丁

固件签名,说白了就是给固件打上一个「数字指纹」。这个指纹只有私钥持有者(也就是你)能生成,但任何人都能用公钥验证。设备在启动或更新时,先验一下这个指纹对不对,不对就拒绝执行。

核心要点:固件签名解决的是「信任」问题——确保固件来自合法发布者,且未被篡改。

1.2 签名与加密的区别——别搞混了,我踩过这个坑

我记得刚入行时,有个同事问我:「签名不就是加密吗?」我当时也说不清楚。后来在项目中才真正搞明白,这两者完全是两码事。

对比项 固件签名 固件加密
目的 验证来源和完整性 保护内容不被泄露
谁可以验证 任何人(有公钥即可) 只有持有密钥的人
是否隐藏内容 不隐藏,固件内容可见 隐藏,固件内容不可见
典型算法 RSA、ECDSA、Ed25519 AES、ChaCha20
应用场景 安全启动、固件更新 固件保密传输、防逆向

举个例子你就明白了:

  • 签名就像你在合同上盖的私章——别人看到章就知道是你盖的,但合同内容谁都能看
  • 加密就像把合同锁进保险柜——只有有钥匙的人才能打开看内容

实际项目中,我经常把两者结合使用:先对固件签名,再对整个包加密。这样既保证了来源可信,又防止了固件被逆向分析。

我的习惯:签名用非对称算法(RSA-2048或ECDSA P-256),加密用对称算法(AES-256-GCM)。非对称慢但适合签名,对称快但需要安全分发密钥。

1.3 签名在安全启动中的作用——从第一行代码开始保护

安全启动(Secure Boot)是嵌入式设备的第一道防线。它的核心逻辑很简单:从ROM开始,每一级代码都要验证下一级的签名。

我曾经调试过一个安全启动失败的问题,折腾了两天。最后发现是Bootloader的签名算法和芯片内置的验签算法不匹配——ECDSA的曲线参数配错了。嗯,这种细节问题最容易让人抓狂。

安全启动的典型流程是这样的:

  1. ROM Bootloader:芯片上电后,ROM里固化的代码先运行。它验证下一级Bootloader的签名
  2. Bootloader:验证通过后,Bootloader加载并验签OS内核
  3. OS内核:内核启动后,验签文件系统和应用程序
  4. 应用程序:应用层也可以继续验签动态加载的模块

每一级都只信任上一级。这就是所谓的「信任链」(Chain of Trust)。

注意:安全启动的根信任是芯片ROM里的公钥。这个公钥一旦被篡改,整个信任链就崩塌了。所以芯片厂商通常会把公钥熔丝(fuse)到芯片里,物理上不可修改。

下面这张图展示了安全启动的信任链结构:

安全启动信任链 ROM Bootloader 硬件固化,不可修改 验签 Bootloader 验证OS内核签名 验签 OS内核 验证文件系统签名 验签 应用程序 验证动态模块签名 验签 信任根(Root of Trust) 芯片ROM中的公钥是信任的起点 每一级只信任上一级的签名验证结果

1.4 签名算法怎么选?—— 我的经验之谈

选签名算法时,我一般看三个因素:安全性、性能、芯片支持。

  • RSA-2048:最通用,几乎所有芯片都支持。但签名验证慢,特别是公钥指数选得大时
  • ECDSA P-256:签名短(64字节),验证快。我最近的项目都在用这个
  • Ed25519:更现代,性能更好,但部分老芯片不支持

避坑指南:我曾经选了一个芯片厂商自研的签名算法,结果工具链不完善,联调时各种踩坑。后来我学乖了——优先选标准算法,别搞花活。

1.5 签名流程的简单示例

下面是一个用OpenSSL对固件签名的典型流程:

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

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

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

# 4. 验证签名(设备端做)
openssl dgst -sha256 -verify public.pem -signature firmware.sig firmware.bin

设备端拿到 firmware.bin 和 firmware.sig 后,用内置的公钥验签。验签通过才允许启动或更新。

注意:私钥一定要保护好!我见过有人把私钥直接放在Git仓库里,结果整个产品线都得换密钥。私钥泄露等于签名体系报废。

好了,这一章就讲到这里。固件签名是整个安全体系的基石,后面的章节我们会一步步深入联调实战。