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为例):

  1. 生成随机数k,计算椭圆曲线点R = k * G。
  2. 计算r = R.x mod n。
  3. 计算s = k^(-1) * (H(m) + r * d) mod n。
  4. 签名对为(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-2048ECDSA (P-256)Ed25519
安全强度112位128位128位
公钥长度256字节32字节32字节
签名长度256字节64字节64字节
签名速度慢中等快
验签速度快中等快
随机数依赖是(PKCS#1 v1.5填充)是否
代码复杂度中等高中等
硬件加速支持广泛广泛较少
标准化程度极高高中等

4.5 选型建议:到底该用哪个?

这个问题没有标准答案,得看你的具体场景。我一般按以下逻辑来选:

  1. 如果MCU有硬件RSA加速器,且对签名体积不敏感,选RSA-2048。验签快,实现简单。
  2. 如果MCU资源紧张,且需要频繁签名(比如OTA升级包签名),优先考虑Ed25519。速度快,无随机数依赖,省心。
  3. 如果项目需要通过FIPS认证,或者客户指定了算法,选ECDSA P-256。虽然实现复杂点,但合规性没问题。
  4. 如果设备没有硬件随机数生成器,千万别用ECDSA。Ed25519或RSA是更安全的选择。

我曾经犯过的错:在一个智能门锁项目里,我选了ECDSA P-256,但MCU没有TRNG。我用软件伪随机数生成器凑合,结果生产批次中出现了两次签名碰撞。虽然概率极低,但一旦发生,攻击者就能推导出私钥。后来全部召回,改用Ed25519。

4.6 核心知识体系

下面这张图总结了三种签名算法的核心对比维度,方便你快速决策:

固件签名算法选型决策图 RSA-2048 公钥: 256B | 签名: 256B 验签快 | 签名慢 硬件加速广泛 适合: 有加速器的设备 ECDSA P-256 公钥: 32B | 签名: 64B 签名中等 | 验签中等 需高质量随机数 适合: 合规要求场景 Ed25519 公钥: 32B | 签名: 64B 签名快 | 验签快 无需随机数 适合: 资源受限设备 选型决策流程 有硬件加速器? → 有TRNG? → 需FIPS认证? → 资源限制? 有硬件RSA加速器 → 选RSA-2048 验签性能最优 无TRNG / 资源紧张 → 选Ed25519 确定性签名,省心 需FIPS / 客户指定 → 选ECDSA P-256 合规优先 ⚠️ 重要提醒 1. 无论选哪种算法,私钥存储必须使用安全元件或HSM 2. 签名算法只是安全链条的一环,还需配合安全启动、防回滚等机制

4.7 实际项目中的注意事项

最后分享几个我在项目中积累的经验:

  • 密钥生命周期管理:签名私钥不能直接放在固件里。生产时用HSM或安全芯片生成和存储私钥,公钥可以烧录在设备BootROM中。
  • 哈希算法搭配:RSA通常搭配SHA-256,ECDSA和Ed25519内部已经指定了哈希算法(Ed25519用SHA-512)。别乱改,改了可能引入漏洞。
  • 签名缓存:如果设备需要频繁验签(比如每次启动都验),可以把验签结果缓存起来,避免重复计算。我在一个工业控制器上就是这么做的,启动时间从2秒降到了0.3秒。
  • 测试向量验证:实现完签名算法后,一定要用官方测试向量验证。我见过太多“看起来能跑,但验签总是失败”的案例,最后发现是字节序搞反了。

我的个人习惯:新项目起步时,我会先用Ed25519做原型验证。如果后续发现性能瓶颈或合规需求,再切换到ECDSA或RSA。Ed25519的实现代码少,调试起来也快。