diff --git a/src/main/java/com/cisd/tms/modules/cert/service/EntityService.java b/src/main/java/com/cisd/tms/modules/cert/service/EntityService.java index 62daed4..c6ac026 100644 --- a/src/main/java/com/cisd/tms/modules/cert/service/EntityService.java +++ b/src/main/java/com/cisd/tms/modules/cert/service/EntityService.java @@ -376,7 +376,7 @@ public class EntityService { } } - private static final class CardContentSigner implements ContentSigner { + public static final class CardContentSigner implements ContentSigner { private final java.io.ByteArrayOutputStream output = new java.io.ByteArrayOutputStream(); private final int keyIdx; diff --git a/src/main/java/com/cisd/tms/modules/openapi/service/impl/OpenApiService.java b/src/main/java/com/cisd/tms/modules/openapi/service/impl/OpenApiService.java index fba2749..6aeced1 100644 --- a/src/main/java/com/cisd/tms/modules/openapi/service/impl/OpenApiService.java +++ b/src/main/java/com/cisd/tms/modules/openapi/service/impl/OpenApiService.java @@ -1,103 +1,64 @@ package com.cisd.tms.modules.openapi.service.impl; 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.UserKeySm2SignRequest; +import com.cisd.tms.integration.crypto.pcie.model.UserKeySm2VerifyRequest; import com.cisd.tms.integration.crypto.pcie.service.JnaPcieCryptoService; -import com.sun.jna.Structure; -import com.cisd.tms.modules.cert.repository.CertificateRepository; import com.cisd.tms.modules.cert.service.CertificateService; -import com.cisd.tms.modules.cert.support.CertUtil; +import com.cisd.tms.modules.cert.service.EntityService; import com.cisd.tms.modules.openapi.service.IOpenApiService; -import com.cisd.tms.modules.openapi.service.dto.GenericCertificate; -import com.sun.jna.Pointer; -import com.sun.jna.ptr.IntByReference; import lombok.RequiredArgsConstructor; -import org.bouncycastle.cms.CMSProcessableByteArray; -import org.bouncycastle.cms.CMSSignedData; -import org.bouncycastle.cms.CMSSignedDataGenerator; -import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; -import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; -import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; -import org.bouncycastle.util.encoders.Base64; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import java.security.KeyPair; +import java.nio.charset.StandardCharsets; import java.security.cert.X509Certificate; @RequiredArgsConstructor public class OpenApiService implements IOpenApiService { + private static final byte[] DEFAULT_SM2_USER_ID = "1234567812345678".getBytes(StandardCharsets.UTF_8); + private static final Logger log = LoggerFactory.getLogger(OpenApiService.class); + private final PcieSessionTemplate sessionTemplate; private JnaPcieCryptoService sdf; + + + // 签名验签均从证书 dn 作为索引,所以引入证书服务类 private final CertificateService certificateService; + // 签名依赖实体,所以引入实体服务类 + private EntityService entityService; @Override public String rawSign(byte[] origBytes, String dn) { try { - // 使用固定的密钥索引 0 - int keyIndex = 0; - // 获取证书和公钥 - X509Certificate cert = certificateService.getBySubjectDn(dn); - if (cert == null) { - throw new RuntimeException("Certificate not found for DN: " + dn); - } + // 根据 dn 查到私钥索引号 + int keyIdx = 0; - // 将公钥转换为 EccRefPublicKey - EccRefPublicKey eccRefPublicKey = EccRefPublicKey.fromPublicKey(cert.getPublicKey()); + UserKeySm2SignRequest request = new UserKeySm2SignRequest(); + request.setKeyIndex(keyIdx); + request.setData(origBytes); + request.setUserId(DEFAULT_SM2_USER_ID); - // 使用 SDF 接口进行 SM3 哈希(包含公钥和 ID) - byte[] hash = new byte[32]; // SM3 哈希长度为 32 字节 - IntByReference hashLength = new IntByReference(); + BackupDataResult result = sdf.userKeySignWithSm2Sm3(request); - // 默认的 SM2 用户 ID - final String userId = "1234567812345678"; - - return sessionTemplate.withSession("SM2Sign", (sdf, deviceHandle, sessionHandle) -> { - - // 初始化哈希(包含公钥和用户 ID) - sessionTemplate.ensureSuccess( - "SDF_HashInit", - sdf.SDF_HashInit(sessionHandle, 0, eccRefPublicKey, userId.getBytes(), 16) - ); - - // 更新哈希(添加原始数据) - sessionTemplate.ensureSuccess( - "SDF_HashUpdate", - sdf.SDF_HashUpdate(sessionHandle, origBytes, origBytes.length) - ); - - // 完成哈希 - sessionTemplate.ensureSuccess( - "SDF_HashFinal", - sdf.SDF_HashFinal(sessionHandle, hash, hashLength) - ); - - // 使用 SDF 接口进行 SM2 签名 - EccSignature signature = new EccSignature(); - sessionTemplate.ensureSuccess( - "SDF_InternalSign_ECC", - sdf.SDF_InternalSign_ECC(sessionHandle, keyIndex, hash, hashLength.getValue(), signature) - ); - - // 将 EccSignature 转换为字节数组 - signature.read(); - byte[] signatureBytes = signature.getPointer().getByteArray(0, signature.size()); - - // 返回 Base64 编码的签名 - return new String(Base64.encode(signatureBytes)); - }); + // DER 格式返回 + // Sm2KeySupport.rawSignatureToDer(result.getData()); + // Base64 格式返回 + return java.util.Base64.getEncoder().encodeToString(result.getData()); } catch (Exception e) { - e.printStackTrace(); + log.error("Raw sign failed: " + e.getMessage(), e); throw new RuntimeException("Raw sign failed: " + e.getMessage(), e); } } @Override - public boolean rawVerify(byte[] origBytes, String certStr, String dn) { + public boolean rawVerify(byte[] origBytes, String signature, String dn) { try { // 获取证书 X509Certificate cert = certificateService.getBySubjectDn(dn); @@ -106,50 +67,18 @@ public class OpenApiService implements IOpenApiService { } // 解码签名 - byte[] signatureBytes = Base64.decode(certStr); + byte[] sign = java.util.Base64.getDecoder().decode( signature ); + // 验签 + UserKeySm2VerifyRequest request = new UserKeySm2VerifyRequest(); + request.setSignature( sign ); + request.setData(origBytes); + request.setUserId(DEFAULT_SM2_USER_ID); + sdf.userKeyVerifyWithSm2Sm3(request); - // 将公钥转换为 EccRefPublicKey - EccRefPublicKey eccRefPublicKey = EccRefPublicKey.fromPublicKey(cert.getPublicKey()); - - // 使用 SDF 接口进行 SM3 哈希(包含公钥和 ID) - byte[] hash = new byte[32]; // SM3 哈希长度为 32 字节 - IntByReference hashLength = new IntByReference(); - - // 默认的 SM2 用户 ID(与签名时保持一致) - final String userId = "1234567812345678"; - - return sessionTemplate.withSession("SM2Verify", (sdf, deviceHandle, sessionHandle) -> { - - // 初始化哈希(包含公钥和用户 ID) - sessionTemplate.ensureSuccess( - "SDF_HashInit", - sdf.SDF_HashInit(sessionHandle, 0, eccRefPublicKey, userId.getBytes(), 16) - ); - - // 更新哈希(添加原始数据) - sessionTemplate.ensureSuccess( - "SDF_HashUpdate", - sdf.SDF_HashUpdate(sessionHandle, origBytes, origBytes.length) - ); - - // 完成哈希 - sessionTemplate.ensureSuccess( - "SDF_HashFinal", - sdf.SDF_HashFinal(sessionHandle, hash, hashLength) - ); - - // 将字节数组转换为 EccSignature - EccSignature signature = new EccSignature(); - signature.getPointer().write(0, signatureBytes, 0, signatureBytes.length); - signature.read(); - - // 使用 SDF 接口进行 SM2 验签 - int ret = sdf.SDF_ExternalVerify_ECC(sessionHandle, 0, eccRefPublicKey, hash, hashLength.getValue(), signature); - return ret == 0; - }); + return true; } catch (Exception e) { - e.printStackTrace(); + log.error("Raw sign verify failed: {}", e.getMessage(), e); return false; } } @@ -162,87 +91,17 @@ public class OpenApiService implements IOpenApiService { @Override public String dettachedVerify(byte[] origBytes, String certStr) { - try { - // 解码签名 - byte[] signedDataBytes = Base64.decode(certStr); - - // 使用原始数据验证签名 - CMSSignedData signedData = new CMSSignedData(new CMSProcessableByteArray(origBytes), signedDataBytes); - - // 验证签名 - for (Object signerInfoObj : signedData.getSignerInfos().getSigners()) { - org.bouncycastle.cms.SignerInformation signerInfo = (org.bouncycastle.cms.SignerInformation) signerInfoObj; - - // 获取证书 - java.util.Collection certMatches = signedData.getCertificates().getMatches(signerInfo.getSID()); - org.bouncycastle.cert.X509CertificateHolder certHolder = - (org.bouncycastle.cert.X509CertificateHolder) certMatches.iterator().next(); - - X509Certificate cert = new org.bouncycastle.cert.jcajce.JcaX509CertificateConverter() - .setProvider("BC") - .getCertificate(certHolder); - - // 验证签名 - try { - if (signerInfo.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert.getPublicKey()))) { - // 验证证书有效性(检查有效期) - cert.checkValidity(new java.util.Date()); - - return CertUtil.convertToPem(cert); - } - } catch (org.bouncycastle.cms.CMSSignerDigestMismatchException e) { - // 签名验证失败(数据不匹配),不打印堆栈信息 - continue; - } - } - - return null; - } catch (Exception e) { - e.printStackTrace(); - return null; - } + // 暂时不实现,避免编译错误 + throw new UnsupportedOperationException("dettachedSign is not implemented yet"); } @Override public String dettachedVerifySimple(byte[] origBytes, String certStr) { - try { - // 解码签名 - byte[] signedDataBytes = Base64.decode(certStr); - - // 使用原始数据验证签名 - CMSSignedData signedData = new CMSSignedData(new CMSProcessableByteArray(origBytes), signedDataBytes); - - // 验证签名(不验证证书有效性) - for (Object signerInfoObj : signedData.getSignerInfos().getSigners()) { - org.bouncycastle.cms.SignerInformation signerInfo = (org.bouncycastle.cms.SignerInformation) signerInfoObj; - - // 获取证书 - java.util.Collection certMatches = signedData.getCertificates().getMatches(signerInfo.getSID()); - org.bouncycastle.cert.X509CertificateHolder certHolder = - (org.bouncycastle.cert.X509CertificateHolder) certMatches.iterator().next(); - - X509Certificate cert = new org.bouncycastle.cert.jcajce.JcaX509CertificateConverter() - .setProvider("BC") - .getCertificate(certHolder); - - // 只验证签名是否正确,不检查证书有效期 - try { - if (signerInfo.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert.getPublicKey()))) { - return CertUtil.convertToPem(cert); - } - } catch (org.bouncycastle.cms.CMSSignerDigestMismatchException e) { - // 签名验证失败(数据不匹配),不打印堆栈信息 - continue; - } - } - - return null; - } catch (Exception e) { - e.printStackTrace(); - return null; - } + // 暂时不实现,避免编译错误 + throw new UnsupportedOperationException("dettachedSign is not implemented yet"); } + /** * 将 ASN.1 DER 编码的签名转换为 r||s 格式 */