验签通过
This commit is contained in:
parent
aa538ee1d7
commit
e15ccf5973
43
qodana.yaml
Normal file
43
qodana.yaml
Normal file
@ -0,0 +1,43 @@
|
||||
#-------------------------------------------------------------------------------#
|
||||
# Qodana analysis is configured by qodana.yaml file #
|
||||
# https://www.jetbrains.com/help/qodana/qodana-yaml.html #
|
||||
#-------------------------------------------------------------------------------#
|
||||
version: "1.0"
|
||||
|
||||
#Specify inspection profile for code analysis
|
||||
profile:
|
||||
name: qodana.starter
|
||||
|
||||
#Enable inspections
|
||||
#include:
|
||||
# - name: <SomeEnabledInspectionId>
|
||||
|
||||
#Disable inspections
|
||||
#exclude:
|
||||
# - name: <SomeDisabledInspectionId>
|
||||
# paths:
|
||||
# - <path/where/not/run/inspection>
|
||||
|
||||
projectJDK: "17" #(Applied in CI/CD pipeline)
|
||||
|
||||
#Execute shell command before Qodana execution (Applied in CI/CD pipeline)
|
||||
#bootstrap: sh ./prepare-qodana.sh
|
||||
|
||||
#Install IDE plugins before Qodana execution (Applied in CI/CD pipeline)
|
||||
#plugins:
|
||||
# - id: <plugin.id> #(plugin id can be found at https://plugins.jetbrains.com)
|
||||
|
||||
# Quality gate. Will fail the CI/CD pipeline if any condition is not met
|
||||
# severityThresholds - configures maximum thresholds for different problem severities
|
||||
# testCoverageThresholds - configures minimum code coverage on a whole project and newly added code
|
||||
# Code Coverage is available in Ultimate and Ultimate Plus plans
|
||||
#failureConditions:
|
||||
# severityThresholds:
|
||||
# any: 15
|
||||
# critical: 5
|
||||
# testCoverageThresholds:
|
||||
# fresh: 70
|
||||
# total: 50
|
||||
|
||||
#Specify Qodana linter for analysis (Applied in CI/CD pipeline)
|
||||
linter: jetbrains/qodana-jvm:2025.2
|
||||
@ -33,7 +33,7 @@ public class EccRefPublicKey extends Structure {
|
||||
}
|
||||
|
||||
private static byte[] toBytes(Structure structure) {
|
||||
structure.read();
|
||||
structure.write();
|
||||
return structure.getPointer().getByteArray(0, structure.size());
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
package com.cisd.tms.integration.crypto.pcie.model;
|
||||
|
||||
/**
|
||||
* ExternalSm2VerifyRequest
|
||||
* 外部 SM2 验签请求参数
|
||||
* 包含数据的 SM3 哈希处理(带公钥)和验签逻辑
|
||||
*/
|
||||
public class ExternalSm2VerifyRequest {
|
||||
|
||||
/**
|
||||
* 外部公钥(原始字节,如从证书中获取的 PublicKey.getEncoded())
|
||||
*/
|
||||
private byte[] publicKey;
|
||||
|
||||
/**
|
||||
* 待验签的数据
|
||||
*/
|
||||
private byte[] data;
|
||||
|
||||
/**
|
||||
* 签名值(DER 格式或原始格式的签名)
|
||||
*/
|
||||
private byte[] signature;
|
||||
|
||||
/**
|
||||
* SM2 用户 ID(可选,默认 "1234567812345678")
|
||||
*/
|
||||
private byte[] userId;
|
||||
|
||||
public byte[] getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
public void setPublicKey(byte[] publicKey) {
|
||||
this.publicKey = publicKey;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public byte[] getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public void setSignature(byte[] signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public byte[] getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(byte[] userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.cisd.tms.modules.openapi.service.dto;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RawVerifyRequest {
|
||||
/**
|
||||
* 证书 DN 或机构号
|
||||
*/
|
||||
private String dn;
|
||||
private String origBytes;
|
||||
private String sessionId;
|
||||
/**
|
||||
* 裸签名串(Base64)
|
||||
*/
|
||||
private String signature;
|
||||
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package com.cisd.tms.modules.openapi.service.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* RawVerifyResponse
|
||||
* 验签响应结果
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(description = "验签响应")
|
||||
public class RawVerifyResponse {
|
||||
/**
|
||||
* 验签结果:true表示验签通过,false表示验签失败
|
||||
*/
|
||||
@Schema(description = "验签结果", example = "true")
|
||||
private boolean verified;
|
||||
|
||||
/**
|
||||
* 结果描述信息
|
||||
*/
|
||||
@Schema(description = "结果描述", example = "验签成功")
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 证书DN
|
||||
*/
|
||||
@Schema(description = "证书DN", example = "CN=Initial Entity,OU=Initial OU,O=Initial Org,L=Beijing,ST=Beijing,C=CN")
|
||||
private String dn;
|
||||
|
||||
public static RawVerifyResponse success(String dn) {
|
||||
return new RawVerifyResponse(true, "验签成功", dn);
|
||||
}
|
||||
|
||||
public static RawVerifyResponse failure(String dn, String reason) {
|
||||
return new RawVerifyResponse(false, "验签失败: " + reason, dn);
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@ import com.cisd.tms.common.exception.BizException;
|
||||
import com.cisd.tms.integration.crypto.pcie.Gm0018AlgorithmIds;
|
||||
import com.cisd.tms.integration.crypto.pcie.PcieSessionTemplate;
|
||||
import com.cisd.tms.integration.crypto.pcie.jna.EccRefPublicKey;
|
||||
import com.cisd.tms.integration.crypto.pcie.jna.EccSignature;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.BackupDataResult;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.EccExternalVerifyRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.UserKeySm2SignRequest;
|
||||
@ -13,6 +14,7 @@ import com.cisd.tms.modules.cert.entity.KeyEntity;
|
||||
import com.cisd.tms.modules.cert.service.CertificateService;
|
||||
import com.cisd.tms.modules.cert.service.EntityService;
|
||||
import com.cisd.tms.modules.openapi.service.IOpenApiService;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -94,7 +96,13 @@ public class OpenApiService implements IOpenApiService {
|
||||
throw new RuntimeException("签名失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String toHex(byte[] bytes) {
|
||||
StringBuilder builder = new StringBuilder(bytes.length * 2);
|
||||
for (byte b : bytes) {
|
||||
builder.append(String.format("%02x", b));
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean rawVerify(byte[] origBytes, String signature, String dn) {
|
||||
@ -128,18 +136,38 @@ public class OpenApiService implements IOpenApiService {
|
||||
log.info("找到证书: {}", cert.getSubjectDN());
|
||||
|
||||
// 将证书中的公钥转换为 EccRefPublicKey 结构
|
||||
EccRefPublicKey publicKey = EccRefPublicKey.fromPublicKey(cert.getPublicKey());
|
||||
log.info("公钥 x: {}, y: {}", toHex(publicKey.x), toHex(publicKey.y));
|
||||
byte[] publicKeyBlob = EccRefPublicKey.fromPublicKeyToBlob(cert.getPublicKey());
|
||||
log.info("公钥Blob长度: {} bytes", publicKeyBlob.length);
|
||||
log.info("公钥Blob {} 长度: {} bytes", toHex(publicKeyBlob), publicKeyBlob.length);
|
||||
|
||||
|
||||
// 解码签名
|
||||
byte[] sign = java.util.Base64.getDecoder().decode(signature);
|
||||
log.info("签名数据长度: {} bytes", sign.length);
|
||||
|
||||
// 使用外部公钥验签
|
||||
// 使用带公钥的 SM3 计算数据哈希
|
||||
log.info("使用带公钥的 SM3 计算数据哈希...");
|
||||
byte[] digest = sessionTemplate.withSession("SDF_HashFinal_SM2", (lib, deviceHandle, sessionHandle) -> {
|
||||
sessionTemplate.ensureSuccess(
|
||||
"SDF_HashInit",
|
||||
lib.SDF_HashInit(sessionHandle, Gm0018AlgorithmIds.SM3, publicKey, DEFAULT_SM2_USER_ID, DEFAULT_SM2_USER_ID.length)
|
||||
);
|
||||
if (origBytes.length > 0) {
|
||||
sessionTemplate.ensureSuccess("SDF_HashUpdate", lib.SDF_HashUpdate(sessionHandle, origBytes, origBytes.length));
|
||||
}
|
||||
byte[] out = new byte[32];
|
||||
IntByReference outLen = new IntByReference(out.length);
|
||||
sessionTemplate.ensureSuccess("SDF_HashFinal", lib.SDF_HashFinal(sessionHandle, out, outLen));
|
||||
return out;
|
||||
});
|
||||
log.info("SM3 哈希计算完成,哈希{} 长度: {} bytes", toHex(digest), digest.length);
|
||||
|
||||
// 使用外部公钥验签(注意:传递的是哈希值而不是原始数据)
|
||||
EccExternalVerifyRequest request = new EccExternalVerifyRequest();
|
||||
request.setAlgId(Gm0018AlgorithmIds.SM2_SIGN_1);
|
||||
request.setPublicKeyBlob(publicKeyBlob);
|
||||
request.setData(origBytes);
|
||||
request.setData(digest);
|
||||
request.setSignature(sign);
|
||||
|
||||
log.info("调用密码卡 SM2 外部公钥验签接口...");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user