bigywater.tech
Java · 407

EdDSA:现代椭圆曲线签名

Ed25519 常被当作 ECDSA 和 RSA 的现代替代。这篇在 JDK 21 上量出它的大小、确定性、与 RFC 8032 和 OpenSSL 的互通、验证边界,以及真实的性能数字——结果里有一条与常见印象相反。

1 vs 20
同一私钥同一消息签 20 次,Ed25519 与 ECDSA P-256 的不同签名个数
逐字节相同
Java 的 Ed25519 签名与 RFC 8032 测试向量 1 的签名、与 OpenSSL 签名的比较结果
422 vs 120 µs
JDK 21 上 Ed25519 与 ECDSA P-256 的单次签名耗时

大小与 API

实测 · 本机执行输出
  Ed25519:算法 EdDSA,公钥 44 字节(X.509),私钥 48 字节(PKCS#8),签名 64 字节,公钥类型 EdECPublicKey
  Ed448:公钥 69 字节,私钥 73 字节,签名 114 字节
  ECDSA P-256:公钥 91 字节,私钥 67 字节,签名(DER)70 字节(长度随 r、s 变化,常见 70–72)
  RSA 2048:公钥 294 字节,私钥 1217 字节,签名 256 字节
  Ed25519 initialize(256):InvalidParameterException:Unsupported size: 256
  Signature.getInstance("EdDSA") 的提供者 SunEC,Ed25519 的提供者 SunEC

确定性

实测 · 本机执行输出
  同一把私钥、同一条消息各签 20 次,不同的签名个数:Ed25519 1,ECDSA P-256 20,RSA PKCS#1 v1.5 1,RSASSA-PSS 20

RFC 8032 与 OpenSSL

实测 · 本机执行输出
  RFC 8032 测试向量 1(种子 9d61b19d…,空消息):Java 的签名与 RFC 给出的签名完全相同 = true(e5564300c360ac729086e2cc806e828a…)
  EdECPrivateKey.getBytes() 是 32 字节(就是 32 字节种子)= true
  已把 Java 生成的密钥和签名写到文件(公钥 X.509 DER、私钥 PKCS#8 DER、java.sig)
  openssl 版本:OpenSSL 4.0.3 29 Sep 2026 (Library: OpenSSL 4.0.3 29 Sep 2026)
  openssl 验证 Java 生成的签名:Signature Verified Successfully
  openssl 用 Java 的私钥签名:退出码 0,签名 64 字节;与 Java 的签名逐字节相同 = True
  Java 验证 openssl 生成的签名:true

篡改与非法输入

实测 · 本机执行输出
  原样验证:true
      抛出 SignatureException:Invalid point
  签名第 0 字节翻转 1 位:false
  签名第 40 字节(S 部分)翻转 1 位:false
  消息改了一个字节:false
  用另一把公钥验证:false
  签名截断成 63 字节:
      抛出 SignatureException:signature length invalid
    结果 false
  签名加长到 65 字节:
      抛出 SignatureException:signature length invalid
    结果 false
      抛出 SignatureException:s is too large
  可锻性测试:把 S 换成 S + L(模 L 同余但数值不同,S + L < 2^256):false(RFC 8032 要求验证者拒绝 S ≥ L 的签名)
  用 Ed448 公钥初始化 Ed25519 的验证:InvalidKeyException:Parameters must be Ed25519

性能

实测 · 本机执行输出
  Ed25519                          签名 422 µs/次(约 2372 次/秒),验证 432 µs/次(约 2316 次/秒)
  ECDSA P-256 (SHA256withECDSA)    签名 120 µs/次(约 8316 次/秒),验证 399 µs/次(约 2507 次/秒)
  RSA 2048 (SHA256withRSA)         签名 871 µs/次(约 1148 次/秒),验证 35 µs/次(约 28171 次/秒)
  RSA 3072 (SHA256withRSA)         签名 2539 µs/次(约 394 次/秒),验证 68 µs/次(约 14757 次/秒)
  生成密钥对:Ed25519 约 0.24 ms,RSA 2048 约 113 ms

分步演示

EdDSA
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK(Temurin 17.0.20、Homebrew 21.0.12 与 27,每篇注明实际用的版本);用 javac 编译、java 直接运行,需要第三方库时用 Maven 解析依赖;计时用 System.nanoTime,数字每次运行会有小幅抖动。JDK 21.0.12(SunEC);OpenSSL 4.0.3(本机);性能数字是自写的 nanoTime 循环、单线程、5 轮中位数,不是 JMH;每次都新建 initSign / initVerify
    • 没有验证:Ed25519ph / Ed25519ctx(预哈希与上下文)、Ed448 的性能、JDK 17 与 JDK 27 的性能差异、其它提供者(BouncyCastle)、批量验证、侧信道特性(JDK 没有给出常数时间的承诺)
    京ICP备2026067502号-1京公网安备11010502063487号