4. 数字签名算法:RSA签名、ECDSA签名、Ed25519签名、SM2签名
数字签名是安全更新的「身份证」。没有它,你下载的固件包可能是攻击者塞给你的恶意代码。我这些年见过太多因为签名选型翻车的案例——有的图省事用弱算法,有的混用签名模式导致验证失败。今天咱们就把四种主流签名算法掰开揉碎讲清楚。
4.1 RSA签名:老牌劲旅,但要注意「坑」
RSA 签名应该是大家最熟悉的。它的核心逻辑是:私钥签名,公钥验签。我最早做 OTA 更新时用的就是 RSA-2048,那时候觉得这玩意儿稳如老狗。后来踩了坑才明白,RSA 的「安全水位」跟参数选择强相关。
关键参数速查表
| 密钥长度 | 安全等级 | 签名长度 | 推荐场景 |
|---|---|---|---|
| 1024 位 | 已不安全 | 128 字节 | ❌ 禁止新用 |
| 2048 位 | 当前安全 | 256 字节 | ✅ 通用场景 |
| 4096 位 | 长期安全 | 512 字节 | ✅ 高安全场景 |
RSA 签名有两种主流填充模式:PKCS#1 v1.5 和 PSS。我个人强烈建议用 PSS。为什么?PKCS#1 v1.5 存在已知的 Bleichenbacher 攻击变种,虽然实际利用条件苛刻,但安全设计上没必要给自己留隐患。我在一个车机项目里就遇到过——第三方芯片的签名验签库只支持 PKCS#1 v1.5,我们硬是加了层 PSS 适配层才放心上线。
避坑指南
我曾经接手过一个遗留系统,RSA 签名用的 1024 位密钥 + PKCS#1 v1.5 填充。安全审计直接给了高危漏洞。后来花了两个月升级到 2048 位 + PSS,还顺带重构了密钥分发流程。记住:1024 位 RSA 在 2024 年的算力下已经可以被国家级对手暴力破解。
4.2 ECDSA签名:短密钥,高性能
ECDSA 基于椭圆曲线密码学。同样的安全强度下,它的密钥长度比 RSA 短得多——256 位 ECDSA 约等于 3072 位 RSA。这意味着签名更小、计算更快。我特别喜欢在 IoT 设备上用 ECDSA,因为那些 MCU 的算力和存储都抠得很。
但 ECDSA 有个「命门」:随机数质量。每次签名必须生成一个唯一的、不可预测的随机数 k。如果 k 重复或可预测,私钥就会直接泄露。这不是理论问题——索尼 PS3 的 ECDSA 签名就因为随机数生成器用了固定值,导致黑客直接算出了私钥,整个游戏生态被攻破。
我的经验
在嵌入式设备上实现 ECDSA 签名时,我建议用硬件真随机数发生器(TRNG)来生成 k。如果芯片没有 TRNG,至少要用 NIST SP 800-90A 批准的 DRBG,并且每次签名后清零内存中的 k 值。别问我为什么强调「清零」——我在一个工控项目里见过签名后 k 值残留在堆内存里被 dump 出来的案例。
常用的椭圆曲线有:
- P-256(secp256r1):NIST 标准,兼容性最好,大多数平台原生支持
- P-384(secp384r1):更高安全等级,适合长期有效证书
- P-521(secp521r1):极高高安全场景,但计算开销大
4.3 Ed25519签名:现代、快速、防侧信道
Ed25519 是 Edwards 曲线数字签名算法,属于 EdDSA 家族。说实话,这是我目前最偏好的签名算法。为什么?因为它把 ECDSA 的那些「坑」全填平了。
首先,Ed25519 的签名是确定性的——它用私钥和消息哈希通过哈希函数生成随机数 k,而不是依赖外部随机数源。这意味着你不需要担心随机数重复的问题。其次,它的签名速度极快,在 ARM Cortex-M 级别的芯片上也能跑得飞起。第三,它的公钥和签名都很短:公钥 32 字节,签名 64 字节。
四种算法签名长度对比
| 算法 | 公钥长度 | 签名长度 | 签名速度(相对) |
|---|---|---|---|
| RSA-2048 | 256 字节 | 256 字节 | 慢 |
| ECDSA P-256 | 32 字节 | 64 字节 | 快 |
| Ed25519 | 32 字节 | 64 字节 | 非常快 |
| SM2 | 32 字节 | 64 字节 | 快 |
Ed25519 还有一个隐藏优势:抗侧信道攻击。它的实现天然是常数时间的,不像 RSA 或 ECDSA 那样容易通过时间、功耗或电磁泄露来推断密钥。我在做金融级安全模块时,侧信道攻击是必须考虑的威胁模型,Ed25519 在这方面几乎是「开箱即用」的安全。
注意
Ed25519 虽然好,但兼容性是个问题。很多老旧系统或硬件安全模块(HSM)不支持 Ed25519。如果你要跟第三方系统对接,先确认对方验签库是否支持。我曾经在一个跨厂商的固件分发平台里,因为一家芯片厂商的 BootROM 只支持 RSA,不得不保留 RSA 作为 fallback 方案。
4.4 SM2签名:国标,必须懂
SM2 是中国国家密码管理局发布的椭圆曲线公钥密码算法标准(GM/T 0003-2012)。如果你做的是面向国内政府、金融、关键基础设施的项目,SM2 是强制要求。我参与过几个等保三级系统的设计,SM2 签名是必选项。
SM2 的曲线参数是固定的,使用 256 位素域上的一条特定椭圆曲线。它的签名算法流程跟 ECDSA 类似,但细节上有差异:
- SM2 签名中使用了用户 ID(ZA 值)作为输入,将签名者身份绑定到签名中
- SM2 的哈希函数固定使用 SM3(国密哈希算法)
- SM2 签名验证时需要先计算 ZA 值,再计算待签名消息的哈希
说实话,SM2 的签名长度和 ECDSA P-256 一样(64 字节),安全强度也相当。但它的实现复杂度略高,主要是 ZA 值的计算和 SM3 哈希的配合。我在一个政务云项目里集成 SM2 时,发现很多开源库的 SM2 实现有边界条件 bug——比如 ZA 值中用户 ID 的长度编码方式搞错,导致签名验证失败。
实用建议
如果你需要同时支持国际算法和国密算法,可以考虑「双签名」策略:对同一份更新包分别用 RSA/ECDSA 和 SM2 签名,验签时根据设备类型选择对应的公钥验证。这样既满足合规要求,又不影响海外设备的兼容性。我在一个跨国车联网平台里就是这么设计的。
4.5 算法选型决策框架
说了这么多,到底该选哪个?我一般按这个逻辑来决策:
- 合规优先:如果项目有国密要求,直接选 SM2,没得商量
- 新项目、新硬件:优先 Ed25519,性能好、安全、省心
- 需要兼容老旧系统:RSA-2048 + PSS,虽然签名大但兼容性最好
- 算力受限的 IoT 设备:ECDSA P-256 或 Ed25519,看芯片是否支持硬件加速
一句话总结
RSA 是「老成持重但有点臃肿」,ECDSA 是「高效但需要小心伺候」,Ed25519 是「现代省心但生态不够广」,SM2 是「合规必选但实现要仔细」。没有银弹,只有最适合你场景的选择。
4.6 签名算法核心流程对比图
下面这张图展示了四种签名算法的核心流程对比。你可以看到,虽然底层数学不同,但「私钥签名、公钥验签」的宏观框架是一致的。
4.7 签名验证的工程实现要点
算法选好了,实现时还有几个容易翻车的地方:
- 哈希算法必须跟签名算法匹配:RSA 通常用 SHA-256,SM2 必须用 SM3,Ed25519 内部用 SHA-512。混用会导致验签失败。
- 签名值编码格式要统一:DER 编码还是原始字节?我见过因为签名格式不匹配导致跨平台验签失败的案例——PC 端用 DER,嵌入式端用原始字节,两边对不上。
- 公钥分发要带证书链:裸公钥容易被替换。至少要用 X.509 证书包装,验签时验证证书链有效性。
- 防重放攻击:签名本身不防重放。需要在签名内容里嵌入时间戳或序列号,验签时检查是否已使用过。
我的习惯
我在设计签名验证模块时,会先写一个「签名验证策略接口」,把算法选择、哈希算法、编码格式、证书验证全部抽象成可配置的策略。这样换算法时只需要新增一个策略实现,不用改业务逻辑。这个模式我在三个项目里复用过了,每次都很省心。