1. 固件签名概述

各位同学好,我是老周。做嵌入式安全这块十几年了,今天咱们聊聊固件签名。

说实话,我刚入行那会儿,固件签名这概念还没这么普及。那时候烧个固件进设备,能跑就行,谁管它是不是被篡改过?直到有一次,我在一个IoT项目里遇到了设备被恶意刷写的事故——嗯,从那以后,我再也不敢轻视签名了。

什么是固件签名

固件签名,说白了就是给固件打个「数字指纹」加「数字印章」。

流程其实不复杂:

  1. 开发者用私钥对固件的哈希值加密,生成签名
  2. 签名和固件一起发布
  3. 设备端用公钥验证签名是否匹配

我习惯把签名比作「防伪标签」。你买一瓶茅台,瓶身上有个防伪码,扫一下就知道真假。固件签名也是这个道理——设备启动时先扫一下固件的「防伪码」,对得上才让跑。

核心要点:固件签名 = 哈希摘要 + 非对称加密。不是把整个固件加密,而是对固件的「指纹」做签名。

为什么需要签名

你想想看,没有签名的固件是什么状态?

  • 任何人都能伪造——改几行代码,换个logo,重新打包就能刷进去
  • 设备无法识别真伪——它不知道跑的是官方固件还是恶意固件
  • 出了问题没法追溯——到底是开发者发的版本,还是被人中间篡改了?说不清

我在一个智能门锁项目里遇到过真实案例。客户反馈门锁偶尔自动开门,查了半天,发现是有人用伪造固件刷写了设备。那次事故直接导致产品召回,损失惨重。从那以后,我们所有产品强制要求签名验证。

避坑提醒:我曾经见过一些团队只在生产环境做签名验证,开发环境直接跳过。结果测试固件被泄露出去,被人逆向分析出漏洞。我的建议是——开发环境也要签名,只是可以用不同的密钥体系。

签名与加密的区别

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

对比维度 固件签名 固件加密
目的 验证身份 + 完整性 保护内容机密性
谁可以验证 任何人(有公钥即可) 只有持有密钥的人
固件是否可见 固件内容公开可见 固件内容被隐藏
防篡改能力 强(篡改后签名失效) 弱(加密不防篡改)
典型算法 RSA + SHA256, ECDSA AES, ChaCha20

我打个比方你就懂了:

  • 签名就像你在合同上按手印——合同内容谁都能看,但手印证明是你签的,别人改不了
  • 加密就像把合同锁进保险柜——别人看不到内容,但打开保险柜的人可以随便改

实际项目中,签名和加密经常一起用。我建议的做法是:先签名再加密,或者先加密再签名,看具体场景。但记住一点——签名是必须的,加密是可选的。

签名在设备安全启动中的作用

安全启动(Secure Boot)是签名最经典的应用场景。咱们画个流程图看看:

固件签名在安全启动中的完整流程 开发者发布固件 计算固件哈希值 私钥签名哈希值 设备启动加载固件 公钥验证签名 → 通过/拒绝 开发者侧 私钥保存在安全环境 签名过程离线完成 设备侧 公钥烧录在一次性OTP 验证在BootROM中执行 失败则进入恢复模式 SHA256 RSA/ECDSA 固件+签名 BootROM

安全启动的链条是这样的:

  1. BootROM(只读存储器中的启动代码)是信任根,它里面固化了公钥
  2. BootROM 验证第一级 bootloader 的签名
  3. 第一级 bootloader 验证第二级 bootloader 的签名
  4. 第二级 bootloader 验证 OS kernel 的签名
  5. OS kernel 验证应用固件的签名

这就是所谓的「信任链」。每一级都验证下一级的签名,环环相扣。只要信任根不被攻破,整个链条就是安全的。

实战经验:我建议你在设计安全启动时,把公钥烧录到一次性可编程存储器(OTP)里,并且熔断调试接口。这样即使攻击者拿到芯片,也无法提取或篡改公钥。我在一个车规级项目里就是这么做的,通过了EAL5+认证。

安全启动能防什么?

  • 防止运行篡改过的固件
  • 防止运行来自未知来源的固件
  • 防止固件降级攻击(配合版本号检查)

不能防什么?

  • 不能防侧信道攻击(如功耗分析)
  • 不能防物理攻击(如探针直接读Flash)
  • 不能防密钥泄露(私钥被偷了,签名就废了)

嗯,说到密钥保护,这是个单独的大话题,咱们后面章节会详细讲。今天先把签名的概念理清楚。

最后总结一句话:固件签名是设备安全的基石,没有签名的安全启动就像没有锁的门——看着有,其实没用。