代码签名基础:数字签名的原理与算法选择
聊到物联网安全更新,绕不开的一个基础就是代码签名。说白了,代码签名就是给固件或软件包贴上一张「防伪标签」。这张标签能证明两件事:第一,这东西确实是你发布的;第二,这东西在发布后没被人动过手脚。
我刚开始接触物联网安全时,觉得签名就是个「加个密」的事。后来踩了坑才明白,这里面的门道比想象中多得多。咱们今天就把这块掰开揉碎了讲清楚。
数字签名的核心原理:哈希 + 非对称加密
数字签名不是把整个文件加密,那样太慢了。它用的是「哈希 + 非对称加密」的组合拳。流程其实很清晰:
- 对固件做哈希:用 SHA-256 这类算法,把任意大小的固件压缩成一个固定长度的摘要(比如 32 字节)。
- 用私钥加密哈希值:只有你持有的私钥能完成这一步,加密后的哈希值就是「签名」。
- 打包发布:固件 + 签名 + 你的公钥证书,一起发给设备。
- 设备验签:设备用你的公钥解密签名,拿到原始哈希值;再对收到的固件重新算一次哈希。两个哈希一比对,一致就通过。
这里有个关键点:哈希是单向的。你从固件算出哈希很容易,但从哈希反推固件几乎不可能。这就保证了攻击者没法伪造一个「看起来一样」的恶意固件。
核心逻辑:私钥签名 = 身份证明,哈希校验 = 完整性证明。两者缺一不可。
我在项目中见过有人只做哈希校验,不做签名。结果攻击者替换了固件和哈希值,设备照单全收。嗯,这种坑踩一次就记住了。
签名算法的选择:RSA vs ECDSA
选算法是架构设计阶段就要定的事。目前主流就两个阵营:RSA 和 ECDSA。我个人的经验是,没有绝对的好坏,关键看你的设备资源。
| 对比维度 | RSA(如 RSA-2048) | ECDSA(如 P-256) |
|---|---|---|
| 密钥长度 | 2048 位(约 256 字节) | 256 位(约 32 字节) |
| 签名长度 | 256 字节 | 64 字节 |
| 验签速度 | 较快 | 更快(约快 3-5 倍) |
| 生成签名速度 | 较慢 | 较快 |
| 硬件支持 | 几乎所有安全芯片都支持 | 较新芯片支持,老芯片可能没有 |
| 安全性(当前) | 2048 位等效于 112 位对称安全 | P-256 等效于 128 位对称安全 |
你想想看,物联网设备很多是资源受限的——MCU 可能只有几十 KB 的 RAM,Flash 也捉襟见肘。ECDSA 的签名短、验签快,天然适合这种场景。但有个前提:你的安全芯片或 MCU 必须硬件支持 ECDSA 运算。纯软件实现 ECDSA 在低端 MCU 上跑,慢得让人抓狂。
我曾经在一个项目里选了 ECDSA,结果发现设备用的老款 STM32 没有硬件加速。验签一次要 2 秒多,用户升级固件时体验极差。后来被迫切回 RSA-2048,虽然签名长了点,但验签只要 200 毫秒。所以我的建议是:先确认硬件能力,再选算法。
我的建议:如果设备有独立安全芯片(如 ATECC608A),优先用 ECDSA。如果只是 MCU 内置的软件库,RSA 更稳妥。
签名时间戳的作用
时间戳这东西,很多人容易忽略。但它其实是个「救命」的设计。为什么?因为证书会过期。
假设你的代码签名证书有效期是 2023 年到 2025 年。你在 2024 年签了一个固件,设备验签通过。到了 2026 年,证书过期了,设备还能不能安装这个固件?
如果没有时间戳,设备会检查证书有效期,发现已过期,直接拒绝安装。这就尴尬了——固件本身没问题,只是证书过期了。
时间戳的作用就是:证明签名是在证书有效期内完成的。具体做法是:
- 签名时,把当前时间发给一个可信的时间戳机构(TSA)。
- TSA 返回一个带时间戳的签名,证明「这个签名发生在 2024 年 3 月 15 日 10:00:00」。
- 设备验签时,只要确认时间戳本身有效,就不管证书是否过期。
说白了,时间戳把「签名时刻」和「验签时刻」解耦了。你 2024 年签的固件,设备 2030 年照样能装。
注意:时间戳服务本身也要可信。如果 TSA 的证书被攻破,攻击者可以伪造任意时间戳。所以时间戳机构的根证书必须预置在设备中,且要定期更新。
我在做智能电表 OTA 时,就吃过没加时间戳的亏。电表部署后 5 年没更新,第 6 年想推送一个安全补丁,结果发现签名证书已经过期了。最后只能远程更新证书,再推送固件,折腾了整整两周。从那以后,我所有签名流程都强制加时间戳。
一张图看懂代码签名流程
下面这张 SVG 图把整个流程串起来了,从签名到验签,一目了然。
实际部署中的几个坑
理论讲完了,说几个我实际踩过的坑,希望能帮你少走弯路。
- 私钥保管:私钥一旦泄露,整个信任体系就崩了。我见过有人把私钥放在 CI 服务器的环境变量里,结果 CI 被入侵,所有固件都得重新签名。建议用硬件安全模块(HSM)或云 KMS 服务。
- 证书链长度:物联网设备资源有限,证书链太长会导致验签慢、占用 Flash 多。我一般控制在 2-3 级(根 CA → 中间 CA → 代码签名证书)。
- 哈希算法选择:SHA-1 已经不安全了,别用。SHA-256 是当前最低要求。如果设备性能允许,可以考虑 SHA-384 或 SHA-512。
- 时间戳的时钟同步:设备如果没有 RTC 或 NTP 同步,时间戳验证可能出问题。我的做法是:设备只验证时间戳的签名有效性,不验证时间戳的「时间值」是否在合理范围内。
重要提醒:代码签名不是「签一次就完事」。证书会过期,算法会变弱,密钥可能泄露。你需要建立一套完整的证书生命周期管理机制,包括定期轮换、吊销和更新。