logo
25
3
WeChat Login

Native EdDSA signature#32

Closed
created 2025-08-22
RhinoBird2025-P2
clq-2025/TencentKona-17:RhinoBird2025-P2
Edit
OverviewCommits
7
Files changed
5
Attachments

PR: EdDSA Native Implementation with OpenSSL via JNI

本 PR 完成了 issue #28 的实现,主要目标是为 EdDSA 算法引入基于 OpenSSL 的本地实现支持,并通过 JNI 集成到 JDK 中,以提升签名与验证性能。


代码改动

1. Java 层

  • src/jdk.crypto.ec/share/classes/sun/security/ec/NativeSunEC.java

    • 新增 EdDSA 曲线的 NID 定义
    • 增加相关方法以调用本地实现
  • src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSASignature.java

    • 增加对本地 EdDSA 签名与验证的支持
    • 提供开关以在纯 Java 与本地实现间切换

2. Native 层

  • src/jdk.crypto.ec/share/native/libsuneccrypto/sunec_ed.c

    • 新增文件,实现与 OpenSSL EdDSA 的交互逻辑
    • 通过 JNI 暴露给 NativeSunEC

3. 测试

  • JTREG 测试

    • 新增 test/jdk/sun/security/ec/ed/NativeEdDSASignature.java
    • 验证 EdDSA 本地实现功能正确性
  • JMH 基准测试

    • 新增 test/micro/org/openjdk/bench/javax/crypto/full/NativeEdDSASignatureBench.java
    • 对比纯 Java 与本地实现的性能差异

测试方法

JTREG

执行功能正确性测试:

make test TEST="jdk/sun/security/ec/ed/NativeEdDSASignature.java"

JMH

测试纯 Java 实现

make test TEST="micro:NativeEdDSASignatureBench" \
  MICRO="OPTIONS=-prof gc '-Djdk.sunec.enableNativeCrypto=false'"

测试 Native 实现

make test TEST="micro:NativeEdDSASignatureBench" \
  MICRO="OPTIONS=-prof gc '-Djdk.sunec.enableNativeCrypto=true -Djdk.openssl.cryptoLibPath=/usr/lib/x86_64-linux-gnu/libcrypto.so.3'"

JMH 基准测试结果

纯 Java 实现

BenchmarkAlgorithmdataSizeModeCntScoreErrorUnits
EdDSABench.signEd2551964thrpt51750.597± 27.845ops/s
EdDSABench.sign:gc.alloc.rateEd2551964thrpt523.506± 0.374MB/sec
EdDSABench.sign:gc.alloc.rate.normEd2551964thrpt514080.026± 0.012B/op
EdDSABench.sign:gc.countEd2551964thrpt516.000counts
EdDSABench.sign:gc.timeEd2551964thrpt521.000ms
EdDSABench.signEd255191024thrpt51748.836± 10.523ops/s
EdDSABench.sign:gc.alloc.rateEd255191024thrpt526.684± 0.161MB/sec
EdDSABench.sign:gc.alloc.rate.normEd255191024thrpt516000.026± 0.007B/op
EdDSABench.sign:gc.countEd255191024thrpt518.000counts
EdDSABench.sign:gc.timeEd255191024thrpt523.000ms
EdDSABench.signEd2551916384thrpt51653.732± 11.415ops/s
EdDSABench.sign:gc.alloc.rateEd2551916384thrpt573.681± 0.507MB/sec
EdDSABench.sign:gc.alloc.rate.normEd2551916384thrpt546720.027± 0.010B/op
EdDSABench.sign:gc.countEd2551916384thrpt551.000counts
EdDSABench.sign:gc.timeEd2551916384thrpt546.000ms
EdDSABench.signEd44864thrpt5523.689± 11.719ops/s
EdDSABench.sign:gc.alloc.rateEd44864thrpt574.928± 1.677MB/sec
EdDSABench.sign:gc.alloc.rate.normEd44864thrpt5150032.082± 0.013B/op
EdDSABench.sign:gc.countEd44864thrpt551.000counts
EdDSABench.sign:gc.timeEd44864thrpt544.000ms
EdDSABench.signEd4481024thrpt5517.758± 0.550ops/s
EdDSABench.sign:gc.alloc.rateEd4481024thrpt575.027± 0.530MB/sec
EdDSABench.sign:gc.alloc.rate.normEd4481024thrpt5151952.085± 0.001B/op
EdDSABench.sign:gc.countEd4481024thrpt552.000counts
EdDSABench.sign:gc.timeEd4481024thrpt546.000ms
EdDSABench.signEd44816384thrpt5494.273± 3.489ops/s
EdDSABench.sign:gc.alloc.rateEd44816384thrpt586.104± 0.688MB/sec
EdDSABench.sign:gc.alloc.rate.normEd44816384thrpt5182672.089± 0.091B/op
EdDSABench.sign:gc.countEd44816384thrpt560.000counts
EdDSABench.sign:gc.timeEd44816384thrpt553.000ms
EdDSABench.verifyEd2551964thrpt51831.305± 405.131ops/s
EdDSABench.verify:gc.alloc.rateEd2551964thrpt557.394± 12.697MB/sec
EdDSABench.verify:gc.alloc.rate.normEd2551964thrpt532864.025± 0.014B/op
EdDSABench.verify:gc.countEd2551964thrpt535.000counts
EdDSABench.verify:gc.timeEd2551964thrpt535.000ms
EdDSABench.verifyEd255191024thrpt51895.277± 54.898ops/s
EdDSABench.verify:gc.alloc.rateEd255191024thrpt573.780± 2.242MB/sec
EdDSABench.verify:gc.alloc.rate.normEd255191024thrpt542856.026± 0.014B/op
EdDSABench.verify:gc.countEd255191024thrpt551.000counts
EdDSABench.verify:gc.timeEd255191024thrpt544.000ms
EdDSABench.verifyEd2551916384thrpt51731.408± 59.757ops/s
EdDSABench.verify:gc.alloc.rateEd2551916384thrpt5121.049± 4.176MB/sec
EdDSABench.verify:gc.alloc.rate.normEd2551916384thrpt573312.026± 0.016B/op
EdDSABench.verify:gc.countEd2551916384thrpt573.000counts
EdDSABench.verify:gc.timeEd2551916384thrpt573.000ms
EdDSABench.verifyEd44864thrpt5558.388± 9.996ops/s
EdDSABench.verify:gc.alloc.rateEd44864thrpt596.208± 1.719MB/sec
EdDSABench.verify:gc.alloc.rate.normEd44864thrpt5189672.078± 0.017B/op
EdDSABench.verify:gc.countEd44864thrpt560.000counts
EdDSABench.verify:gc.timeEd44864thrpt560.000ms
EdDSABench.verifyEd4481024thrpt5549.635± 8.050ops/s
EdDSABench.verify:gc.alloc.rateEd4481024thrpt595.585± 1.399MB/sec
EdDSABench.verify:gc.alloc.rate.normEd4481024thrpt5182360.081± 0.011B/op
EdDSABench.verify:gc.countEd4481024thrpt565.000counts
EdDSABench.verify:gc.timeEd4481024thrpt557.000ms
EdDSABench.verifyEd44816384thrpt5537.589± 7.217ops/s
EdDSABench.verify:gc.alloc.rateEd44816384thrpt5109.292± 1.461MB/sec
EdDSABench.verify:gc.alloc.rate.normEd44816384thrpt5213184.083± 0.010B/op
EdDSABench.verify:gc.countEd44816384thrpt575.000counts
EdDSABench.verify:gc.timeEd44816384thrpt568.000ms
  • Ed25519 签名性能约 1.7k ops/s
  • Ed448 签名性能约 500 ops/s
  • 验证性能与签名相近,但 GC 开销较高(B/op 数量级大)

Native 实现(基于 OpenSSL)

BenchmarkAlgorithmdataSizeModeCntScoreErrorUnits
EdDSABench.signEd2551964thrpt513805.520± 874.334ops/s
EdDSABench.sign:gc.alloc.rateEd2551964thrpt54.318± 0.274MB/sec
EdDSABench.sign:gc.alloc.rate.normEd2551964thrpt5328.003± 0.001B/op
EdDSABench.sign:gc.countEd2551964thrpt53.000counts
EdDSABench.sign:gc.timeEd2551964thrpt55.000ms
EdDSABench.signEd255191024thrpt513572.522± 580.612ops/s
EdDSABench.sign:gc.alloc.rateEd255191024thrpt529.097± 1.245MB/sec
EdDSABench.sign:gc.alloc.rate.normEd255191024thrpt52248.003± 0.001B/op
EdDSABench.sign:gc.countEd255191024thrpt520.000counts
EdDSABench.sign:gc.timeEd255191024thrpt522.000ms
EdDSABench.signEd2551916384thrpt59104.879± 485.999ops/s
EdDSABench.sign:gc.alloc.rateEd2551916384thrpt5286.254± 15.291MB/sec
EdDSABench.sign:gc.alloc.rate.normEd2551916384thrpt532968.005± 0.001B/op
EdDSABench.sign:gc.countEd2551916384thrpt5198.000counts
EdDSABench.sign:gc.timeEd2551916384thrpt5172.000ms
EdDSABench.signEd44864thrpt52566.018± 178.947ops/s
EdDSABench.sign:gc.alloc.rateEd44864thrpt50.940± 0.066MB/sec
EdDSABench.sign:gc.alloc.rate.normEd44864thrpt5384.018± 0.097B/op
EdDSABench.sign:gc.countEd44864thrpt51.000counts
EdDSABench.sign:gc.timeEd44864thrpt51.000ms
EdDSABench.signEd4481024thrpt52602.332± 68.678ops/s
EdDSABench.sign:gc.alloc.rateEd4481024thrpt55.718± 0.161MB/sec
EdDSABench.sign:gc.alloc.rate.normEd4481024thrpt52304.017± 0.009B/op
EdDSABench.sign:gc.countEd4481024thrpt54.000counts
EdDSABench.sign:gc.timeEd4481024thrpt57.000ms
EdDSABench.signEd44816384thrpt52251.679± 19.011ops/s
EdDSABench.sign:gc.alloc.rateEd44816384thrpt570.912± 0.597MB/sec
EdDSABench.sign:gc.alloc.rate.normEd44816384thrpt533024.020± 0.088B/op
EdDSABench.sign:gc.countEd44816384thrpt549.000counts
EdDSABench.sign:gc.timeEd44816384thrpt545.000ms
EdDSABench.verifyEd2551964thrpt510315.092± 447.194ops/s
EdDSABench.verify:gc.alloc.rateEd2551964thrpt52.440± 0.106MB/sec
EdDSABench.verify:gc.alloc.rate.normEd2551964thrpt5248.004± 0.001B/op
EdDSABench.verify:gc.countEd2551964thrpt51.000counts
EdDSABench.verify:gc.timeEd2551964thrpt52.000ms
EdDSABench.verifyEd255191024thrpt510118.079± 214.473ops/s
EdDSABench.verify:gc.alloc.rateEd255191024thrpt520.919± 0.443MB/sec
EdDSABench.verify:gc.alloc.rate.normEd255191024thrpt52168.004± 0.001B/op
EdDSABench.verify:gc.countEd255191024thrpt514.000counts
EdDSABench.verify:gc.timeEd255191024thrpt522.000ms
EdDSABench.verifyEd2551916384thrpt54902.671± 54.306ops/s
EdDSABench.verify:gc.alloc.rateEd2551916384thrpt5263.356± 1.700MB/sec
EdDSABench.verify:gc.alloc.rate.normEd2551916384thrpt532838.026± 0.016B/op
EdDSABench.verify:gc.countEd2551916384thrpt5184.000counts
EdDSABench.verify:gc.timeEd2551916384thrpt5160.000ms
EdDSABench.verifyEd44864thrpt54779.592± 48.256ops/s
EdDSABench.verify:gc.alloc.rateEd44864thrpt51.116± 0.011MB/sec
EdDSABench.verify:gc.alloc.rate.normEd44864thrpt5248.004± 0.001B/op
EdDSABench.verify:gc.countEd44864thrpt51.000counts
EdDSABench.verify:gc.timeEd44864thrpt52.000ms
EdDSABench.verifyEd4481024thrpt54784.292± 143.738ops/s
EdDSABench.verify:gc.alloc.rateEd4481024thrpt59.892± 0.297MB/sec
EdDSABench.verify:gc.alloc.rate.normEd4481024thrpt52168.009± 0.001B/op
EdDSABench.verify:gc.countEd4481024thrpt57.000counts
EdDSABench.verify:gc.timeEd4481024thrpt513.000ms
EdDSABench.verifyEd44816384thrpt54116.051± 75.161ops/s
EdDSABench.verify:gc.alloc.rateEd44816384thrpt5129.093± 2.358MB/sec
EdDSABench.verify:gc.alloc.rate.normEd44816384thrpt532888.011± 0.002B/op
EdDSABench.verify:gc.countEd44816384thrpt590.000counts
EdDSABench.verify:gc.timeEd44816384thrpt577.000ms
  • Ed25519 签名性能提升至 13k ops/s,约 7.5x 提升
  • Ed448 签名性能提升至 2.6k ops/s,约 5x 提升
  • 验证性能同样显著提升(约 10x),且 GC 开销极低(B/op 数量级显著下降)

EdDSA 性能对比(JMH 测试结果)

算法操作纯 Java 实现 (ops/s)Native 实现 (ops/s)提升倍数
Ed25519签名~1,750~13,800≈ 7.9x
验证~1,830~10,300≈ 5.6x
Ed448签名~520~2,560≈ 4.9x
验证~560~4,780≈ 8.5x

📊 从表格可以直观看出:

  • Ed25519:签名提升接近 8 倍,验证提升 5–6 倍
  • Ed448:签名提升约 5 倍,验证提升接近 9 倍
  • 同时 GC 开销显著降低,Native 实现更适合高性能场景

性能对比总结

  • 本地实现显著降低了 GC 压力(B/op 数量从数万降至数百)

  • Ed25519Ed448 两种曲线上,签名与验证性能均获得 5–10 倍提升

  • 本地实现适用于对性能敏感的场景,可通过系统属性切换:

    • -Djdk.sunec.enableNativeCrypto=true
    • -Djdk.openssl.cryptoLibPath=<libcrypto 路径>

结论

本 PR 为 JDK 的 EdDSA 算法引入了 OpenSSL 的本地实现支持:

  • ✅ 功能层面:保持与现有纯 Java 实现一致
  • ✅ 测试层面:通过 JTREG 与 JMH 验证正确性与性能
  • ✅ 性能层面:实现 5–10 倍性能提升,显著降低 GC 开销
administrator

关于JMH测试的结果,为什么格式有些凌乱?
JMH在输出结果时,应该作过格式化的。

Benchmark                          (dataSize)  Mode  Cnt   Score   Error  Units
EdDSABench.sign:?gc.alloc.rate     Ed25519      64   thrpt   5  1750.597  ?  27.845  ops/s
EdDSABench.sign:?gc.alloc.rate.norm Ed25519      64   thrpt   5   23.506  ?   0.374  MB/sec
EdDSABench.sign:?gc.count         Ed25519      64   thrpt   5  14080.026  ?   0.012  B/op
EdDSABench.sign:?gc.time          Ed25519      64   thrpt   5    16.000  ?     counts
EdDSABench.sign                   Ed25519      64   thrpt   5    21.000  ?    ms
EdDSABench.sign                   Ed25519    1024   thrpt   5  1748.836  ?   10.523  ops/s
EdDSABench.sign:?gc.alloc.rate    Ed25519    1024   thrpt   5   26.684  ?   0.161  MB/sec
EdDSABench.sign:?gc.alloc.rate.norm Ed25519    1024   thrpt   5  16000.026  ?   0.007  B/op
EdDSABench.sign:?gc.count         Ed25519    1024   thrpt   5    18.000  ?     counts
...
createor

关于JMH测试的结果,为什么格式有些凌乱?
JMH在输出结果时,应该作过格式化的。

Benchmark                          (dataSize)  Mode  Cnt   Score   Error  Units
EdDSABench.sign:?gc.alloc.rate     Ed25519      64   thrpt   5  1750.597  ?  27.845  ops/s
EdDSABench.sign:?gc.alloc.rate.norm Ed25519      64   thrpt   5   23.506  ?   0.374  MB/sec
EdDSABench.sign:?gc.count         Ed25519      64   thrpt   5  14080.026  ?   0.012  B/op
EdDSABench.sign:?gc.time          Ed25519      64   thrpt   5    16.000  ?     counts
EdDSABench.sign                   Ed25519      64   thrpt   5    21.000  ?    ms
EdDSABench.sign                   Ed25519    1024   thrpt   5  1748.836  ?   10.523  ops/s
EdDSABench.sign:?gc.alloc.rate    Ed25519    1024   thrpt   5   26.684  ?   0.161  MB/sec
EdDSABench.sign:?gc.alloc.rate.norm Ed25519    1024   thrpt   5  16000.026  ?   0.007  B/op
EdDSABench.sign:?gc.count         Ed25519    1024   thrpt   5    18.000  ?     counts
...

@johnjiang(jiangsha) 格式有些凌乱是因为我把数据图片给gpt让他分析性能变化并要他以markdown格式生成报告,gpt并未对数据进行格式对齐。

closed the pull request
No conflicts between the source branch and the target branch
Reviewer
None yet
Assignee
None yet
Label
None yet
Participant