diff --git a/jmeter/招行测试计划.jmx b/jmeter/招行测试计划.jmx
index 0a261aa..2a5b3ff 100644
--- a/jmeter/招行测试计划.jmx
+++ b/jmeter/招行测试计划.jmx
@@ -9,6 +9,7 @@
+
@@ -243,7 +244,7 @@
-
+
continue
false
@@ -475,11 +476,11 @@
-
+
continue
false
- 10
+ 10000
1
1
@@ -542,7 +543,7 @@
cmbpoc.JmeterTest
-
+
false
saveConfig
@@ -579,7 +580,7 @@
-
+
false
saveConfig
@@ -653,7 +654,7 @@
-
+
false
saveConfig
@@ -698,7 +699,545 @@
false
-
+
+ false
+
+ saveConfig
+
+
+ true
+ true
+ true
+
+ true
+ true
+ true
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+ 1000
+ false
+
+
+
+
+ false
+ false
+
+
+
+
+ continue
+
+ false
+ 100
+
+ 1
+ 1
+ false
+
+
+ true
+
+
+
+
+
+
+ function
+ SYD_SM2_Encrypt
+ =
+
+
+ sleep
+ 1
+ =
+
+
+ plainDataLen
+ 2097152
+ =
+
+
+ publicKey4Ende
+ 03420004AF3D4E55D26564C6C937E6EA9232691C01AC5E7916AD2136F788CE7C1E4D0AE8C4754DEC2F7F6A78962D51A171A6F5B4F11823390AEC8B5B0246CD2CCF8052B7
+ =
+
+
+ privateKey4Ende
+ 00010000963F7C3A98B7810F52D2861A060E18A9D4D59796CF33967DD61EEDA091E1AD9B0000000000000000000000000000000000000000000000000000000000000000
+ =
+
+
+ ip
+ 192.168.100.145
+ =
+
+
+ ip2
+ 172.1.41.96
+ =
+
+
+ port
+ 8889
+ =
+
+
+ timeout
+ 3000
+ =
+
+
+
+ cmbpoc.JmeterTest
+
+
+
+ false
+
+ saveConfig
+
+
+ true
+ true
+ true
+
+ true
+ true
+ true
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+
+
+
+ false
+
+ saveConfig
+
+
+ true
+ true
+ true
+
+ true
+ true
+ true
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+
+
+
+ false
+
+ saveConfig
+
+
+ true
+ true
+ true
+
+ true
+ true
+ true
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+
+
+
+ false
+
+ saveConfig
+
+
+ true
+ true
+ true
+
+ true
+ true
+ true
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+ 500
+ false
+
+
+
+
+ false
+ false
+
+
+
+ false
+
+ saveConfig
+
+
+ true
+ true
+ true
+
+ true
+ true
+ true
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+ 1000
+ false
+
+
+
+
+ false
+ false
+
+
+
+
+ continue
+
+ false
+ 100
+
+ 1
+ 1
+ false
+
+
+ true
+
+
+
+
+
+
+ function
+ SYD_SM2_Encrypt
+ =
+
+
+ sleep
+ 1
+ =
+
+
+ plainDataLen
+ 2048
+ =
+
+
+ publicKey4Ende
+ 03420004AF3D4E55D26564C6C937E6EA9232691C01AC5E7916AD2136F788CE7C1E4D0AE8C4754DEC2F7F6A78962D51A171A6F5B4F11823390AEC8B5B0246CD2CCF8052B7
+ =
+
+
+ privateKey4Ende
+ 00010000963F7C3A98B7810F52D2861A060E18A9D4D59796CF33967DD61EEDA091E1AD9B0000000000000000000000000000000000000000000000000000000000000000
+ =
+
+
+ ip
+ 192.168.100.145
+ =
+
+
+ ip2
+ 172.1.41.96
+ =
+
+
+ port
+ 8889
+ =
+
+
+ timeout
+ 3000
+ =
+
+
+
+ cmbpoc.JmeterTest
+
+
+
+ false
+
+ saveConfig
+
+
+ true
+ true
+ true
+
+ true
+ true
+ true
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+
+
+
+ false
+
+ saveConfig
+
+
+ true
+ true
+ true
+
+ true
+ true
+ true
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+
+
+
+ false
+
+ saveConfig
+
+
+ true
+ true
+ true
+
+ true
+ true
+ true
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+
+
+
+ false
+
+ saveConfig
+
+
+ true
+ true
+ true
+
+ true
+ true
+ true
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+ 500
+ false
+
+
+
+
+ false
+ false
+
+
+
false
saveConfig
diff --git a/src/main/java/com/sunyard/entity/TimeStats.java b/src/main/java/com/sunyard/entity/TimeStats.java
new file mode 100644
index 0000000..ce53ed1
--- /dev/null
+++ b/src/main/java/com/sunyard/entity/TimeStats.java
@@ -0,0 +1,103 @@
+package com.sunyard.entity;
+
+/**
+ * SM2加密解密时间统计类
+ * 用于记录发送、计算、接收三个阶段的耗时
+ */
+public class TimeStats {
+ // 发送阶段总耗时(毫秒)- 循环发送数据块的时间
+ private long sendTime;
+ // 计算阶段耗时(毫秒)- 执行加密/解密计算的时间
+ private long computeTime;
+ // 接收阶段总耗时(毫秒)- 循环接收数据块的时间
+ private long receiveTime;
+ // 发送次数
+ private int sendCount;
+ // 接收次数
+ private int receiveCount;
+
+ public TimeStats() {
+ this.sendTime = 0;
+ this.computeTime = 0;
+ this.receiveTime = 0;
+ this.sendCount = 0;
+ this.receiveCount = 0;
+ }
+
+ public long getSendTime() {
+ return sendTime;
+ }
+
+ public void setSendTime(long sendTime) {
+ this.sendTime = sendTime;
+ }
+
+ public long getComputeTime() {
+ return computeTime;
+ }
+
+ public void setComputeTime(long computeTime) {
+ this.computeTime = computeTime;
+ }
+
+ public long getReceiveTime() {
+ return receiveTime;
+ }
+
+ public void setReceiveTime(long receiveTime) {
+ this.receiveTime = receiveTime;
+ }
+
+ public int getSendCount() {
+ return sendCount;
+ }
+
+ public void setSendCount(int sendCount) {
+ this.sendCount = sendCount;
+ }
+
+ public int getReceiveCount() {
+ return receiveCount;
+ }
+
+ public void setReceiveCount(int receiveCount) {
+ this.receiveCount = receiveCount;
+ }
+
+ /**
+ * 获取总耗时
+ */
+ public long getTotalTime() {
+ return sendTime + computeTime + receiveTime;
+ }
+
+ /**
+ * 获取各阶段耗时占比
+ */
+ public double getSendPercentage() {
+ long total = getTotalTime();
+ return total == 0 ? 0 : (double) sendTime / total * 100;
+ }
+
+ public double getComputePercentage() {
+ long total = getTotalTime();
+ return total == 0 ? 0 : (double) computeTime / total * 100;
+ }
+
+ public double getReceivePercentage() {
+ long total = getTotalTime();
+ return total == 0 ? 0 : (double) receiveTime / total * 100;
+ }
+
+ @Override
+ public String toString() {
+ return String.format(
+ "TimeStats{sendTime=%dms(%.1f%%), computeTime=%dms(%.1f%%), receiveTime=%dms(%.1f%%), total=%dms, sendCount=%d, receiveCount=%d}",
+ sendTime, getSendPercentage(),
+ computeTime, getComputePercentage(),
+ receiveTime, getReceivePercentage(),
+ getTotalTime(),
+ sendCount, receiveCount
+ );
+ }
+}
diff --git a/src/main/java/racal/sunyard/main/SydApi4j.java b/src/main/java/racal/sunyard/main/SydApi4j.java
index 6ba343f..7cc4334 100644
--- a/src/main/java/racal/sunyard/main/SydApi4j.java
+++ b/src/main/java/racal/sunyard/main/SydApi4j.java
@@ -16,6 +16,7 @@ import com.sunyard.constant.CertUsage;
import com.sunyard.entity.ImportResult;
import com.sunyard.entity.MutiReturn7;
import com.sunyard.entity.Struct;
+import com.sunyard.entity.TimeStats;
import com.sunyard.log.ILogFactory;
import com.sunyard.log.ILogger;
import com.sunyard.proto.Packet;
@@ -7170,6 +7171,149 @@ public class SydApi4j implements SydApi {
}
}
+ /**
+ * SM2 加密(支持大包分段)- 带时间统计
+ * @param publicKey 公钥字节数组
+ * @param pOrgData 明文数据
+ * @param timeStats 时间统计对象(输出参数)
+ * @return 加密后的密文
+ */
+ public byte[] SYD_SM2Encrypt(byte[] publicKey, byte[] pOrgData, TimeStats timeStats){
+ ParamChecker.checkNotNull(publicKey, "publicKey");
+ ParamChecker.checkNotNull(pOrgData, "pOrgData");
+
+ final int CHUNK_SIZE = 62 * 1024; // 62 KB
+ int dataLen = pOrgData.length;
+ int offset = 0;
+ long sendStartTime = System.currentTimeMillis();
+ int sendCount = 0;
+
+ while (offset < dataLen) {
+ int len = Math.min(CHUNK_SIZE, dataLen - offset);
+ SYD_SM2Encrypt(1, publicKey, ByteBuffer.wrap(pOrgData, offset, len), offset, len, dataLen);
+ offset += len;
+ sendCount++;
+ }
+ long sendEndTime = System.currentTimeMillis();
+
+ long computeStartTime = System.currentTimeMillis();
+ SYD_SM2Encrypt(2, publicKey, null, 0, 0, dataLen);
+ long computeEndTime = System.currentTimeMillis();
+
+ long receiveStartTime = System.currentTimeMillis();
+ int idx = 0;
+ List chunks = new ArrayList<>();
+ int totalLen = 0;
+ int isLast = 0;
+ int receiveCount = 0;
+
+ while (isLast != 1) {
+ MutiReturn7 ret = SYD_SM2Encrypt(3, null, null, idx, 0, 0);
+ ByteBuffer bb = ret.getData();
+ isLast = ret.getIsLast();
+
+ if (bb != null && bb.remaining() > 0) {
+ int remaining = bb.remaining();
+ chunks.add(bb);
+ totalLen += remaining;
+ idx += remaining;
+ receiveCount++;
+ } else if (isLast != 1) {
+ throw new RuntimeException("Empty chunk with isLast=0");
+ }
+ }
+ long receiveEndTime = System.currentTimeMillis();
+
+ byte[] result = new byte[totalLen];
+ int offset2 = 0;
+ for (ByteBuffer chunk : chunks) {
+ int len = chunk.remaining();
+ chunk.get(result, offset2, len);
+ offset2 += len;
+ }
+
+ if (timeStats != null) {
+ timeStats.setSendTime(sendEndTime - sendStartTime);
+ timeStats.setComputeTime(computeEndTime - computeStartTime);
+ timeStats.setReceiveTime(receiveEndTime - receiveStartTime);
+ timeStats.setSendCount(sendCount);
+ timeStats.setReceiveCount(receiveCount);
+ }
+
+ return result;
+ }
+
+ /**
+ * SM2 解密(支持大包分段)- 带时间统计
+ * @param privateKey 私钥字节数组
+ * @param pCipherData 密文数据
+ * @param timeStats 时间统计对象(输出参数)
+ * @return 解密后的明文
+ */
+ public byte[] SYD_SM2Decrypt(byte[] privateKey, byte[] pCipherData, TimeStats timeStats) {
+ ParamChecker.checkNotNull(privateKey, "privateKey");
+ ParamChecker.checkNotNull(pCipherData, "pCipherData");
+
+ final int CHUNK_SIZE = 62 * 1024; // 62 KB,与加密保持一致
+ int dataLen = pCipherData.length;
+ int offset = 0;
+ long sendStartTime = System.currentTimeMillis();
+ int sendCount = 0;
+
+ while (offset < dataLen) {
+ int len = Math.min(CHUNK_SIZE, dataLen - offset);
+ SYD_SM2Decrypt(1, privateKey, ByteBuffer.wrap(pCipherData, offset, len), offset, len, 0);
+ offset += len;
+ sendCount++;
+ }
+ long sendEndTime = System.currentTimeMillis();
+
+ long computeStartTime = System.currentTimeMillis();
+ SYD_SM2Decrypt(2, privateKey, null, 0, 0, dataLen);
+ long computeEndTime = System.currentTimeMillis();
+
+ long receiveStartTime = System.currentTimeMillis();
+ int idx = 0;
+ List chunks = new ArrayList<>();
+ int totalLen = 0;
+ int isLast = 0;
+ int receiveCount = 0;
+
+ while (isLast != 1) {
+ MutiReturn7 ret = SYD_SM2Decrypt(3, null, null, idx, 0, 0);
+ ByteBuffer bb = ret.getData();
+ isLast = ret.getIsLast();
+
+ if (bb != null && bb.remaining() > 0) {
+ chunks.add(bb);
+ totalLen += bb.remaining();
+ idx += bb.remaining();
+ receiveCount++;
+ } else if (isLast != 1) {
+ throw new RuntimeException("Empty plain chunk with isLast=0");
+ }
+ }
+ long receiveEndTime = System.currentTimeMillis();
+
+ byte[] result = new byte[totalLen];
+ int offset2 = 0;
+ for (ByteBuffer chunk : chunks) {
+ int len = chunk.remaining();
+ chunk.get(result, offset2, len);
+ offset2 += len;
+ }
+
+ if (timeStats != null) {
+ timeStats.setSendTime(sendEndTime - sendStartTime);
+ timeStats.setComputeTime(computeEndTime - computeStartTime);
+ timeStats.setReceiveTime(receiveEndTime - receiveStartTime);
+ timeStats.setSendCount(sendCount);
+ timeStats.setReceiveCount(receiveCount);
+ }
+
+ return result;
+ }
+
@Override
public String SM2Encrypt(byte[] publicKey, byte[] pOrgData) {
diff --git a/src/test/java/cmbpoc/PerformanceTest.java b/src/test/java/cmbpoc/PerformanceTest.java
index 435beb4..ee2eaec 100644
--- a/src/test/java/cmbpoc/PerformanceTest.java
+++ b/src/test/java/cmbpoc/PerformanceTest.java
@@ -2,6 +2,7 @@ package cmbpoc;
import com.sunyard.RetWrap;
import com.sunyard.SydApi;
+import com.sunyard.entity.TimeStats;
import com.sunyard.proto.Util;
import org.junit.*;
import racal.sunyard.main.SydApi4j;
@@ -136,4 +137,48 @@ public class PerformanceTest {
System.out.printf("Decrypt Throughput: %.2f KB/s%n", decryptThroughput);
System.out.println();
}
+
+ @Test
+ public void SYD_SM2_Encrypt_TimeStats_2M() {
+ System.out.println("=== SYD_SM2_Encrypt Time Statistics Test - 2M Data ===");
+
+ // 预热
+ for (int i = 0; i < 2; i++) {
+ byte[] enData = this.api.SYD_SM2Encrypt(publicKey4Ende, orgData2M);
+ byte[] deData = this.api.SYD_SM2Decrypt(privateKey4Ende, enData);
+ }
+
+ // 正式测试
+ TimeStats encryptStats = new TimeStats();
+ TimeStats decryptStats = new TimeStats();
+
+ byte[] enData = this.api.SYD_SM2Encrypt(publicKey4Ende, orgData2M, encryptStats);
+ byte[] deData = this.api.SYD_SM2Decrypt(privateKey4Ende, enData, decryptStats);
+
+ Assert.assertArrayEquals(orgData2M, deData);
+
+ System.out.println("\n--- 加密阶段时间统计 ---");
+ System.out.printf("发送阶段: %d ms (%.1f%%), 发送次数: %d%n",
+ encryptStats.getSendTime(), encryptStats.getSendPercentage(), encryptStats.getSendCount());
+ System.out.printf("计算阶段: %d ms (%.1f%%)%n",
+ encryptStats.getComputeTime(), encryptStats.getComputePercentage());
+ System.out.printf("接收阶段: %d ms (%.1f%%), 接收次数: %d%n",
+ encryptStats.getReceiveTime(), encryptStats.getReceivePercentage(), encryptStats.getReceiveCount());
+ System.out.printf("加密总耗时: %d ms%n", encryptStats.getTotalTime());
+
+ System.out.println("\n--- 解密阶段时间统计 ---");
+ System.out.printf("发送阶段: %d ms (%.1f%%), 发送次数: %d%n",
+ decryptStats.getSendTime(), decryptStats.getSendPercentage(), decryptStats.getSendCount());
+ System.out.printf("计算阶段: %d ms (%.1f%%)%n",
+ decryptStats.getComputeTime(), decryptStats.getComputePercentage());
+ System.out.printf("接收阶段: %d ms (%.1f%%), 接收次数: %d%n",
+ decryptStats.getReceiveTime(), decryptStats.getReceivePercentage(), decryptStats.getReceiveCount());
+ System.out.printf("解密总耗时: %d ms%n", decryptStats.getTotalTime());
+
+ System.out.println("\n--- 汇总 ---");
+ long totalTime = encryptStats.getTotalTime() + decryptStats.getTotalTime();
+ System.out.printf("加密解密总耗时: %d ms%n", totalTime);
+ System.out.printf("加密吞吐量: %.2f KB/s%n", (2048.0 / encryptStats.getTotalTime()) * 1000);
+ System.out.printf("解密吞吐量: %.2f KB/s%n", (2048.0 / decryptStats.getTotalTime()) * 1000);
+ }
}