4、ECC签名算法:椭圆曲线密码学基础、ECDSA签名流程、Ed25519的优势

说到非对称签名,RSA 统治了很多年。但这些年,ECC(椭圆曲线密码学)越来越流行。为什么?因为同样的安全强度,ECC 的密钥短得多,计算也快。在嵌入式这种资源受限的环境里,这简直是天大的优势。

我个人习惯把 ECC 看作 RSA 的「升级替代方案」。你想想看,一个 256 位的 ECC 密钥,安全性和 3072 位的 RSA 差不多。省下的那几千比特,在 Flash 和 RAM 里都是真金白银。

4.1 椭圆曲线密码学基础

椭圆曲线长什么样?数学上,它是一类方程:y² = x³ + ax + b。画出来是一条关于 x 轴对称的曲线。但密码学里用的,不是连续曲线上的所有点,而是定义在有限域上的离散点集。

说白了,ECC 的安全性建立在「椭圆曲线离散对数问题」上:给定基点 G 和公钥 Q = kG,想反推出私钥 k,在计算上几乎不可能。这就是 ECC 的根基。

核心参数(以 secp256r1 为例):

  • p:定义有限域的素数(256 位)
  • a, b:曲线方程系数
  • G:基点(一个公开的曲线上的点)
  • n:基点 G 的阶(一个很大的素数)
  • h:余因子(通常为 1)

我在项目中遇到过一个问题:有人直接把 OpenSSL 生成的 secp256r1 密钥对放到 STM32 上,结果签名验签死活不对。查了半天,发现是曲线参数没对齐——嵌入式端的库用了不同的字节序。嗯,这里要注意,参数传递时一定要确认大端小端。

4.2 ECDSA 签名流程

ECDSA(椭圆曲线数字签名算法)是目前最主流的 ECC 签名方案。它的流程比 RSA 复杂一点,但理解后其实很清晰。

我把它拆成三步:密钥生成、签名、验签。

4.2.1 密钥生成

  1. 选择一个椭圆曲线(如 secp256r1)和基点 G。
  2. 随机生成一个私钥 d(一个小于 n 的大整数)。
  3. 计算公钥 Q = d * G(椭圆曲线上的点乘)。

4.2.2 签名过程

  1. 对消息 m 做哈希,得到 e = HASH(m)。
  2. 生成一个随机数 k(每次签名必须不同!)。
  3. 计算点 R = k * G,取 R 的 x 坐标作为 r。
  4. 计算 s = k⁻¹ * (e + r * d) mod n。
  5. 签名值就是 (r, s)。

⚠️ 随机数 k 绝对不能重复!

我曾经见过一个产品,因为随机数生成器坏了,两次签名用了同一个 k。攻击者直接通过两个签名反推出了私钥。这在 ECDSA 里是致命的。如果你用硬件随机数生成器,一定要做健康检测。

4.2.3 验签过程

  1. 对消息 m 做哈希,得到 e = HASH(m)。
  2. 检查 r, s 是否在 [1, n-1] 范围内。
  3. 计算 w = s⁻¹ mod n。
  4. 计算 u1 = e * w mod n,u2 = r * w mod n。
  5. 计算点 P = u1 * G + u2 * Q。
  6. 如果 P 的 x 坐标等于 r,验签通过;否则失败。

你看,验签不需要私钥,只需要公钥 Q。这就是非对称签名的精髓。

💡 我的经验:在嵌入式里实现 ECDSA 验签时,尽量用硬件加速器。很多 MCU(如 NXP i.MX RT 系列、STM32H7)都内置了椭圆曲线硬件引擎。纯软件实现 256 位 ECDSA 验签,在 200MHz 的 Cortex-M7 上大概要 10-20 毫秒。硬件加速可以压到 1 毫秒以内。

4.3 Ed25519 的优势

ECDSA 虽然好,但有几个「坑」:随机数 k 的生成、侧信道攻击、实现复杂度。于是有了 Ed25519。

Ed25519 是基于 Curve25519 的 Edwards 曲线数字签名算法。它和 ECDSA 最大的区别是什么?我总结了几点:

特性 ECDSA (secp256r1) Ed25519
曲线类型 Weierstrass 曲线 Edwards 曲线
签名大小 64 字节 64 字节
公钥大小 64 字节(未压缩) 32 字节
随机数需求 每次签名需要高质量随机数 确定性签名(不需要随机数)
侧信道防护 实现不当容易泄露私钥 天然抗侧信道
性能 较快 更快(尤其验签)

Ed25519 最大的优势,我个人认为是「确定性签名」。它用私钥和消息哈希一起派生出一个伪随机数,而不是依赖真随机数生成器。这意味着:

  • 同样的消息和私钥,永远产生同样的签名。
  • 不需要硬件随机数生成器。
  • 不存在随机数重复导致私钥泄露的风险。

另外,Ed25519 的实现天然是常数时间的。ECDSA 里如果你不小心,点乘运算的时间可能会泄露私钥的比特位。Ed25519 的曲线设计让常数时间实现变得简单很多。

我的建议:如果你在做一个新的安全启动方案,而且没有历史兼容性要求,直接上 Ed25519。我在一个 IoT 网关项目里从 ECDSA 切到 Ed25519 后,签名速度提升了 30%,而且再也不用担心随机数生成器出问题了。

不过,Ed25519 也不是万能的。它和传统的 ECDSA 不兼容。如果你的系统需要和现有的 PKI 体系(如 X.509 证书)对接,可能还是得用 ECDSA。另外,有些老旧的安全芯片只支持 ECDSA,不支持 Ed25519。

下面这张图展示了 ECDSA 和 Ed25519 在安全启动中的核心流程对比:

ECDSA vs Ed25519 安全启动签名流程对比 ECDSA 签名流程 ① 生成随机数 k(需高质量熵源) ② 计算 R = k*G,取 r = R.x ③ 计算 s = k⁻¹ * (HASH(m) + r*d) ④ 输出签名 (r, s) 共 64 字节 ⚠️ 风险:随机数 k 重复 → 私钥泄露 ⚠️ 风险:非恒定时间实现 → 侧信道攻击 Ed25519 签名流程 ① 用私钥 + 消息哈希派生伪随机数 r ② 计算 R = r * B(B 为基点) ③ 计算 S = r + HASH(R, A, m) * a ④ 输出签名 (R, S) 共 64 字节 ✅ 优势:确定性签名,无需随机数生成器 ✅ 优势:天然恒定时间,抗侧信道攻击 结论:新项目优先选 Ed25519,兼容性要求选 ECDSA 安全启动场景下,Ed25519 更安全、更易实现

最后说一句,不管用哪种算法,密钥的存储和保护才是安全启动的命门。算法再强,私钥被人读走了,一切白搭。我习惯把私钥放在安全元件或 MCU 内置的 OTP 区域里,并且启用读保护。嗯,这部分我们后面会详细讲。