SM2 版本工具

This commit is contained in:
cheney 2026-05-13 16:31:05 +08:00
parent 3779a055e0
commit fc273376a7
11 changed files with 493 additions and 84 deletions

View File

@ -6,6 +6,9 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.security.KeyPair;
import java.util.Base64;
@RestController
@RequestMapping("/device")
public class DeviceActivationController {
@ -24,8 +27,10 @@ public class DeviceActivationController {
String concatenatedParams = params.toConcatenatedString();
String calculatedHash = deviceActivationService.calculateSm3Hash(concatenatedParams);
String deviceActivationPublicKey = deviceActivationService.generateDeviceActivationPublicKey();
String deviceActivationResult = deviceActivationService.signWithSm2Pkcs1(calculatedHash, deviceActivationPublicKey);
KeyPair keyPair = deviceActivationService.generateDeviceActivationKeyPair();
String deviceActivationPublicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
String privateKeyBase64 = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
String deviceActivationResult = deviceActivationService.signWithSm2Pkcs1(calculatedHash, privateKeyBase64);
DeviceActivationResponse.Data data = new DeviceActivationResponse.Data();
data.setHash(calculatedHash);

View File

@ -63,6 +63,16 @@ public class DeviceActivationService {
}
}
public KeyPair generateDeviceActivationKeyPair() {
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC", PROVIDER);
keyGen.initialize(256);
return keyGen.generateKeyPair();
} catch (Exception e) {
throw new RuntimeException("生成设备激活密钥对失败", e);
}
}
public KeyPair generateKeyPair() {
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC", PROVIDER);

View File

@ -18,6 +18,33 @@
</properties>
<dependencies>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.9.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.9.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.42</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
@ -44,6 +71,30 @@
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.sunyard.cisd.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,9 +1,45 @@
package com.sunyard.cisd;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
public class DeviceFingerprintService {
private static final String SDF_LIBRARY_PATH = "/home/tms/libs/libsdf_syd1408-x64.so.1.0.0";
private static SdfNativeLibrary sdfLibrary = null;
private static boolean libraryLoaded = false;
private static String loadError = null;
static {
System.out.println("[DEBUG] Attempting to load SDF library from: " + SDF_LIBRARY_PATH);
File libFile = new File(SDF_LIBRARY_PATH);
if (libFile.exists()) {
System.out.println("[DEBUG] Library file exists: " + SDF_LIBRARY_PATH);
System.out.println("[DEBUG] File size: " + libFile.length() + " bytes");
} else {
System.out.println("[ERROR] Library file not found: " + SDF_LIBRARY_PATH);
loadError = "Library file not found";
}
try {
sdfLibrary = Native.load(SDF_LIBRARY_PATH, SdfNativeLibrary.class);
libraryLoaded = true;
System.out.println("[DEBUG] SDF library loaded successfully");
} catch (UnsatisfiedLinkError e) {
loadError = "UnsatisfiedLinkError: " + e.getMessage();
System.err.println("[ERROR] Failed to load SDF library (UnsatisfiedLinkError): " + e.getMessage());
System.err.println("[ERROR] Cause: " + (e.getCause() != null ? e.getCause().getMessage() : "null"));
} catch (Exception e) {
loadError = "Exception: " + e.getMessage();
System.err.println("[ERROR] Failed to load SDF library (Exception): " + e.getClass().getName() + " - " + e.getMessage());
e.printStackTrace();
}
}
public DeviceFingerprint getDeviceFingerprint() {
DeviceFingerprint fingerprint = new DeviceFingerprint();
@ -43,65 +79,148 @@ public class DeviceFingerprintService {
return result != null && !result.isEmpty() ? result : "Unknown";
}
private static String zeroTerminatedString(byte[] value) {
int len = 0;
while (len < value.length && value[len] != 0) {
len++;
}
return new String(value, 0, len, StandardCharsets.UTF_8).trim();
}
private String getDeviceSerialNumber() {
if (!SDFNative.isLibraryLoaded()) {
System.out.println("[DEBUG] getDeviceSerialNumber() called");
System.out.println("[DEBUG] Library loaded: " + libraryLoaded + ", sdfLibrary: " + (sdfLibrary != null ? "not null" : "null"));
if (!libraryLoaded || sdfLibrary == null) {
System.err.println("[ERROR] SDF library not loaded. Cannot get device serial number.");
System.err.println("[ERROR] Load error: " + loadError);
return "Unknown";
}
int hDevice = -1;
int hSession = -1;
Pointer deviceHandle = null;
Pointer sessionHandle = null;
try {
byte[] deviceName = new byte[256];
int[] deviceNameLen = new int[]{256};
int ret = SDFNative.SDF_OpenDevice(0, deviceName, deviceNameLen);
System.out.println("[DEBUG] Calling SDF_OpenDevice...");
PointerByReference phDeviceHandle = new PointerByReference();
int ret = sdfLibrary.SDF_OpenDevice(phDeviceHandle);
System.out.println("[DEBUG] SDF_OpenDevice returned: " + ret);
if (ret != 0) {
System.err.println("SDF_OpenDevice failed with error: " + ret);
System.err.println("[ERROR] SDF_OpenDevice failed with error code: " + ret);
System.err.println("[ERROR] Error code meaning: " + getErrorMessage(ret));
return "Unknown";
}
hDevice = ret;
deviceHandle = phDeviceHandle.getValue();
System.out.println("[DEBUG] Device handle obtained: " + deviceHandle);
byte[] appID = "DeviceFingerprint".getBytes();
int[] sessionHandle = new int[1];
ret = SDFNative.SDF_OpenSession(hDevice, 0, appID, appID.length, sessionHandle);
System.out.println("[DEBUG] Calling SDF_OpenSession...");
PointerByReference phSessionHandle = new PointerByReference();
ret = sdfLibrary.SDF_OpenSession(deviceHandle, phSessionHandle);
System.out.println("[DEBUG] SDF_OpenSession returned: " + ret);
if (ret != 0) {
System.err.println("SDF_OpenSession failed with error: " + ret);
System.err.println("[ERROR] SDF_OpenSession failed with error code: " + ret);
System.err.println("[ERROR] Error code meaning: " + getErrorMessage(ret));
return "Unknown";
}
hSession = sessionHandle[0];
sessionHandle = phSessionHandle.getValue();
System.out.println("[DEBUG] Session handle obtained: " + sessionHandle);
System.out.println("[DEBUG] Calling SDF_GetDeviceInfo...");
SdfDeviceInfo info = new SdfDeviceInfo();
ret = SDFNative.SDF_GetDeviceInfo(hSession, info);
ret = sdfLibrary.SDF_GetDeviceInfo(sessionHandle, info);
System.out.println("[DEBUG] SDF_GetDeviceInfo returned: " + ret);
if (ret != 0) {
System.err.println("SDF_GetDeviceInfo failed with error: " + ret);
System.err.println("[ERROR] SDF_GetDeviceInfo failed with error code: " + ret);
System.err.println("[ERROR] Error code meaning: " + getErrorMessage(ret));
return "Unknown";
}
info.read();
String deviceSerial = info.getDeviceSerial();
return deviceSerial.isEmpty() ? "Unknown" : deviceSerial;
String issuerName = zeroTerminatedString(info.getIssuerName());
String deviceName = zeroTerminatedString(info.getDeviceName());
String deviceSerial = zeroTerminatedString(info.getDeviceSerial());
System.out.println("[DEBUG] Device info retrieved:");
System.out.println("[DEBUG] IssuerName: '" + issuerName + "'");
System.out.println("[DEBUG] DeviceName: '" + deviceName + "'");
System.out.println("[DEBUG] DeviceSerial: '" + deviceSerial + "'");
} catch (UnsatisfiedLinkError | Exception e) {
System.err.println("Failed to get device serial number from SDF: " + e.getMessage());
if (deviceSerial == null || deviceSerial.isEmpty()) {
System.err.println("[WARNING] Device serial number is empty");
return "Unknown";
}
return deviceSerial;
} catch (UnsatisfiedLinkError e) {
System.err.println("[ERROR] UnsatisfiedLinkError when calling SDF API: " + e.getMessage());
e.printStackTrace();
return "Unknown";
} catch (Exception e) {
System.err.println("[ERROR] Exception when calling SDF API: " + e.getClass().getName() + " - " + e.getMessage());
e.printStackTrace();
return "Unknown";
} finally {
if (hSession != -1) {
if (sessionHandle != null) {
try {
SDFNative.SDF_CloseSession(hSession);
System.out.println("[DEBUG] Closing session handle: " + sessionHandle);
sdfLibrary.SDF_CloseSession(sessionHandle);
} catch (Exception e) {
System.err.println("Error closing session: " + e.getMessage());
System.err.println("[ERROR] Error closing session: " + e.getMessage());
}
}
if (hDevice != -1) {
if (deviceHandle != null) {
try {
SDFNative.SDF_CloseDevice(hDevice);
System.out.println("[DEBUG] Closing device handle: " + deviceHandle);
sdfLibrary.SDF_CloseDevice(deviceHandle);
} catch (Exception e) {
System.err.println("Error closing device: " + e.getMessage());
System.err.println("[ERROR] Error closing device: " + e.getMessage());
}
}
}
}
private String getErrorMessage(int errorCode) {
switch (errorCode) {
case 0:
return "Success";
case -1:
return "General error";
case -2:
return "Invalid parameter";
case -3:
return "Memory allocation failed";
case -4:
return "Device not found";
case -5:
return "Device not opened";
case -6:
return "Session not opened";
case -7:
return "Operation not supported";
case -8:
return "Key not found";
case -9:
return "Key access denied";
case -10:
return "Invalid key";
case -11:
return "Invalid signature";
case -12:
return "Invalid certificate";
case -13:
return "Buffer too small";
case -14:
return "Timeout";
case -15:
return "Hardware error";
default:
return "Unknown error code: " + errorCode;
}
}
private String executeCommand(String command) {
try {
Process process = Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", command});
@ -124,11 +243,11 @@ public class DeviceFingerprintService {
String result = output.toString().trim();
return result.isEmpty() ? "Unknown" : result;
} else {
System.err.println("Command '" + command + "' failed with exit code " + exitCode + ": " + errorOutput);
System.err.println("[ERROR] Command '" + command + "' failed with exit code " + exitCode + ": " + errorOutput);
return "Unknown";
}
} catch (Exception e) {
System.err.println("Error executing command '" + command + "': " + e.getMessage());
System.err.println("[ERROR] Error executing command '" + command + "': " + e.getMessage());
return "Unknown";
}
}

View File

@ -1,25 +0,0 @@
package com.sunyard.cisd;
public class SDFNative {
private static final String SDF_LIBRARY_PATH = "/home/tms/libs/libsdf_syd1408-x64.so.1.0.0";
private static boolean libraryLoaded = false;
static {
try {
System.load(SDF_LIBRARY_PATH);
libraryLoaded = true;
} catch (UnsatisfiedLinkError e) {
System.err.println("Warning: SDF library not loaded: " + e.getMessage());
}
}
public static boolean isLibraryLoaded() {
return libraryLoaded;
}
public static native int SDF_OpenDevice(int dwDeviceType, byte[] pDeviceName, int[] pdwDeviceNameLen);
public static native int SDF_CloseDevice(int hDevice);
public static native int SDF_OpenSession(int hDevice, int dwAppType, byte[] pAppID, int dwAppIDLen, int[] phSession);
public static native int SDF_CloseSession(int hSession);
public static native int SDF_GetDeviceInfo(int hSession, SdfDeviceInfo pDeviceInfo);
}

View File

@ -0,0 +1,156 @@
package com.sunyard.cisd;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.BigIntegers;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class SM2Util {
private static final String ALGORITHM = "EC";
private static final String PROVIDER = "BC";
private static final String CURVE_NAME = "sm2p256v1";
private static final String SIGNATURE_ALGORITHM = "SM3withSM2";
static {
Security.addProvider(new BouncyCastleProvider());
}
public static byte[] sign(byte[] data, PrivateKey privateKey) throws Exception {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM, PROVIDER);
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
}
public static boolean verify(byte[] data, byte[] sign, PublicKey publicKey) throws Exception {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM, PROVIDER);
signature.initVerify(publicKey);
signature.update(data);
return signature.verify(sign);
}
public static byte[] sign(byte[] data, String privateKeyFilePath) throws Exception {
PrivateKey privateKey = loadPrivateKey(privateKeyFilePath);
return sign(data, privateKey);
}
public static boolean verify(byte[] data, byte[] sign, String publicKeyFilePath) throws Exception {
PublicKey publicKey = loadPublicKey(publicKeyFilePath);
return verify(data, sign, publicKey);
}
public static PrivateKey loadPrivateKey(String filePath) throws Exception {
InputStream inputStream = SM2Util.class.getResourceAsStream(filePath);
if (inputStream == null) {
throw new IllegalArgumentException("Private key file not found: " + filePath);
}
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
StringBuilder keyBuilder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
if (!line.startsWith("-----")) {
keyBuilder.append(line.trim());
}
}
reader.close();
String keyBase64 = keyBuilder.toString();
byte[] keyBytes = Base64.getDecoder().decode(keyBase64);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM, PROVIDER);
return keyFactory.generatePrivate(keySpec);
}
public static PublicKey loadPublicKey(String filePath) throws Exception {
InputStream inputStream = SM2Util.class.getResourceAsStream(filePath);
if (inputStream == null) {
throw new IllegalArgumentException("Public key file not found: " + filePath);
}
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
StringBuilder keyBuilder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
if (!line.startsWith("-----")) {
keyBuilder.append(line.trim());
}
}
reader.close();
String keyBase64 = keyBuilder.toString();
byte[] keyBytes = Base64.getDecoder().decode(keyBase64);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM, PROVIDER);
return keyFactory.generatePublic(keySpec);
}
public static KeyPair generateKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM, PROVIDER);
ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(CURVE_NAME);
keyPairGenerator.initialize(ecSpec, new SecureRandom());
return keyPairGenerator.generateKeyPair();
}
public static String privateKeyToPEM(PrivateKey privateKey) {
byte[] encoded = privateKey.getEncoded();
String base64 = Base64.getEncoder().encodeToString(encoded);
StringBuilder pem = new StringBuilder();
pem.append("-----BEGIN PRIVATE KEY-----\n");
int index = 0;
while (index < base64.length()) {
pem.append(base64.substring(index, Math.min(index + 64, base64.length())));
pem.append("\n");
index += 64;
}
pem.append("-----END PRIVATE KEY-----\n");
return pem.toString();
}
public static String publicKeyToPEM(PublicKey publicKey) {
byte[] encoded = publicKey.getEncoded();
String base64 = Base64.getEncoder().encodeToString(encoded);
StringBuilder pem = new StringBuilder();
pem.append("-----BEGIN PUBLIC KEY-----\n");
int index = 0;
while (index < base64.length()) {
pem.append(base64.substring(index, Math.min(index + 64, base64.length())));
pem.append("\n");
index += 64;
}
pem.append("-----END PUBLIC KEY-----\n");
return pem.toString();
}
}

View File

@ -1,41 +1,36 @@
package com.sunyard.cisd;
import java.nio.ByteBuffer;
import com.sun.jna.Structure;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
@Data
@Structure.FieldOrder({
"issuerName",
"deviceName",
"deviceSerial",
"deviceVersion",
"standardVersion",
"asymAlgAbility",
"symAlgAbility",
"hashAlgAbility",
"bufferSize"
})
public class SdfDeviceInfo extends Structure {
public class SdfDeviceInfo {
public byte[] issuerName = new byte[40];
public byte[] deviceName = new byte[40];
public byte[] deviceSerial = new byte[40];
public byte[] deviceName = new byte[16];
public byte[] deviceSerial = new byte[16];
public int deviceVersion;
public int standardVersion;
public int asymAlgAbility[] = new int[2];
public int[] asymAlgAbility = new int[2];
public int symAlgAbility;
public int hashAlgAbility;
public int bufferSize;
public void read() {
}
public String getIssuerName() {
return zeroTerminatedString(issuerName);
}
public String getDeviceName() {
return zeroTerminatedString(deviceName);
}
public String getDeviceSerial() {
return zeroTerminatedString(deviceSerial);
}
private String zeroTerminatedString(byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return "";
}
int len = 0;
while (len < bytes.length && bytes[len] != 0) {
len++;
}
return new String(bytes, 0, len).trim();
public SdfDeviceInfo() {
super(ALIGN_NONE);
}
}

View File

@ -0,0 +1,13 @@
package com.sunyard.cisd;
import com.sun.jna.Library;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;
public interface SdfNativeLibrary extends Library {
int SDF_OpenDevice(PointerByReference phDeviceHandle);
int SDF_CloseDevice(Pointer hDeviceHandle);
int SDF_OpenSession(Pointer hDeviceHandle, PointerByReference phSessionHandle);
int SDF_CloseSession(Pointer hSessionHandle);
int SDF_GetDeviceInfo(Pointer hSessionHandle, SdfDeviceInfo deviceInfo);
}

View File

@ -0,0 +1,6 @@
-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg7isDlcvx8WmYYw/6
Xc25GcgDx3N19Czq6O2tz2v5Jx+gCgYIKoEcz1UBgi2hRANCAATJMA+gouZuIttR
bqpDk/tjk4jefTgG1ncg7xuVoTVz10hFja5bbTssru4oD4Pooxz4VbTR1KIylDYo
bLe3PyUJ
-----END PRIVATE KEY-----

View File

@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEyTAPoKLmbiLbUW6qQ5P7Y5OI3n04
BtZ3IO8blaE1c9dIRY2uW207LK7uKA+D6KMc+FW00dSiMpQ2KGy3tz8lCQ==
-----END PUBLIC KEY-----

View File

@ -0,0 +1,75 @@
package com.sunyard.cisd;
import org.junit.Test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
public class SM2UtilTest {
@Test
public void testGenerateAndSaveKeyPair() throws Exception {
KeyPair keyPair = SM2Util.generateKeyPair();
String privateKeyPEM = SM2Util.privateKeyToPEM(keyPair.getPrivate());
String publicKeyPEM = SM2Util.publicKeyToPEM(keyPair.getPublic());
String resourcesPath = "src/main/resources";
File resourcesDir = new File(resourcesPath);
if (!resourcesDir.exists()) {
resourcesDir.mkdirs();
}
File privateKeyFile = new File(resourcesPath + "/sm2_private_key.pem");
try (Writer writer = new OutputStreamWriter(new FileOutputStream(privateKeyFile), StandardCharsets.UTF_8)) {
writer.write(privateKeyPEM);
}
System.out.println("Private key saved to: " + privateKeyFile.getAbsolutePath());
File publicKeyFile = new File(resourcesPath + "/sm2_public_key.pem");
try (Writer writer = new OutputStreamWriter(new FileOutputStream(publicKeyFile), StandardCharsets.UTF_8)) {
writer.write(publicKeyPEM);
}
System.out.println("Public key saved to: " + publicKeyFile.getAbsolutePath());
System.out.println("\nGenerated Key Pair:");
System.out.println("Private Key:\n" + privateKeyPEM);
System.out.println("Public Key:\n" + publicKeyPEM);
}
@Test
public void testSignAndVerify() throws Exception {
KeyPair keyPair = SM2Util.generateKeyPair();
String testData = "Hello, SM2!";
byte[] data = testData.getBytes(StandardCharsets.UTF_8);
byte[] signature = SM2Util.sign(data, keyPair.getPrivate());
System.out.println("Signature generated, length: " + signature.length + " bytes");
boolean verified = SM2Util.verify(data, signature, keyPair.getPublic());
System.out.println("Signature verified: " + verified);
assert verified : "Signature verification failed";
}
@Test
public void testSignAndVerifyWithKeyFiles() throws Exception {
testGenerateAndSaveKeyPair();
String testData = "Test data for SM2 signature";
byte[] data = testData.getBytes(StandardCharsets.UTF_8);
byte[] signature = SM2Util.sign(data, "/sm2_private_key.pem");
System.out.println("Signature generated from file, length: " + signature.length + " bytes");
boolean verified = SM2Util.verify(data, signature, "/sm2_public_key.pem");
System.out.println("Signature verified from file: " + verified);
assert verified : "Signature verification with key files failed";
}
}