1. 固件签名基础:什么是固件签名、数字签名的工作原理、常见的签名算法
做固件逆向分析,绕不过去的第一道坎就是签名验证。我刚开始接触嵌入式安全那会儿,总觉得签名就是个「加个密」的事儿,后来被现实狠狠教育了一顿——签名不是加密,签名是防篡改和验身份。你想想看,一个设备要是连谁写的固件都验不出来,那跟裸奔有什么区别?
1.1 什么是固件签名
固件签名,说白了就是在固件镜像后面贴一张「数字封条」。这张封条用私钥生成,任何人都能用对应的公钥去验证它是不是真的。
一个典型的签名固件包含两部分:
- 固件本体——二进制镜像,可能是裸机程序、Linux 内核、或者某个 bootloader
- 签名值——对固件哈希值进行私钥运算后的结果,通常附加在固件末尾或头部
我在项目中遇到过不少设备,签名值就放在固件偏移 0x100 的位置,连个对齐填充都没做。嗯,这种「裸奔式签名」其实挺常见的,尤其是那些从开源项目改过来的 IoT 设备。
核心要点:固件签名 ≠ 固件加密。签名保证的是「谁写的」和「改没改过」,加密保证的是「别人看不懂」。很多工程师把这两个概念混在一起,调试的时候会出大问题。
1.2 数字签名的工作原理
数字签名的流程其实不复杂,我画个图你就明白了:
流程看着简单,但实际落地的时候坑特别多。我见过一个设备,验签的时候只检查了签名值的前 4 个字节——你猜怎么着?攻击者随便填个 0x00000000 就绕过去了。这种「半吊子验签」在逆向分析里简直就是送人头。
1.3 常见的签名算法
嵌入式世界里,签名算法就那么几种。我按使用频率排个序:
| 算法 | 密钥长度 | 签名长度 | 典型场景 | 我的评价 |
|---|---|---|---|---|
| RSA | 1024~4096 bit | 与密钥等长 | Bootloader、固件更新包 | 老牌选手,资源消耗大 |
| ECDSA | 256~521 bit | 约 2×密钥长度 | IoT 设备、安全芯片 | 短密钥高强度,我的首选 |
| HMAC | 对称密钥 | 与哈希输出等长 | 内部通信、轻量验证 | 不是真正的签名,慎用 |
RSA 签名
RSA 签名是最早被广泛使用的方案。它的核心逻辑是:私钥加密哈希值,公钥解密比对。我习惯叫它「教科书式签名」——因为几乎所有密码学教材都会拿它举例。
但 RSA 有个硬伤:慢。尤其是在那些主频不到 100MHz 的 MCU 上,验一次 2048 位的 RSA 签名可能要几百毫秒。我曾经在一个 Cortex-M3 的平台上调 RSA 验签,优化了半天才压到 150ms——用户还是嫌开机慢。
避坑指南:我曾经遇到过一个设备,RSA 公钥硬编码在固件里,但验签时没有检查公钥的合法性。攻击者直接替换公钥为自己的公钥,然后用自己生成的私钥签名恶意固件——完美绕过。记住:公钥必须被安全存储和验证,否则签名形同虚设。
ECDSA 签名
ECDSA 基于椭圆曲线密码学,用更短的密钥达到和 RSA 同等级别的安全强度。我个人非常推荐在资源受限的设备上用 ECDSA。
举个例子:
- RSA 2048 位签名 ≈ 256 字节
- ECDSA 256 位签名 ≈ 64 字节(r + s 各 32 字节)
签名长度差了 4 倍,这对固件大小和传输带宽的影响是实打实的。我在做智能门锁项目时,固件更新包只有 64KB,用 RSA 的话光签名就占了 256 字节,换成 ECDSA 只占 64 字节——省下来的空间够塞一个功能模块了。
不过 ECDSA 也有坑:随机数质量。如果签名时用的随机数重复或可预测,私钥就能被算出来。嗯,这个漏洞在真实世界里已经出现过好几次了,比如索尼 PS3 的签名密钥泄露事件。
HMAC 签名
HMAC 其实不是真正的「数字签名」,它用的是对称密钥。发送方和接收方共享同一个密钥,对消息计算 HMAC 值,接收方用同样的密钥重新计算并比对。
为什么说它「不是真正的签名」?因为:
- 无法提供不可否认性——双方都能生成同样的 HMAC,没法证明是谁签的
- 密钥分发是个大问题——所有验签设备都得存同一个密钥,泄露一个等于全完
但 HMAC 也有它的用武之地。我在一些低成本的蓝牙设备上见过 HMAC 做固件验证——说白了就是防君子不防小人。攻击者只要从一台设备里把密钥 dump 出来,整个产品线就沦陷了。
警告:HMAC 不能用于「你是谁」的验证,只能用于「消息有没有被改过」。如果你的产品需要防固件篡改,请用 RSA 或 ECDSA。HMAC 在逆向分析面前基本等于裸奔——我见过太多用 HMAC 做「签名」的设备,密钥提取出来后整个安全体系瞬间崩塌。
1.4 签名在固件中的存储方式
签名值怎么塞进固件里?常见的做法有三种:
- 追加在固件末尾——最简单,bootloader 先读固件再读签名
- 嵌入在固件头部——签名放在固定偏移,方便快速定位
- 独立签名文件——固件和签名分开存储,更新时一起下发
我个人最讨厌第三种——因为逆向分析的时候,你得先找到签名文件在哪,再找到对应的公钥。有一次我分析一个路由器固件,签名文件藏在文件系统的 /etc 目录下,文件名还伪装成配置文件……找了我整整两天。
1.5 本章小结
固件签名不是什么玄学,它就是一套「谁写的 + 改没改过」的验证机制。RSA 老而弥坚,ECDSA 短小精悍,HMAC 只能算个备胎。理解这些基础,后面讲签名绕过攻击的时候你才能知道——攻击者到底在绕什么。