4. 签名算法与密钥管理
签名算法选型,说白了就是在安全、性能、代码体积之间做权衡。我这些年经手过不少嵌入式项目,从8位MCU到高性能ARM Cortex-A,签名算法这块踩过的坑还真不少。今天咱们就把RSA、ECDSA、Ed25519这三兄弟掰开揉碎了聊一聊。
4.1 RSA签名:老牌劲旅,但有点“重”
RSA签名,大家应该都不陌生。它基于大整数分解难题,原理简单,标准成熟。我在2015年做一个网关产品时,用的就是RSA-2048。
RSA签名的核心流程:
- 生成密钥对:选两个大素数p、q,计算n = p * q,生成公钥(n, e)和私钥(n, d)。
- 签名:对消息哈希H(m)做私钥运算:s = H(m)^d mod n。
- 验签:用公钥计算s^e mod n,比对是否等于H(m)。
关键参数:RSA-2048是目前嵌入式领域的最低安全门槛。NIST建议2030年前使用至少2048位。
RSA的优缺点:
| 维度 | 评价 |
|---|---|
| 安全性 | 成熟,2048位以上足够安全 |
| 签名速度 | 慢(私钥操作涉及大数模幂) |
| 验签速度 | 快(公钥指数通常选65537) |
| 密钥体积 | 大(公钥256字节,私钥更大) |
| 签名体积 | 大(与密钥长度相同,2048位=256字节) |
| 代码体积 | 大(需要大数运算库) |
我曾经踩过的坑:在某款低端MCU上实现RSA-2048签名,发现一次签名耗时超过3秒。原因是没有硬件加速器,纯软件大数模幂运算太慢。后来不得不改用ECDSA。
4.2 ECDSA签名:椭圆曲线的优雅方案
ECDSA基于椭圆曲线离散对数难题。同样的安全强度下,密钥长度比RSA短得多。我个人习惯在资源受限的嵌入式设备上优先考虑ECDSA。
ECDSA签名流程(以secp256r1为例):
- 生成随机数k,计算椭圆曲线点R = k * G。
- 计算r = R.x mod n。
- 计算s = k^(-1) * (H(m) + r * d) mod n。
- 签名对为(r, s)。
常用曲线对比:
| 曲线名称 | 密钥长度 | 安全等级 | 典型应用 |
|---|---|---|---|
| secp256r1 (P-256) | 256位 | 128位 | IoT、TLS |
| secp384r1 (P-384) | 384位 | 192位 | 高安全场景 |
| secp521r1 (P-521) | 521位 | 256位 | 军工级 |
我的建议:大多数嵌入式固件签名场景,secp256r1就够用了。它和RSA-3072安全等级相当,但密钥只有32字节,签名也只有64字节。
ECDSA的痛点:
- 签名需要高质量的随机数生成器。随机数重复或可预测,私钥就会泄露。我在2018年审计过一个项目,发现他们的随机数种子竟然是固定值...嗯,后果可想而知。
- 验签比RSA慢一些,因为涉及椭圆曲线点乘运算。
- 实现复杂度高,容易引入侧信道漏洞。
4.3 Ed25519签名:后起之秀,又快又安全
Ed25519是EdDSA算法在Curve25519曲线上的具体实现。它由Daniel J. Bernstein设计,近年来在嵌入式领域越来越受欢迎。
Ed25519的亮点:
- 签名速度极快,比ECDSA快2-3倍。
- 验签速度也快,比ECDSA快1.5倍左右。
- 密钥和签名体积小:公钥32字节,签名64字节。
- 不需要随机数生成器!签名是确定性的,避免了随机数质量带来的安全风险。
- 抗侧信道攻击设计,实现相对安全。
核心优势:Ed25519的签名过程不依赖随机数,这意味着你不需要在MCU上维护一个高质量的TRNG或DRBG。对于没有硬件随机数发生器的设备来说,这简直是福音。
Ed25519的局限性:
- 标准化时间较晚(2011年),部分老旧系统不支持。
- FIPS认证尚未覆盖(但NIST SP 800-186已纳入)。
- 某些硬件加速器不支持Ed25519,只能纯软件实现。
4.4 三种算法综合对比
| 对比维度 | RSA-2048 | ECDSA (P-256) | Ed25519 |
|---|---|---|---|
| 安全强度 | 112位 | 128位 | 128位 |
| 公钥长度 | 256字节 | 32字节 | 32字节 |
| 签名长度 | 256字节 | 64字节 | 64字节 |
| 签名速度 | 慢 | 中等 | 快 |
| 验签速度 | 快 | 中等 | 快 |
| 随机数依赖 | 是(PKCS#1 v1.5填充) | 是 | 否 |
| 代码复杂度 | 中等 | 高 | 中等 |
| 硬件加速支持 | 广泛 | 广泛 | 较少 |
| 标准化程度 | 极高 | 高 | 中等 |
4.5 选型建议:到底该用哪个?
这个问题没有标准答案,得看你的具体场景。我一般按以下逻辑来选:
- 如果MCU有硬件RSA加速器,且对签名体积不敏感,选RSA-2048。验签快,实现简单。
- 如果MCU资源紧张,且需要频繁签名(比如OTA升级包签名),优先考虑Ed25519。速度快,无随机数依赖,省心。
- 如果项目需要通过FIPS认证,或者客户指定了算法,选ECDSA P-256。虽然实现复杂点,但合规性没问题。
- 如果设备没有硬件随机数生成器,千万别用ECDSA。Ed25519或RSA是更安全的选择。
我曾经犯过的错:在一个智能门锁项目里,我选了ECDSA P-256,但MCU没有TRNG。我用软件伪随机数生成器凑合,结果生产批次中出现了两次签名碰撞。虽然概率极低,但一旦发生,攻击者就能推导出私钥。后来全部召回,改用Ed25519。
4.6 核心知识体系
下面这张图总结了三种签名算法的核心对比维度,方便你快速决策:
4.7 实际项目中的注意事项
最后分享几个我在项目中积累的经验:
- 密钥生命周期管理:签名私钥不能直接放在固件里。生产时用HSM或安全芯片生成和存储私钥,公钥可以烧录在设备BootROM中。
- 哈希算法搭配:RSA通常搭配SHA-256,ECDSA和Ed25519内部已经指定了哈希算法(Ed25519用SHA-512)。别乱改,改了可能引入漏洞。
- 签名缓存:如果设备需要频繁验签(比如每次启动都验),可以把验签结果缓存起来,避免重复计算。我在一个工业控制器上就是这么做的,启动时间从2秒降到了0.3秒。
- 测试向量验证:实现完签名算法后,一定要用官方测试向量验证。我见过太多“看起来能跑,但验签总是失败”的案例,最后发现是字节序搞反了。
我的个人习惯:新项目起步时,我会先用Ed25519做原型验证。如果后续发现性能瓶颈或合规需求,再切换到ECDSA或RSA。Ed25519的实现代码少,调试起来也快。