一、固件签名基础:从“你是谁”到“你被信任”
各位好,我是老周。做嵌入式安全这些年,我见过太多因为固件被篡改而翻车的项目。今天咱们就从最基础的东西聊起——固件签名。
你可能会问:签名不就是加个校验吗?其实没那么简单。我刚开始接触这个领域时也这么想,直到有一次在产线上发现,明明哈希校验都过了,设备还是跑飞了……嗯,后来才搞明白,哈希和签名是两码事。
什么是固件签名?
固件签名,说白了就是给固件打上一个“数字指纹+身份证明”。它解决两个核心问题:
- 这个固件是谁发布的?——身份认证
- 这个固件有没有被改过?——完整性校验
我习惯用一个比喻:固件签名就像你给重要文件盖上公章。别人看到公章就知道是你发的,而且如果文件被涂改过,公章就失效了。
核心概念:固件签名 = 私钥签名 + 公钥验证。私钥只有发布者持有,公钥可以公开。签名过程是“加密”哈希值,验证过程是“解密”并比对。
为什么需要签名?
你想想看,没有签名的固件是什么状态?就像在公共白板上贴了一张纸条,谁都能撕下来改两笔再贴回去。设备拿到固件后,根本不知道它是不是原厂发的。
我在项目中遇到过最典型的场景:
- OTA升级被劫持——攻击者伪造固件包,设备傻傻地刷进去,直接变砖
- 供应链攻击——代工厂偷偷替换固件,植入后门
- 调试接口泄露——未签名的固件被逆向,核心算法被盗
避坑指南:我曾经接手过一个项目,团队觉得“反正产品不联网,签名没必要”。结果客户现场用U盘升级固件,U盘被人动了手脚……从那以后,我坚持所有固件必须签名,不管是否联网。
签名与哈希的区别
这是新人最容易搞混的地方。我画个表你就明白了:
| 特性 | 哈希(Hash) | 签名(Signature) |
|---|---|---|
| 作用 | 校验数据完整性 | 校验完整性 + 身份认证 |
| 密钥 | 不需要密钥 | 需要公私钥对 |
| 能否伪造 | 任何人都能计算哈希 | 只有私钥持有者能签名 |
| 抗抵赖性 | 无 | 有(非对称加密保证) |
| 典型算法 | SHA-256, SHA-384 | RSA, ECDSA, Ed25519 |
简单说:哈希只能告诉你“东西变了没”,签名能告诉你“谁变的”以及“是不是合法的”。
我的经验:很多安全方案只做哈希校验,觉得够了。但你想,如果攻击者同时替换了固件和哈希值,设备根本发现不了。签名就不一样——攻击者没有私钥,伪造不了签名。
常见的签名算法
目前主流的就是RSA和ECDSA。我分别说说它们的脾气。
RSA(Rivest-Shamir-Adleman)
RSA是老牌算法,成熟、稳定、专利已过期。我最早做固件签名时用的就是RSA-2048。
- 优点:实现简单,硬件支持广泛,很多MCU内置RSA加速器
- 缺点:密钥太长(2048位),签名慢,占用Flash空间大
- 典型场景:网关、服务器端签名,资源相对充裕的设备
// RSA-2048 签名示例(伪代码)
// 1. 计算固件哈希
hash = SHA256(firmware.bin)
// 2. 使用私钥签名
signature = RSA_Sign(private_key, hash, PSS_PADDING)
// 3. 将签名附加到固件尾部
firmware_signed = firmware.bin || signature
ECDSA(Elliptic Curve Digital Signature Algorithm)
ECDSA是后起之秀,用更短的密钥达到同等安全强度。我个人现在更倾向用ECDSA,尤其是资源受限的IoT设备。
- 优点:密钥短(256位 ≈ RSA-3072安全等级),签名快,省Flash
- 缺点:实现复杂,随机数生成要求高(随机数出问题会泄露私钥)
- 典型场景:MCU、传感器、蓝牙设备等资源受限场景
// ECDSA P-256 签名示例(伪代码)
// 1. 计算固件哈希
hash = SHA256(firmware.bin)
// 2. 使用私钥签名(注意:随机数k必须安全生成)
signature = ECDSA_Sign(private_key, hash, k_random)
// 3. 将签名附加到固件尾部
firmware_signed = firmware.bin || signature
踩过的坑:ECDSA的随机数生成是个大坑。我曾经见过一个方案,随机数生成器没初始化好,每次签名都用同一个k值。结果攻击者拿到两个签名就反推出了私钥……嗯,从那以后我坚持每次签名前检查随机数熵源。
算法对比表
| 对比项 | RSA-2048 | ECDSA P-256 | Ed25519 |
|---|---|---|---|
| 密钥长度 | 2048位 | 256位 | 256位 |
| 签名长度 | 256字节 | 64字节 | 64字节 |
| 签名速度 | 慢 | 快 | 极快 |
| 验证速度 | 快 | 慢 | 快 |
| 硬件支持 | 广泛 | 较广泛 | 较少 |
| 推荐场景 | 服务器端、网关 | MCU、IoT设备 | 高性能嵌入式 |
固件签名流程总览
下面这张图是我自己总结的固件签名标准流程,你可以把它当作模板来用:
小结
固件签名不是可选项,而是安全基线。我见过太多“先上线再说”的项目,最后都回来补签名方案——代价往往是原来的10倍。
记住三个要点:
- 哈希 ≠ 签名,签名多了身份认证和抗抵赖性
- RSA适合资源充裕的场景,ECDSA适合资源受限的设备
- 私钥必须安全存储,公钥可以公开但需要防篡改
个人建议:新项目直接上ECDSA P-256或Ed25519。RSA虽然成熟,但密钥太长,未来趋势是向椭圆曲线迁移。别等到产品定型了再改算法,那滋味……我尝过,不好受。