固件包安全机制:签名、加密、校验与防回滚
各位工程师,今天我们聊固件包的安全机制。说白了,就是解决一个问题:怎么保证刷进车里的固件,是官方发的、没被改过、而且是最新的?
我在项目里见过太多因为固件安全没做好而出的事故。有的车被刷了第三方固件,电池管理系统直接乱套;有的因为没做防回滚,黑客把系统降级到有漏洞的老版本,然后远程破解。嗯,这些坑,咱们今天一个一个填上。
4.1 固件签名与验签:RSA vs ECDSA
签名验签,是固件安全的基石。它的逻辑很简单:私钥签名,公钥验签。私钥只有 OEM 有,公钥放在车端。
目前主流方案有两种:RSA 和 ECDSA。我直接给你对比表,你一看就明白。
| 对比项 | RSA (2048/4096 bit) | ECDSA (P-256/P-384) |
|---|---|---|
| 密钥长度 | 2048 / 4096 bit | 256 / 384 bit |
| 签名速度 | 较慢 | 快(约快 3-5 倍) |
| 验签速度 | 较快 | 较慢(约慢 2-3 倍) |
| 签名体积 | 256 / 512 字节 | 64 / 96 字节 |
| 安全强度 | 高 | 高(同等强度下密钥更短) |
| 车端资源消耗 | 较高(需要大内存) | 较低(适合 MCU) |
| ISO 21434 推荐 | 兼容性好 | 更推荐(效率优先) |
我曾经在一个项目里,客户坚持用 RSA 4096。结果 MCU 验签一次要 800 毫秒,OTA 升级时用户等得直骂娘。后来换成 ECDSA P-256,验签降到 120 毫秒,体验好太多了。
签名流程大致如下:
- OEM 用 SHA-256 计算固件哈希值
- 用私钥对哈希值签名,生成签名文件
- 将固件 + 签名文件打包成 OTA 包
- 车端收到后,用公钥解密签名,得到哈希值 A
- 车端自己计算固件哈希值 B
- 对比 A 和 B,一致则验签通过
4.2 固件加密与解密:AES-GCM
签名保证的是「没被改过」,但固件在传输过程中还是明文。如果有人抓包,就能看到固件内容,甚至逆向分析。所以,加密是必须的。
我推荐用 AES-GCM。为什么?因为它同时做了两件事:加密 + 完整性校验。GCM 模式自带 GMAC 认证标签,能检测数据是否被篡改。
来看一个典型的加密流程:
// 加密端(OEM 云端)
AES_GCM_encrypt(
plaintext: firmware.bin,
key: AES_128_KEY, // 128/192/256 bit
iv: random_12_bytes,
aad: "firmware_v3.2", // 附加认证数据
output: ciphertext,
tag: gmac_tag_16_bytes
);
// 解密端(车端)
AES_GCM_decrypt(
ciphertext: received_ciphertext,
key: AES_128_KEY,
iv: received_iv,
aad: "firmware_v3.2",
tag: received_tag,
output: plaintext,
result: success_or_fail
);
密钥怎么管理?我建议用分层密钥结构:
- 根密钥(KEK):存储在 HSM 中,永远不导出
- 固件加密密钥(FEK):由 KEK 加密后传输,每次 OTA 更新一次
- 会话密钥:临时生成,用于单次升级
这样即使 FEK 泄露,只要 KEK 没丢,就能快速更换。
4.3 固件完整性校验:SHA-256
签名和加密都做了完整性校验,为什么还要单独提 SHA-256?因为验签和加密解密都需要计算资源。在升级流程中,我们通常分两步走:
- 快速校验:下载完成后,先算 SHA-256,对比云端下发的哈希值。这一步很快,能快速发现传输错误。
- 完整验签:在安装前,做完整的签名验证。这一步更安全,但耗时更长。
SHA-256 的碰撞概率极低(2^128 次运算才可能找到一个碰撞),完全满足汽车安全需求。我个人习惯在固件包的元数据里同时放两个哈希值:
| 字段 | 说明 | 长度 |
|---|---|---|
| sha256_checksum | 固件本身的 SHA-256 哈希 | 32 字节 |
| sha256_metadata | 元数据(版本号、大小等)的哈希 | 32 字节 |
4.4 防回滚机制
防回滚,是 OTA 安全里最容易忽略的一环。你想想看,黑客如果能把系统降级到有漏洞的老版本,那签名和加密做得再好也没用。
防回滚的核心思路:版本号只能递增,不能递减。
具体实现方式:
- 版本号存储在安全存储区:比如 HSM 的 NVRAM 或 eFuse。普通 Flash 可能被擦写,不安全。
- 版本号与签名绑定:签名时把版本号作为附加数据(AAD)一起签名。车端验签时检查版本号是否大于等于当前版本。
- 硬件防回滚:有些芯片支持一次性写入的版本寄存器,写入后不可更改。这是最硬核的方案。
防回滚的典型流程:
- 车端读取当前固件版本号(从安全存储)
- 解析 OTA 包中的目标版本号
- 比较:目标版本号 >= 当前版本号 + 允许的回滚次数?
- 如果否,拒绝升级;如果是,继续验签
- 验签通过后,写入新版本号到安全存储
- 执行固件更新
知识体系总览
下面这张图,把固件包安全的四个核心机制串起来了。你一看就明白它们之间的关系。
嗯,这四个机制,每一个单独拿出来都不难。但把它们组合在一起,形成一个完整的防御链,才是真正的挑战。我在做 ISO 21434 合规咨询时,见过太多「单点强、整体弱」的案例。比如签名做得很好,但密钥管理一塌糊涂;或者加密很强,但防回滚完全没做。
记住一句话:安全不是某个功能的强弱,而是整个链条的完整性。链条上最弱的一环,决定了你的安全水平。