4、数字签名原理:非对称加密基础、签名与验签流程、RSA与ECDSA算法
数字签名,说白了就是给固件打上一个「防伪标签」。你想想看,OTA 升级时设备从云端下载了一个固件包,怎么确认这个包确实是官方发布的、没有被篡改过?靠的就是数字签名。
我刚开始做嵌入式安全时,总觉得签名就是个「加密的反向操作」,后来踩了坑才明白——签名不是加密,它解决的是完整性和身份认证问题,不是保密问题。
4.1 非对称加密基础
数字签名的根基是非对称加密。它有一对密钥:私钥(自己藏好)和公钥(公开出去)。
- 私钥签名,公钥验签——这是签名体系的核心原则。
- 私钥一旦泄露,整个信任链就崩了。
- 公钥可以随便分发,但必须保证它的真实性(后面讲证书链时会细说)。
我在项目中遇到过一件事:某次产线烧录时,公钥被写错了几个字节,结果所有设备升级都验签失败。排查了两天才发现是烧录脚本的问题。嗯,从那以后我养成了一个习惯——验签前先校验公钥的哈希值。
核心概念:非对称加密中,加密和解密使用不同密钥;签名和验签也使用不同密钥。私钥只能由签名方持有,公钥可以公开。
4.2 签名与验签流程
签名流程其实不复杂,我画了一张图帮你理解:
流程拆开来看,其实就三步:
- 计算摘要:对固件做哈希运算(比如 SHA-256),得到固定长度的摘要。
- 私钥签名:用私钥对摘要进行签名运算,生成签名值。
- 打包分发:把固件和签名值一起发给设备。
设备收到后,验签流程也是三步:
- 计算摘要:对收到的固件做同样的哈希运算,得到摘要1。
- 公钥解密:用公钥对签名值进行验签运算,得到摘要2。
- 比较摘要:如果摘要1 == 摘要2,说明固件是完整的、来源可信。
我的经验:验签时一定要做「恒定时间比较」,不能用 memcmp 直接比。否则攻击者可以通过时序攻击猜出摘要内容。我曾经在某个 IoT 项目里发现过这个漏洞,修复后性能损失不到 1%,但安全性提升了一个量级。
4.3 RSA 算法
RSA 是目前最广泛使用的签名算法之一。它的安全性基于大整数分解的困难性。
| 参数 | 说明 | 典型值 |
|---|---|---|
| 密钥长度 | 模数 n 的位数 | 2048 / 4096 位 |
| 签名长度 | 等于密钥长度 | 256 / 512 字节 |
| 计算速度 | 验签快,签名慢 | 签名约 1ms,验签约 0.1ms(2048位) |
| 安全性 | 依赖大数分解 | 2048位目前安全 |
RSA 的签名过程,说白了就是「用私钥做模幂运算」。验签时用公钥做同样的运算,然后比对结果。
// RSA 签名伪代码(简化版)
// 签名
digest = SHA256(firmware)
signature = RSA_sign(private_key, digest)
// 验签
digest1 = SHA256(firmware)
digest2 = RSA_verify(public_key, signature)
if (digest1 == digest2) {
// 签名有效
}
避坑指南:RSA 签名一定要使用 PSS 填充模式,不要用 PKCS#1 v1.5。我曾经在审计一个老项目时发现,v1.5 填充存在 Bleichenbacher 攻击风险,攻击者可以伪造签名。PSS 模式虽然计算量稍大,但安全性高得多。
4.4 ECDSA 算法
ECDSA(椭圆曲线数字签名算法)是 RSA 的现代替代方案。它的优势在于:更短的密钥、更快的计算、同等的安全性。
| 对比项 | RSA-2048 | ECDSA-P256 |
|---|---|---|
| 密钥长度 | 2048 位 | 256 位 |
| 签名长度 | 256 字节 | 64 字节 |
| 安全性等级 | 112 位 | 128 位 |
| 签名速度 | 较慢 | 快 3-5 倍 |
| 验签速度 | 较快 | 快 2-3 倍 |
ECDSA 的安全性基于椭圆曲线离散对数问题。说白了,就是给定椭圆曲线上的点 P 和 kP,很难反推出 k 的值。
我在项目中更倾向于使用 ECDSA,尤其是在资源受限的嵌入式设备上。原因很简单:签名短、省带宽、省存储。OTA 升级包动辄几十 MB,签名值每少 192 字节,对千万级设备来说就是几十 GB 的流量节省。
选型建议:
- 如果设备有硬件加速模块(如 ARM CryptoCell),优先用 ECDSA。
- 如果兼容性要求高(比如需要和旧系统对接),选 RSA。
- 如果对签名长度敏感(比如 LoRa、NB-IoT 等窄带通信),必须用 ECDSA。
4.5 算法对比与选型
我整理了一张对比表,方便你快速决策:
| 维度 | RSA | ECDSA |
|---|---|---|
| 密钥生成 | 慢(需要找大素数) | 快(随机数 + 基点运算) |
| 签名长度 | 256-512 字节 | 64-72 字节 |
| 计算资源 | CPU 占用高 | CPU 占用低 |
| 硬件支持 | 广泛 | 逐渐普及 |
| 专利问题 | 已过期 | 部分曲线有专利 |
| 推荐场景 | PC/服务器端 | 嵌入式/IoT 设备 |
我的建议:新项目直接上 ECDSA P-256 曲线。它被 NIST 推荐,专利已过期,硬件支持也越来越好。如果实在担心兼容性,可以同时支持 RSA 和 ECDSA,但默认用 ECDSA。
最后说一句:算法本身不是安全的全部。密钥管理、随机数生成、侧信道防护,这些环节任何一个出问题,再强的算法也白搭。我见过太多「算法选对了,实现搞砸了」的案例了。