Native EdDSA signature#29
| original file line number | diff file line number | diff file change |
|---|
是否测试过这个实现的有效性?
是否执行过与纯Java实现的互操作测试?
https://docs.openssl.org/3.5/man7/EVP_SIGNATURE-ED25519/#examples
上面OpenSSL的文档中的示例如下,
const OSSL_PARAM params[] = {
OSSL_PARAM_utf8_string ("instance", "Ed25519ctx", 10),
OSSL_PARAM_octet_string("context-string", (unsigned char *)"A protocol defined context string", 33),
OSSL_PARAM_END
};
/* The input "params" is not needed if default options are acceptable.
Use NULL in place of "params" in that case. */
EVP_DigestSignInit_ex(md_ctx, NULL, NULL, NULL, NULL, ed_key, params);
我将依此回答您的问题:
一.测试类有测试prehash和context参数处理的有效性。
在我的 NativeEdDSASignature.java 的 testEdDSAParameterSpecModes 方法中,包含了以下测试:
二.当前测试类没有执行与纯Java实现的互操作测试。
如果需要的话,我应该添加以下测试:
您看是否需要添加上述测试内容?
三.参考了OpenSSL的文档中的示例,我发现了当前实现存在的一些问题:
您看上述问题总结的是否全面,并且我是否需要进行这些更改?
关键点,没有针对EdDSAParameterSpec做与纯Java的互操作测试。
即便存在使用prehash和context的测试用例,但由于签名与验签名都是你的实现,依然无法判断它们的正确性。
试想极端情况,某个实现的验签操作总是返回true,那么无论测试用例用了哪些参数,验签总能通过。
如果prehash和context在你的sign与verify实现都没有被使用到,那么你的实现内部还是可以自洽的。
建议快速地做一下与纯Java的互操作测试,不用写到正式的JTREG程序中。
只是验证一下这个问题。
@johnjiang(jiangsha) 我临时写了测试类EdDSAInteropTest.java进行Native与纯Java实现的互操作测试,结果都通过了,成功验证了Native EdDSA实现与纯Java实现的完全兼容性:

测试结果总结
Ed25519曲线测试 :
✅ 基本互操作测试:Native签名→Java验证、Java签名→Native验证均通过
✅ EdDSAParameterSpec测试:Prehash、EmptyContext、NonEmptyContext、PrehashAndContext四种模式的双向互操作均通过
Ed448曲线测试 :
✅ 基本互操作测试:Native签名→Java验证、Java签名→Native验证均通过
✅ EdDSAParameterSpec测试:Prehash、EmptyContext、NonEmptyContext、PrehashAndContext四种模式的双向互操作均通过
EdDSAInteropTest.java的具体内容:
import java.security.*;
import java.security.spec.*;
import java.nio.charset.StandardCharsets;
import java.lang.reflect.Method;
/**
* 快速互操作测试:验证Native EdDSA实现与纯Java实现的兼容性
* 特别针对EdDSAParameterSpec的prehash和context参数
*/
public class EdDSAInteropTest {
private static final byte[] TEST_MESSAGE = "EdDSA Interop Test Message".getBytes(StandardCharsets.UTF_8);
private static final SecureRandom SECURE_RANDOM = new SecureRandom();
public static void main(String[] args) {
System.out.println("=== EdDSA Native-Java 互操作测试 ===");
try {
// 测试Ed25519
System.out.println("\n1. 测试Ed25519互操作性:");
testInteroperability("Ed25519", 255);
// 测试Ed448
System.out.println("\n2. 测试Ed448互操作性:");
testInteroperability("Ed448", 448);
System.out.println("\n=== 所有互操作测试通过! ===");
} catch (Exception e) {
System.err.println("互操作测试失败: " + e.getMessage());
e.printStackTrace();
System.exit(1);
}
}
private static void testInteroperability(String curveName, int keySize) throws Exception {
// 生成密钥对
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EdDSA");
kpg.initialize(keySize, SECURE_RANDOM);
KeyPair keyPair = kpg.generateKeyPair();
// 测试基本互操作性(无参数)
testBasicInterop(curveName, keyPair);
// 测试EdDSAParameterSpec互操作性
testParameterSpecInterop(curveName, keyPair);
}
private static void testBasicInterop(String curveName, KeyPair keyPair) throws Exception {
System.out.println(" 基本互操作测试 (" + curveName + "):");
// Native签名 -> Java验证
byte[] nativeSignature = signWithImplementation(keyPair.getPrivate(), true, null);
boolean javaVerifyNative = verifyWithImplementation(keyPair.getPublic(), nativeSignature, false, null);
System.out.println(" Native签名 -> Java验证: " + (javaVerifyNative ? "通过" : "失败"));
// Java签名 -> Native验证
byte[] javaSignature = signWithImplementation(keyPair.getPrivate(), false, null);
boolean nativeVerifyJava = verifyWithImplementation(keyPair.getPublic(), javaSignature, true, null);
System.out.println(" Java签名 -> Native验证: " + (nativeVerifyJava ? "通过" : "失败"));
if (!javaVerifyNative || !nativeVerifyJava) {
throw new RuntimeException(curveName + " 基本互操作测试失败");
}
}
private static void testParameterSpecInterop(String curveName, KeyPair keyPair) throws Exception {
System.out.println(" EdDSAParameterSpec互操作测试 (" + curveName + "):");
// 测试1: Prehash模式
EdDSAParameterSpec prehashSpec = new EdDSAParameterSpec(true);
testSpecInterop(curveName, keyPair, prehashSpec, "Prehash");
// 测试2: Context模式(空context)
EdDSAParameterSpec emptyContextSpec = new EdDSAParameterSpec(false, new byte[0]);
testSpecInterop(curveName, keyPair, emptyContextSpec, "EmptyContext");
// 测试3: Context模式(非空context)
byte[] testContext = "test-context-data".getBytes(StandardCharsets.UTF_8);
EdDSAParameterSpec contextSpec = new EdDSAParameterSpec(false, testContext);
testSpecInterop(curveName, keyPair, contextSpec, "NonEmptyContext");
// 测试4: Prehash + Context组合
EdDSAParameterSpec combinedSpec = new EdDSAParameterSpec(true, testContext);
testSpecInterop(curveName, keyPair, combinedSpec, "PrehashAndContext");
}
private static void testSpecInterop(String curveName, KeyPair keyPair,
EdDSAParameterSpec spec, String testName) throws Exception {
try {
// Native签名 -> Java验证
byte[] nativeSignature = signWithImplementation(keyPair.getPrivate(), true, spec);
boolean javaVerifyNative = verifyWithImplementation(keyPair.getPublic(), nativeSignature, false, spec);
// Java签名 -> Native验证
byte[] javaSignature = signWithImplementation(keyPair.getPrivate(), false, spec);
boolean nativeVerifyJava = verifyWithImplementation(keyPair.getPublic(), javaSignature, true, spec);
System.out.println(" " + testName + " - Native->Java: " + (javaVerifyNative ? "通过" : "失败") +
", Java->Native: " + (nativeVerifyJava ? "通过" : "失败"));
if (!javaVerifyNative || !nativeVerifyJava) {
throw new RuntimeException(curveName + " " + testName + " 互操作测试失败");
}
} catch (Exception e) {
System.out.println(" " + testName + " - 测试异常: " + e.getMessage());
// 对于某些参数组合,可能不被支持,这是可以接受的
if (e.getMessage().contains("not supported") || e.getMessage().contains("Invalid")) {
System.out.println(" " + testName + " - 跳过(不支持的参数组合)");
} else {
throw e;
}
}
}
private static byte[] signWithImplementation(PrivateKey privateKey, boolean useNative,
EdDSAParameterSpec spec) throws Exception {
// 强制使用指定实现
setNativeEnabled(useNative);
Signature signature = Signature.getInstance("EdDSA");
if (spec != null) {
signature.setParameter(spec);
}
signature.initSign(privateKey, SECURE_RANDOM);
signature.update(TEST_MESSAGE);
return signature.sign();
}
private static boolean verifyWithImplementation(PublicKey publicKey, byte[] signatureBytes,
boolean useNative, EdDSAParameterSpec spec) throws Exception {
// 强制使用指定实现
setNativeEnabled(useNative);
Signature signature = Signature.getInstance("EdDSA");
if (spec != null) {
signature.setParameter(spec);
}
signature.initVerify(publicKey);
signature.update(TEST_MESSAGE);
return signature.verify(signatureBytes);
}
private static void setNativeEnabled(boolean enabled) {
// 通过系统属性控制Native实现的使用
System.setProperty("jdk.sunec.enableNativeCrypto", String.valueOf(enabled));
try {
// 尝试通过反射重置NativeSunEC的状态(如果有缓存的话)
Class<?> nativeSunECClass = Class.forName("sun.security.ec.NativeSunEC");
// 某些实现可能有重置方法,这里尝试调用
try {
Method resetMethod = nativeSunECClass.getDeclaredMethod("resetNativeState");
resetMethod.setAccessible(true);
resetMethod.invoke(null);
} catch (NoSuchMethodException e) {
// 没有重置方法,忽略
}
} catch (Exception e) {
// 反射失败,忽略
}
}
}
private static void setNativeEnabled(boolean enabled) {
// 通过系统属性控制Native实现的使用
System.setProperty("jdk.sunec.enableNativeCrypto", String.valueOf(enabled));
try {
// 尝试通过反射重置NativeSunEC的状态(如果有缓存的话)
Class<?> nativeSunECClass = Class.forName("sun.security.ec.NativeSunEC");
// 某些实现可能有重置方法,这里尝试调用
try {
Method resetMethod = nativeSunECClass.getDeclaredMethod("resetNativeState");
resetMethod.setAccessible(true);
resetMethod.invoke(null);
} catch (NoSuchMethodException e) {
// 没有重置方法,忽略
}
} catch (Exception e) {
// 反射失败,忽略
}
}
NativeSunEC中并不存在方法resetNativeState,是你在本地又修改过了?
@johnjiang(jiangsha) 抱歉误导了您,我本地没有修改过NativeSunEC,也确实不存在方法resetNativeState,不过这样也不影响EdDSAInteropTest.java的正常测试,因为:
异常处理机制:EdDSAInteropTest.java中的setNativeEnabled方法已经通过try-catch块正确处理了NoSuchMethodException,当找不到resetNativeState方法时会忽略该异常并继续执行。
系统属性控制仍然有效:
System.setProperty("jdk.sunec.enableNativeCrypto", String.valueOf(enabled))设置系统属性IS_NATIVE_CRYPTO_ENABLED常量通过GetBooleanAction.privilegedGetProperty("jdk.sunec.enableNativeCrypto")读取该属性useNativeEdDSA()方法依赖isNativeCryptoEnabled()来判断是否使用Native实现测试验证机制:
engineSign()和engineVerify()方法会实时调用NativeSunEC.useNativeEdDSA()来决定使用哪种实现不过为了代码的精简,我的EdDSAInteropTest.java确实不应该添加上述部分的代码。
我只是很疑惑,你的测试程序是如何让一个java进程,既能使用纯Java实现,又能使用Native实现?
IS_NATIVE_CRYPTO_ENABLED应该只能被初始化一次。
即便多次设置了系统属性,如jdk.sunec.enableNativeCrypto,IS_NATIVE_CRYPTO_ENABLED的值也不能再被改变了。
@johnjiang(jiangsha) 老师您好,这次我采用多进程的方案进行测试,并成功进行了以下测试:

以下是该测试类的说明:
runMainProcess 负责协调整个测试流程runChildProcess 执行具体的签名或验证操作runChildProcessAndGetResult 管理子进程的创建、执行和结果收集测试覆盖两种主要的EdDSA曲线:
3.1 基础互操作测试
testNativeSignJavaVerifytestJavaSignNativeVerify3.2 参数兼容性测试
testParameterCompatibility 测试四种 EdDSAParameterSpec 参数组合:
EdDSAMultiProcessInteropTest.java的完整内容:
import java.io.*;
import java.nio.file.*;
import java.security.*;
import java.security.spec.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.*;
/**
* 多进程EdDSA互操作测试:为每种模式启动独立的JVM进程
* 解决单进程内无法切换Native和Java实现的问题
*/
public class EdDSAMultiProcessInteropTest {
private static final byte[] TEST_MESSAGE = "EdDSA Interop Test Message".getBytes(StandardCharsets.UTF_8);
private static final String TEMP_DIR = System.getProperty("java.io.tmpdir");
public static void main(String[] args) throws Exception {
if (args.length > 0) {
// 子进程模式
runChildProcess(args);
} else {
// 主进程模式
runMainProcess();
}
}
private static void runMainProcess() throws Exception {
System.out.println("=== EdDSA 多进程互操作测试 ===");
try {
// 测试Ed25519
System.out.println("\n1. 测试Ed25519互操作性:");
testCurveInteroperability("Ed25519", 255);
// 测试Ed448
System.out.println("\n2. 测试Ed448互操作性:");
testCurveInteroperability("Ed448", 448);
System.out.println("\n=== 所有多进程互操作测试通过! ===");
} catch (Exception e) {
System.err.println("多进程互操作测试失败: " + e.getMessage());
e.printStackTrace();
System.exit(1);
}
}
private static void testCurveInteroperability(String curveName, int keySize) throws Exception {
// 生成密钥对并保存到临时文件
KeyPair keyPair = generateKeyPair(keySize);
String keyPairId = saveKeyPair(keyPair);
try {
// 测试1: Native签名 -> Java验证
System.out.println(" 测试1: Native签名 -> Java验证");
testNativeSignJavaVerify(curveName, keyPairId);
// 测试2: Java签名 -> Native验证
System.out.println(" 测试2: Java签名 -> Native验证");
testJavaSignNativeVerify(curveName, keyPairId);
// 测试3: 参数兼容性测试
System.out.println(" 测试3: 参数兼容性测试");
testParameterCompatibility(curveName, keyPairId);
} finally {
// 清理临时文件
cleanupKeyPair(keyPairId);
}
}
private static void testNativeSignJavaVerify(String curveName, String keyPairId) throws Exception {
// 启动Native进程生成签名
String signatureFile = runChildProcessAndGetResult("sign", "native", keyPairId, null);
// 启动Java进程验证签名
String result = runChildProcessAndGetResult("verify", "java", keyPairId, signatureFile);
if (!"true".equals(result.trim())) {
throw new RuntimeException(curveName + " Native签名->Java验证失败");
}
System.out.println(" " + curveName + " Native签名->Java验证: 通过");
}
private static void testJavaSignNativeVerify(String curveName, String keyPairId) throws Exception {
// 启动Java进程生成签名
String signatureFile = runChildProcessAndGetResult("sign", "java", keyPairId, null);
// 启动Native进程验证签名
String result = runChildProcessAndGetResult("verify", "native", keyPairId, signatureFile);
if (!"true".equals(result.trim())) {
throw new RuntimeException(curveName + " Java签名->Native验证失败");
}
System.out.println(" " + curveName + " Java签名->Native验证: 通过");
}
private static void testParameterCompatibility(String curveName, String keyPairId) throws Exception {
// 测试不同的EdDSAParameterSpec参数组合
String[] paramSpecs = {
"prehash",
"empty-context",
"test-context",
"prehash-context"
};
for (String paramSpec : paramSpecs) {
try {
// Native签名 -> Java验证
String nativeSignature = runChildProcessAndGetResult("sign", "native", keyPairId, paramSpec);
String javaVerifyResult = runChildProcessAndGetResult("verify", "java", keyPairId, nativeSignature + "|" + paramSpec);
// Java签名 -> Native验证
String javaSignature = runChildProcessAndGetResult("sign", "java", keyPairId, paramSpec);
String nativeVerifyResult = runChildProcessAndGetResult("verify", "native", keyPairId, javaSignature + "|" + paramSpec);
boolean nativeToJava = "true".equals(javaVerifyResult.trim());
boolean javaToNative = "true".equals(nativeVerifyResult.trim());
System.out.println(" " + curveName + " " + paramSpec + " - Native->Java: " +
(nativeToJava ? "通过" : "失败") + ", Java->Native: " +
(javaToNative ? "通过" : "失败"));
if (!nativeToJava || !javaToNative) {
throw new RuntimeException(curveName + " " + paramSpec + " 参数兼容性测试失败");
}
} catch (Exception e) {
if (e.getMessage().contains("not supported") || e.getMessage().contains("Invalid")) {
System.out.println(" " + curveName + " " + paramSpec + " - 跳过(不支持的参数组合)");
} else {
throw e;
}
}
}
}
private static String runChildProcessAndGetResult(String operation, String implementation,
String keyPairId, String extraParam) throws Exception {
List<String> command = new ArrayList<>();
command.add(System.getProperty("java.home") + "/bin/java");
command.add("-cp");
command.add(System.getProperty("java.class.path"));
// 设置系统属性
if ("native".equals(implementation)) {
command.add("-Djdk.sunec.enableNativeCrypto=true");
} else {
command.add("-Djdk.sunec.enableNativeCrypto=false");
}
command.add("EdDSAMultiProcessInteropTest");
command.add(operation);
command.add(implementation);
command.add(keyPairId);
if (extraParam != null) {
command.add(extraParam);
}
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectErrorStream(true);
Process process = pb.start();
// 读取输出
StringBuilder output = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}
}
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new RuntimeException("子进程执行失败 (exit code: " + exitCode + "): " + output.toString());
}
return output.toString().trim();
}
private static void runChildProcess(String[] args) throws Exception {
String operation = args[0]; // sign 或 verify
String implementation = args[1]; // native 或 java
String keyPairId = args[2];
String extraParam = args.length > 3 ? args[3] : null;
try {
if ("sign".equals(operation)) {
String result = performSign(keyPairId, extraParam);
System.out.println(result);
} else if ("verify".equals(operation)) {
boolean result = performVerify(keyPairId, extraParam);
System.out.println(result);
}
} catch (Exception e) {
System.err.println("子进程执行异常: " + e.getMessage());
e.printStackTrace();
System.exit(1);
}
}
private static String performSign(String keyPairId, String paramSpec) throws Exception {
KeyPair keyPair = loadKeyPair(keyPairId);
Signature signature = Signature.getInstance("EdDSA");
// 设置参数
if (paramSpec != null) {
EdDSAParameterSpec spec = createParameterSpec(paramSpec);
if (spec != null) {
signature.setParameter(spec);
}
}
signature.initSign(keyPair.getPrivate(), new SecureRandom());
signature.update(TEST_MESSAGE);
byte[] signatureBytes = signature.sign();
// 保存签名到临时文件并返回文件路径
String signatureFile = TEMP_DIR + "/signature_" + System.currentTimeMillis() + "_" +
Thread.currentThread().getId() + ".dat";
Files.write(Paths.get(signatureFile), signatureBytes);
return signatureFile;
}
private static boolean performVerify(String keyPairId, String signatureInfo) throws Exception {
KeyPair keyPair = loadKeyPair(keyPairId);
// 解析签名信息
String[] parts = signatureInfo.split("\\|");
String signatureFile = parts[0];
String paramSpec = parts.length > 1 ? parts[1] : null;
byte[] signatureBytes = Files.readAllBytes(Paths.get(signatureFile));
Signature signature = Signature.getInstance("EdDSA");
// 设置参数
if (paramSpec != null) {
EdDSAParameterSpec spec = createParameterSpec(paramSpec);
if (spec != null) {
signature.setParameter(spec);
}
}
signature.initVerify(keyPair.getPublic());
signature.update(TEST_MESSAGE);
boolean result = signature.verify(signatureBytes);
// 清理签名文件
try {
Files.deleteIfExists(Paths.get(signatureFile));
} catch (Exception e) {
// 忽略清理错误
}
return result;
}
private static EdDSAParameterSpec createParameterSpec(String paramSpec) {
switch (paramSpec) {
case "prehash":
return new EdDSAParameterSpec(true);
case "empty-context":
return new EdDSAParameterSpec(false, new byte[0]);
case "test-context":
return new EdDSAParameterSpec(false, "test-context-data".getBytes(StandardCharsets.UTF_8));
case "prehash-context":
return new EdDSAParameterSpec(true, "test-context-data".getBytes(StandardCharsets.UTF_8));
default:
return null;
}
}
private static KeyPair generateKeyPair(int keySize) throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EdDSA");
kpg.initialize(keySize, new SecureRandom());
return kpg.generateKeyPair();
}
private static String saveKeyPair(KeyPair keyPair) throws Exception {
String keyPairId = "keypair_" + System.currentTimeMillis() + "_" + Thread.currentThread().getId();
// 保存私钥
String privateKeyFile = TEMP_DIR + "/" + keyPairId + "_private.key";
Files.write(Paths.get(privateKeyFile), keyPair.getPrivate().getEncoded());
// 保存公钥
String publicKeyFile = TEMP_DIR + "/" + keyPairId + "_public.key";
Files.write(Paths.get(publicKeyFile), keyPair.getPublic().getEncoded());
return keyPairId;
}
private static KeyPair loadKeyPair(String keyPairId) throws Exception {
// 加载私钥
String privateKeyFile = TEMP_DIR + "/" + keyPairId + "_private.key";
byte[] privateKeyBytes = Files.readAllBytes(Paths.get(privateKeyFile));
// 加载公钥
String publicKeyFile = TEMP_DIR + "/" + keyPairId + "_public.key";
byte[] publicKeyBytes = Files.readAllBytes(Paths.get(publicKeyFile));
// 重构密钥对
KeyFactory keyFactory = KeyFactory.getInstance("EdDSA");
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
return new KeyPair(publicKey, privateKey);
}
private static void cleanupKeyPair(String keyPairId) {
try {
Files.deleteIfExists(Paths.get(TEMP_DIR + "/" + keyPairId + "_private.key"));
Files.deleteIfExists(Paths.get(TEMP_DIR + "/" + keyPairId + "_public.key"));
} catch (Exception e) {
// 忽略清理错误
}
}
}
Native EdDSA signature
本PR用于完成该issue:#28
环境准备
我的运行环境为:Windows 11 24H2 的 WSL2(Ubuntu 24.04.2 LTS)子系统
1. 任务概述
本PR实现了基于OpenSSL的EdDSASignature的native实现,通过JNI调用OpenSSL库提供高性能的EdDSA签名和验证操作,支持Ed25519和Ed448曲线。
2. 技术实现思路
2.1 核心修改文件
Java层代码:
src/jdk.crypto.ec/share/classes/sun/security/ec/NativeSunEC.java- 添加EdDSA相关的native方法声明和支持检查src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSASignature.java- 集成native实现,参考ECDSASignature的模式JNI层代码:
src/jdk.crypto.ec/share/native/libsuneccrypto/sunec_ed.c- 新增文件,实现EdDSA的JNI native方法JTREG测试:
test/jdk/sun/security/ec/ed/NativeEdDSASignature.java- 新增文件,Native EdDSA签名验证功能测试JMH测试:
test/micro/org/openjdk/bench/javax/crypto/full/NativeEdDSASignatureBench.java- 新增文件,EdDSA性能基准测试2.2 技术实现细节
系统属性配置:
jdk.sunec.enableNativeCrypto系统属性开启Native实现jdk.openssl.cryptoLibPath指定OpenSSL libcrypto.so.3的本地绝对路径Native方法定义:
在NativeSunEC类中定义EdDSA相关的native方法,包括:
实现特性:
3. 测试结果分析
3.1 JTREG功能测试结果
测试命令
make test TEST="test/jdk/sun/security/ec/ed/NativeEdDSASignature.java"NativeEdDSASignature.java测试:

测试状态:1个测试全部通过(PASS: 1, FAIL: 0, ERROR: 0)
验证内容:
实现细节:
3.2 JMH性能测试结果
测试命令
# 测试纯Java实现 make test TEST="micro:NativeEdDSASignatureBench" MICRO="OPTIONS=-prof gc" MICRO_JAVA_OPTIONS="-Djdk.sunec.enableNativeCrypto=false" # 测试Native实现 make test TEST="micro:NativeEdDSASignatureBench" MICRO="OPTIONS=-prof gc" MICRO_JAVA_OPTIONS="-Djdk.sunec.enableNativeCrypto=true -Djdk.openssl.cryptoLibPath=/usr/local/openssl/lib64/libcrypto.so.3"测试配置:
纯Java实现:

Native实现:

3.3 性能分析总结
Ed25519曲线性能提升分析:
Ed448曲线性能提升分析:
内存分配性能特点分析:
内存分配速率对比:从基准测试数据可以看出,纯Java实现和Native实现在内存分配模式上存在显著差异。纯Java实现的内存分配速率相对较高且稳定,而Native实现在大多数场景下显示出更低的内存分配速率,体现了更高效的内存使用
Ed25519内存分配特征:
Ed448内存分配特征:
内存分配模式差异:Native实现通过优化的内存管理策略,在签名操作中显著降低了内存分配速率,特别是Ed448算法在签名操作中内存分配效率提升最为明显,从而减少了GC压力并提升了整体性能
整体评估:
4. 结论
本PR成功实现了EdDSA的OpenSSL native实现,通过系统属性提供了灵活的开关控制。功能测试验证了实现的正确性,性能测试显示了显著的性能优势:
最新修改
8.24
8.25
8.26
采用多进程的方案,使用临时的测试类进行Native与纯Java实现的互操作测试:
在昨日增加了Native实现中Ed25519曲线对prehash和context 参数的支持之后,重新运行JMH测试并修改报告的内容