导出公钥和证书

This commit is contained in:
liulu 2024-12-30 09:06:11 +08:00
parent 265d81a7f0
commit c05423c0a3
20 changed files with 597 additions and 70 deletions

View File

@ -43,12 +43,12 @@ public interface AppCertMapper extends BaseMapper<AppCert> {
return certs.iterator().next();
}
default AppCert selectEncBySubject(String dn) {
default AppCert selectByTypeAndDn(String type,String dn) {
Assert.hasText(dn, "证书序列号不能为空");
String subject = Subject.fromDN(dn).getDN();
List<AppCert> certs = selectList(new LambdaQueryWrapper<AppCert>()
.eq(AppCert::getSubject, subject)
.eq(AppCert::getCertType, KeyUsage.ENCRYPT_DECRYPT.getCode())
.eq(AppCert::getCertType, type)
);
if (CollectionUtils.isEmpty(certs)) {
return null;

View File

@ -25,12 +25,7 @@ import com.sunyard.chsm.utils.gm.BCSM4Utils;
import com.sunyard.chsm.utils.gm.cert.BCSM2CertUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.bouncycastle.asn1.ASN1BitString;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DLSequence;
import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
@ -50,12 +45,7 @@ import java.nio.ByteBuffer;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -155,6 +145,8 @@ public class AppCertServiceImpl implements AppCertService {
AppCert exist = appCertMapper.selectBySN(x509Cert.getSerialNumber().toString());
Assert.isNull(exist, "此证书已经存在");
exist = appCertMapper.selectByTypeAndDn(importCert.getCertType(), x509Cert.getSubjectX500Principal().getName());
Assert.isNull(exist, "此证书主题已经存在");
AppCert cert = genCert(x509Cert, keyInfo.getApplicationId(), record, importCert);
appCertMapper.insert(cert);

View File

@ -0,0 +1,26 @@
package com.sunyard.chsm.param;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @author liulu
* @since 2024/12/27
*/
@Data
public class ExportCertReq {
/**
* 证书的主题
*/
@NotBlank(message = "证书主题不能为空")
private String subject;
/**
* 证书类型: encrypt_decrypt 加密证书, sign_verify 签名证书
*/
@NotBlank(message = "证书类型不能为空")
private String certType;
}

View File

@ -0,0 +1,15 @@
package com.sunyard.chsm.param;
import lombok.Data;
/**
* @author liulu
* @since 2024/12/27
*/
@Data
public class ExportCertResp {
// 证书内容, base64编码
private String certText;
}

View File

@ -0,0 +1,18 @@
package com.sunyard.chsm.param;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author liulu
* @since 2024/12/27
*/
@Data
public class ExportPubKeyReq {
// 密钥ID
@NotNull(message = "密钥ID不能为空")
private Long keyId;
}

View File

@ -0,0 +1,21 @@
package com.sunyard.chsm.param;
import lombok.Data;
/**
* @author liulu
* @since 2024/12/27
*/
@Data
public class ExportPubKeyResp {
// 密钥ID
private Long keyId;
// 密钥索引
private String keyIndex;
// 公钥:x+y, base64编码
private String pubKey;
}

View File

@ -16,7 +16,7 @@ public class GenRandomReq {
// 随机数长度, 最大10240
@NotNull(message = "随机数长度不能为空")
@Min(value = 1L, message = "随机数长度最小为1")
@Max(value = 10240L, message = "随机数长度最大为10240")
@Max(value = 1024L, message = "随机数长度最大为1024")
private Integer length;

View File

@ -0,0 +1,45 @@
package com.sunyard.chsm.param;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
/**
* @author liulu
* @since 2024/12/27
*/
@Data
public class ImportCertReq {
/**
* 密钥算法 目前支持: SM2
*/
@NotEmpty(message = "密钥算法不能为空")
private String keyAlg;
/**
* 是否单证,
*/
@NotNull(message = "单双证不能为空")
private Boolean single;
/**
* 证书类型: encrypt_decrypt 加密证书, sign_verify 签名证书
*/
private String certType;
/**
* 单证证书内容
*/
private String certText;
/**
* 签名证书内容
*/
private String signCertText;
/**
* 加密证书内容
*/
private String encCertText;
/**
* 加密密钥信封
*/
private String envelopedKey;
private String remark;
}

View File

@ -26,6 +26,18 @@ public class AsymKeyController {
@Autowired
private AsymKeyService asymKeyService;
/**
* 导出非对称公钥
*
* @param req
* @return
*/
@PostMapping("/exportPubKey")
public R<ExportPubKeyResp> exportPubKey(@Valid @RequestBody ExportPubKeyReq req) {
ExportPubKeyResp resp = asymKeyService.exportPubKey(req);
return R.data(resp);
}
/**
* 非对称加密
*

View File

@ -3,10 +3,10 @@ package com.sunyard.chsm.controller;
import com.sunyard.chsm.model.R;
import com.sunyard.chsm.model.dto.CertDTO;
import com.sunyard.chsm.param.CertExinfoResp;
import com.sunyard.chsm.param.CertInfoResp;
import com.sunyard.chsm.param.*;
import com.sunyard.chsm.service.AppCertService;
import com.sunyard.chsm.service.CertService;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@ -15,7 +15,6 @@ import javax.validation.Valid;
/**
* 证书管理类接口
*
*/
@RestController
@RequestMapping("/cert")
@ -28,6 +27,17 @@ public class CertController {
@Resource
private CertService certService;
/**
* 导出证书
*
* @param req
* @return
*/
@PostMapping("/exportCert")
public R<ExportCertResp> exportCert(@Valid @RequestBody ExportCertReq req) {
ExportCertResp resp = certService.exportCert(req);
return R.data(resp);
}
/**
* 获取证书信息
@ -64,15 +74,15 @@ public class CertController {
}
/**
* 导入证书
*
* @param importCert 证书
* @param req 证书
*/
@GetMapping ("/import")
public R<Void> importCert(@Valid @RequestBody CertDTO.ImportCert importCert) {
@PostMapping("/import")
public R<Void> importCert(@Valid @RequestBody ImportCertReq req) {
CertDTO.ImportCert importCert = new CertDTO.ImportCert();
BeanUtils.copyProperties(req, importCert);
appCertService.importCert(importCert);
return R.ok();
}

View File

@ -7,7 +7,6 @@ import com.sunyard.chsm.sdf.SdfApiService;
import com.sunyard.chsm.sdf.context.AlgId;
import com.sunyard.chsm.sdf.model.*;
import com.sunyard.chsm.sdf.util.PaddingUtil;
import com.sunyard.chsm.utils.CodecUtils;
import com.sunyard.chsm.utils.gm.BCECUtils;
import com.sunyard.chsm.utils.gm.BCSM3Utils;
import com.sunyard.chsm.utils.gm.SM2PreprocessSigner;
@ -68,13 +67,6 @@ public class LoadBalancedSdfApiService implements SdfApiService {
Assert.notNull(iv, "CBC模式下, iv不能为空");
Assert.isTrue(iv.length >= key.length, "CBC模式下, iv长度不能低于key的长度");
}
log.info("symDecrypt: alg:{}, padding: {}, key: {}, iv:{}, cipherData:{}",
alg.name(),
padding.getCode(),
CodecUtils.encodeHex(key),
CodecUtils.encodeHex(iv),
CodecUtils.encodeHex(data)
);
byte[] decrypt = apply(s -> {
String keyHandle = s.getSdfApiAdapter().importKey(s.getSessionHandle(), key);
byte[] d = s.getSdfApiAdapter().symDecrypt(s.getSessionHandle(), keyHandle, alg, iv, data);
@ -193,9 +185,6 @@ public class LoadBalancedSdfApiService implements SdfApiService {
@Override
public byte[] decryptByTMK(byte[] data) {
byte[] decrypt = apply(s -> s.getSdfApiAdapter().symDecrypt(s.getSessionHandle(), s.getKeyHandle(), AlgId.SGD_SM4_CBC, CryptoConst.iv(), data));
if (log.isDebugEnabled()) {
log.debug("decryptByTMK res: {}", CodecUtils.encodeHex(decrypt));
}
return PaddingUtil.PKCS7Unpadding(decrypt);
}
}

View File

@ -58,6 +58,17 @@ public class AsymKeyService {
private final SpKeyRecordMapper spKeyRecordMapper;
private final SdfApiService sdfApiService;
public ExportPubKeyResp exportPubKey(ExportPubKeyReq req) {
KeyInfo keyInfo = checkKey(req.getKeyId(), null);
KeyRecord keyRecord = spKeyRecordMapper.selectUsedByKeyId(keyInfo.getId());
ExportPubKeyResp resp = new ExportPubKeyResp();
resp.setKeyId(keyInfo.getId());
resp.setKeyIndex(keyRecord.getKeyIndex());
byte[] pub = CodecUtils.decodeHex(keyRecord.getPubKey());
resp.setPubKey(CodecUtils.encodeBase64(pub));
return resp;
}
public AsymEncryptResp encrypt(AsymEncryptReq req) {
byte[] plainData = CodecUtils.decodeBase64(req.getPlainData());
@ -448,13 +459,15 @@ public class AsymKeyService {
KeyInfo keyInfo = keyInfoMapper.selectById(keyId);
Assert.notNull(keyInfo, "密钥ID不存在");
Assert.isTrue(Objects.equals(keyInfo.getApplicationId(), UserContext.getCurrentAppId()), "您无权使用此密钥ID");
Assert.isTrue(KeyCategory.ASYM_KEY.getCode().equals(keyInfo.getKeyType()), "此密钥不是对称密钥");
Assert.isTrue(KeyCategory.ASYM_KEY.getCode().equals(keyInfo.getKeyType()), "此密钥不是对称密钥");
KeyStatus status = KeyStatus.of(keyInfo.getStatus());
LocalDateTime now = LocalDateTime.now();
Assert.isTrue(KeyStatus.ENABLED == status, "此密钥不是启用状态, 无法操作");
Assert.isTrue(now.isAfter(keyInfo.getEffectiveTime()) && now.isBefore(keyInfo.getExpiredTime()), "此密钥不是启用状态, 无法操作");
if (usage != null) {
Assert.isTrue(KeyUsage.hasUsage(keyInfo.getKeyUsage(), usage), "此密钥无权进行" + usage.getDesc() + "操作");
}
return keyInfo;
}

View File

@ -1,21 +1,43 @@
package com.sunyard.chsm.service;
import com.sunyard.chsm.param.CertCheckResp;
import com.sunyard.chsm.param.CertExinfoResp;
import com.sunyard.chsm.param.CertInfoResp;
import com.sunyard.chsm.auth.UserContext;
import com.sunyard.chsm.enums.KeyUsage;
import com.sunyard.chsm.mapper.AppCertMapper;
import com.sunyard.chsm.model.entity.AppCert;
import com.sunyard.chsm.param.*;
import com.sunyard.chsm.utils.CertUtil;
import com.sunyard.chsm.utils.CodecUtils;
import com.sunyard.chsm.utils.DateFormat;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
@Service
@RequiredArgsConstructor
public class CertService {
private final AppCertMapper appCertMapper;
public ExportCertResp exportCert(ExportCertReq req) {
boolean checkType = Objects.equals(KeyUsage.ENCRYPT_DECRYPT.getCode(), req.getCertType())
|| Objects.equals(KeyUsage.SIGN_VERIFY.getCode(), req.getCertType());
Assert.isTrue(checkType, "证书类型错误");
AppCert appCert = appCertMapper.selectByTypeAndDn(req.getCertType(), req.getSubject());
Assert.notNull(appCert, "证书不存在");
Assert.isTrue(Objects.equals(appCert.getApplicationId(), UserContext.getCurrentAppId()), "您无权导出此证书");
ExportCertResp resp = new ExportCertResp();
resp.setCertText(appCert.getCertText());
return resp;
}
public CertInfoResp getCertInfo(String certString) {
X509Certificate x509Certificate = CertUtil.convertToX509Cert(certString);
CertInfoResp certInfo = new CertInfoResp();
@ -40,7 +62,6 @@ public class CertService {
}
public Boolean checkCert(String certString) {
X509Certificate x509Certificate = CertUtil.convertToX509Cert(certString);
CertCheckResp certCheck = new CertCheckResp();
@ -57,6 +78,4 @@ public class CertService {
}
}

View File

@ -3,9 +3,13 @@ package api;
import com.sunyard.chsm.param.*;
import com.sunyard.chsm.utils.CodecUtils;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.util.Collections;
/**
* @author liulu
* @since 2024/12/24
@ -23,18 +27,83 @@ public class AsymKeyTest extends BaseTest {
private static final String signDetachHsm = "MIIDMQYKKoEcz1UGAQQCAqCCAyEwggMdAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICMjCCAi4wggHSoAMCAQICBgGUAQHeQjAMBggqgRzPVQGDdQUAMEsxCzAJBgNVBAYTAkNOMQ4wDAYDVQQKEwVHTVNTTDEQMA4GA1UECxMHUEtJL1NNMjEaMBgGA1UEAxMRTWlkZGxlQ0EgZm9yIFRlc3QwIhgPMjAyNDEyMjUxNjAwMDBaGA8yMDI1MTIyNTE2MDAwMFowXTELMAkGA1UEBgwCQ04xCzAJBgNVBAgMAnpqMQswCQYDVQQHDAJoejEQMA4GA1UECgwHc3VueWFyZDEQMA4GA1UECwwHc3VueWFyZDEQMA4GA1UEAwwHdGVzdDEyMzBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABBNw7w5PxepQWwg5tfYoRIwilnqp01YvdY3ZnZD1ShHw6DX4f8cLblHagNazkOU9C5zeXvUWvtrcvZz5s92TLTGjgYkwgYYwGwYDVR0jBBQwEoAQ+X9VtCeUM2KmVspvzF0a/zAZBgNVHQ4EEgQQCR6s1jJA8ENWsIEo61LkMjAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGGFWh0dHBzOi8vb2NzcC5nbXNzbC5jbjAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIAwDAMBggqgRzPVQGDdQUAA0gAMEUCIEaCtRZ8G4OgwhqI6NqxVwfUELvHS7ojkTGbImLX1ZkiAiEApFb7utbtgvL5hkV0Gj/k/CLY0vl+RbYSqAVoPtNEr1oxgcMwgcACAQEwVTBLMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFR01TU0wxEDAOBgNVBAsTB1BLSS9TTTIxGjAYBgNVBAMTEU1pZGRsZUNBIGZvciBUZXN0AgYBlAEB3kIwDAYIKoEcz1UBgxEFADANBgkqgRzPVQGCLQEFAARHMEUCIEzIJwjBsG6/2VemCJuQ0/eJhNS+Nwcz+7+WqJwlsgV5AiEA4ILu0NFEaM3IC4d9gAFswOZnACwYnKR2/gm9eZB4GsY=";
private static final byte[] plainHsm = "12345678".getBytes();
@BeforeAll
public static void beforeAll() {
keyId = execute("/key/gen", KeyCreateReq.builder().keyTemplateCode(asymKeyTemplate).genNumber(1).build(), Long.class);
Assertions.assertTrue(keyId > 0);
}
@AfterAll
public static void afterAll() {
KeyManageReq keyManageReq = new KeyManageReq();
keyManageReq.setIds(Collections.singletonList(keyId));
execute("/key/disable", keyManageReq, Void.class);
execute("/key/destroy", keyManageReq, Void.class);
}
@Test
public void testExportKey() {
ExportPubKeyReq req = new ExportPubKeyReq();
req.setKeyId(keyId);
ExportPubKeyResp exportPubKeyResp = execute("/asym/exportPubKey", req, ExportPubKeyResp.class);
Assertions.assertNotNull(exportPubKeyResp);
log.info("ExportPubKeyResp: {}", exportPubKeyResp.getPubKey());
}
@Test
public void testRaw() {
AsymSignRawReq signRawReq = new AsymSignRawReq();
signRawReq.setKeyId(keyId);
signRawReq.setPlainData(CodecUtils.encodeBase64(plain));
AsymSignRawResp signRawResp = execute("/asym/sign/raw", signRawReq, AsymSignRawResp.class);
Assertions.assertNotNull(signRawResp);
log.info("AsymSignRawResp: {}", signRawResp);
AsymVerifyRawReq verifyRawReq = new AsymVerifyRawReq();
verifyRawReq.setKeyId(keyId);
verifyRawReq.setKeyIndex(signRawResp.getKeyIndex());
verifyRawReq.setPlainData(CodecUtils.encodeBase64(plain));
verifyRawReq.setSignData(signRawResp.getSignData());
VerifyResp verifyResp = execute("/asym/verify/raw", verifyRawReq, VerifyResp.class);
Assertions.assertNotNull(verifyResp);
log.info("verifyResp: {}", verifyResp);
Assertions.assertTrue(verifyResp.getVerified());
}
@Test
public void testAttach() {
AsymSignP7Req signP7Req = new AsymSignP7Req();
signP7Req.setSubject(dn);
signP7Req.setPlainData(CodecUtils.encodeBase64(plain));
AsymSignP7Resp signP7Resp = execute("/asym/sign/P7Attach", signP7Req, AsymSignP7Resp.class);
log.info("signP7: {}", signP7Resp.getSignData());
Assertions.assertNotNull(signP7Resp);
log.info("AsymSignP7Resp: {}", signP7Resp.getSignData());
AsymVerifyP7Req verifyP7Req = new AsymVerifyP7Req();
verifyP7Req.setSignData(signP7Resp.getSignData());
VerifyResp verifyResp = execute("/asym/verify/P7Attach", verifyP7Req, VerifyResp.class);
log.info("verifyResp: {}", verifyResp.getVerified());
Assertions.assertNotNull(verifyResp);
log.info("verifyResp: {}", verifyResp);
Assertions.assertTrue(verifyResp.getVerified());
}
@Test
public void testDetach() {
AsymSignP7Req signP7Req = new AsymSignP7Req();
signP7Req.setSubject(dn);
signP7Req.setPlainData(CodecUtils.encodeBase64(plain));
AsymSignP7Resp signP7Resp = execute("/asym/sign/P7Detach", signP7Req, AsymSignP7Resp.class);
Assertions.assertNotNull(signP7Resp);
log.info("AsymSignP7Resp: {}", signP7Resp.getSignData());
AsymVerifyP7Req verifyP7Req = new AsymVerifyP7Req();
verifyP7Req.setSignData(signP7Resp.getSignData());
verifyP7Req.setPlainData(CodecUtils.encodeBase64(plain));
VerifyResp verifyResp = execute("/asym/verify/P7Detach", verifyP7Req, VerifyResp.class);
Assertions.assertNotNull(verifyResp);
log.info("verifyResp: {}", verifyResp);
Assertions.assertTrue(verifyResp.getVerified());
}
@ -44,14 +113,16 @@ public class AsymKeyTest extends BaseTest {
AsymVerifyP7Req verifyP7Req = new AsymVerifyP7Req();
verifyP7Req.setSignData(signAttachHsm);
VerifyResp verifyResp = execute("/asym/verify/P7Attach", verifyP7Req, VerifyResp.class);
log.info("verifyResp: {}", verifyResp.getVerified());
Assertions.assertNotNull(verifyResp);
log.info("verifyResp: {}", verifyResp);
Assertions.assertTrue(verifyResp.getVerified());
verifyP7Req.setSignData(signDetachHsm);
verifyP7Req.setPlainData(CodecUtils.encodeBase64(plainHsm));
verifyResp = execute("/asym/verify/P7Detach", verifyP7Req, VerifyResp.class);
log.info("verifyResp: {}", verifyResp.getVerified());
Assertions.assertTrue(verifyResp.getVerified());
VerifyResp verifyResp2 = execute("/asym/verify/P7Detach", verifyP7Req, VerifyResp.class);
Assertions.assertNotNull(verifyResp2);
log.info("verifyResp: {}", verifyResp2);
Assertions.assertTrue(verifyResp2.getVerified());
}
@Test
@ -60,13 +131,15 @@ public class AsymKeyTest extends BaseTest {
sealReq.setEncCert(enc_cert);
sealReq.setPlainData(CodecUtils.encodeBase64(plain));
AsymEnvelopeSealResp sealResp = execute("/asym/envelope/seal", sealReq, AsymEnvelopeSealResp.class);
log.info("EnvelopeData: {}", sealResp.getEnvelopeData());
Assertions.assertNotNull(sealResp);
log.info("AsymEnvelopeSealResp: {}", sealResp);
AsymEnvelopeUnsealReq unsealReq = new AsymEnvelopeUnsealReq();
unsealReq.setEnvelopeData(sealResp.getEnvelopeData());
AsymEnvelopeUnsealResp unsealResp = execute("/asym/envelope/unseal", unsealReq, AsymEnvelopeUnsealResp.class);
log.info("verifyResp: {}", unsealResp.getPlainData());
log.info("verifyResp: {}", new String(CodecUtils.decodeBase64(unsealResp.getPlainData())));
Assertions.assertNotNull(unsealResp);
log.info("AsymEnvelopeUnsealResp: {}", unsealResp);
log.info("AsymEnvelopeUnsealResp: {}", new String(CodecUtils.decodeBase64(unsealResp.getPlainData())));
Assertions.assertArrayEquals(plain, CodecUtils.decodeBase64(unsealResp.getPlainData()));
}
@ -78,13 +151,15 @@ public class AsymKeyTest extends BaseTest {
sealReq.setEncCert(enc_cert);
sealReq.setPlainData(CodecUtils.encodeBase64(plain));
AsymEnvelopeSealResp sealResp = execute("/asym/signedEnvelope/seal", sealReq, AsymEnvelopeSealResp.class);
log.info("EnvelopeData: {}", sealResp.getEnvelopeData());
Assertions.assertNotNull(sealResp);
log.info("SignedEnvelopeEnvelopeSealResp: {}", sealResp);
AsymEnvelopeUnsealReq unsealReq = new AsymEnvelopeUnsealReq();
unsealReq.setEnvelopeData(sealResp.getEnvelopeData());
AsymEnvelopeUnsealResp unsealResp = execute("/asym/signedEnvelope/unseal", unsealReq, AsymEnvelopeUnsealResp.class);
log.info("verifyResp: {}", unsealResp.getPlainData());
log.info("verifyResp: {}", new String(CodecUtils.decodeBase64(unsealResp.getPlainData())));
Assertions.assertNotNull(unsealResp);
log.info("AsymEnvelopeUnsealResp: {}", unsealResp);
log.info("AsymEnvelopeUnsealResp: {}", new String(CodecUtils.decodeBase64(unsealResp.getPlainData())));
Assertions.assertArrayEquals(plain, CodecUtils.decodeBase64(unsealResp.getPlainData()));
}

View File

@ -27,6 +27,7 @@ import java.util.Optional;
public abstract class BaseTest {
protected static final String keyTemplate = "sym-sm4-001";
protected static final String asymKeyTemplate = "asym-sm2-001";
protected static final String ak = "216205d408130d83d13c5072305b8b65";
protected static final String sk = "ae64515d1d5adec2cc6ae8726d0c1bbc";
protected static final String server = "http://172.16.18.46:8900";

View File

@ -0,0 +1,197 @@
package api;
import com.sunyard.chsm.enums.AlgMode;
import com.sunyard.chsm.enums.Padding;
import com.sunyard.chsm.param.*;
import com.sunyard.chsm.sdf.util.LangUtils;
import com.sunyard.chsm.utils.CodecUtils;
import com.sunyard.chsm.utils.gm.BCSM3Utils;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.util.Assert;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
/**
* @author liulu
* @since 2024/12/27
*/
@Slf4j
public class BigDataTest extends BaseTest {
private static final byte[] plain = new byte[1024 * 7];
private final static byte[] iv = "ghwikdhj1234713v".getBytes();
private static Long keyId;
@BeforeAll
public static void beforeAll() {
Arrays.fill(plain, (byte) 0x04);
keyId = execute("/key/gen", KeyCreateReq.builder().keyTemplateCode(keyTemplate).genNumber(1).build(), Long.class);
Assertions.assertTrue(keyId > 0);
}
@AfterAll
public static void afterAll() {
KeyManageReq keyManageReq = new KeyManageReq();
keyManageReq.setIds(Collections.singletonList(keyId));
execute("/key/disable", keyManageReq, Void.class);
execute("/key/destroy", keyManageReq, Void.class);
}
@Test
public void testMultiSm4() {
byte[] bigdata = new byte[1024*7*1024];
Arrays.fill(bigdata, (byte) 0x07);
SymEncryptResp resp = multiPackageSymEnc(bigdata);
byte[] cipherData = CodecUtils.decodeBase64(resp.getCipherData());
log.info("SymEncryptResp: {}, {}", cipherData.length, resp);
byte[] plain = multiPackageSymDec(resp.getKeyIndex(), cipherData);
log.info("multiPackageSymDec: {}", plain.length);
Assertions.assertArrayEquals(bigdata, plain);
}
@Test
public void testMultiHash() {
byte[] bigdata = new byte[1024 * 7 * 128];
Arrays.fill(bigdata, (byte) 0x07);
byte[] hash = multiPackageHash(bigdata);
log.info("sdf hash: {}", CodecUtils.encodeHex(hash));
byte[] bcHash = BCSM3Utils.hash(bigdata);
log.info("bc hash: {}", CodecUtils.encodeHex(bcHash));
Assertions.assertArrayEquals(hash, bcHash);
}
public static byte[] multiPackageHash(byte[] data) {
return multiPackageHash(new ByteArrayInputStream(data));
}
public static byte[] multiPackageHash(InputStream is) {
HashResp hashResp = execute("/multi/package/hash/init", new HashReq(), HashResp.class);
Assert.notNull(hashResp, "HashInit failed");
log.info("hash: {}", hashResp);
HashReq hashReq = new HashReq();
hashReq.setHandle(hashResp.getHandle());
int len = 1024 * 7;
byte[] buffer = new byte[len];
while (true) {
int bytesRead;
try {
if ((bytesRead = is.read(buffer)) == -1) break;
} catch (IOException e) {
throw new RuntimeException(e);
}
if (bytesRead < len) {
buffer = Arrays.copyOf(buffer, bytesRead);
}
hashReq.setPlainData(CodecUtils.encodeBase64(buffer));
hashResp = execute("/multi/package/hash/update", hashReq, HashResp.class);
}
hashResp = execute("/multi/package/hash/finish", hashReq, HashResp.class);
Assert.notNull(hashResp, "HashFinish failed");
log.info("hash: {}", hashResp);
return CodecUtils.decodeBase64(hashResp.getHash());
}
static int len = 1024*7;
public static SymEncryptResp multiPackageSymEnc(byte[] array) {
return multiPackageSymEnc(new ByteArrayInputStream(array));
}
public static SymEncryptResp multiPackageSymEnc(InputStream is) {
SymEncryptReq symEncryptReq = new SymEncryptReq();
symEncryptReq.setKeyId(keyId);
symEncryptReq.setPadding(Padding.NOPadding);
symEncryptReq.setIv(CodecUtils.encodeBase64(iv));
symEncryptReq.setMode(AlgMode.CBC);
SymEncryptResp resp = new SymEncryptResp();
byte[] buffer = new byte[len];
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
while (true) {
int bytesRead;
if ((bytesRead = is.read(buffer)) == -1) break;
if (bytesRead < len) {
symEncryptReq.setPadding(Padding.PCKS7Padding);
buffer = Arrays.copyOf(buffer, bytesRead);
}
int available = is.available();
if (available < 16) {
byte[] bytes = new byte[available];
is.read(bytes);
buffer = LangUtils.merge(buffer, bytes);
symEncryptReq.setPadding(Padding.PCKS7Padding);
}
symEncryptReq.setPlainData(CodecUtils.encodeBase64(buffer));
SymEncryptResp tmp = execute("/sym/encrypt", symEncryptReq, SymEncryptResp.class);
os.write(CodecUtils.decodeBase64(tmp.getCipherData()));
resp.setKeyId(tmp.getKeyId());
resp.setKeyIndex(tmp.getKeyIndex());
}
resp.setCipherData(CodecUtils.encodeBase64(os.toByteArray()));
} catch (IOException e) {
throw new RuntimeException(e);
}
return resp;
}
public static byte[] multiPackageSymDec(String keyIdx, byte[] array) {
return multiPackageSymDec(keyIdx, new ByteArrayInputStream(array));
}
public static byte[] multiPackageSymDec(String keyIdx, InputStream is) {
SymDecryptReq decryptReq = new SymDecryptReq();
decryptReq.setKeyId(keyId);
decryptReq.setKeyIndex(keyIdx);
decryptReq.setPadding(Padding.NOPadding);
decryptReq.setIv(CodecUtils.encodeBase64(iv));
decryptReq.setMode(AlgMode.CBC);
byte[] buffer = new byte[len];
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
while (true) {
int bytesRead;
if ((bytesRead = is.read(buffer)) == -1) break;
if (bytesRead < len) {
decryptReq.setPadding(Padding.PCKS7Padding);
buffer = Arrays.copyOf(buffer, bytesRead);
}
int available = is.available();
if (available <= 16) {
decryptReq.setPadding(Padding.PCKS7Padding);
byte[] bytes = new byte[available];
is.read(bytes);
buffer = LangUtils.merge(buffer, bytes);
}
decryptReq.setCipherData(CodecUtils.encodeBase64(buffer));
SymDecryptResp resp = execute("/sym/decrypt", decryptReq, SymDecryptResp.class);
os.write(CodecUtils.decodeBase64(resp.getPlainData()));
}
return os.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -2,7 +2,6 @@ package api;
import com.sunyard.chsm.param.HashReq;
import com.sunyard.chsm.param.HashResp;
import com.sunyard.chsm.sdf.util.LangUtils;
import com.sunyard.chsm.utils.CodecUtils;
import com.sunyard.chsm.utils.gm.BCSM3Utils;
import lombok.extern.slf4j.Slf4j;
@ -39,13 +38,20 @@ public class HashTest extends BaseTest {
@Test
public void testMultiHash() {
int len = 128;
byte[] bigdata = new byte[1024 * 7 * len];
Arrays.fill(bigdata, (byte) 0x07);
HashReq hashReq = new HashReq();
HashResp hashResp = execute("/multi/package/hash/init", hashReq, HashResp.class);
log.info("hash: {}", hashResp);
hashReq.setPlainData(CodecUtils.encodeBase64(plain));
hashReq.setHandle(hashResp.getHandle());
for (int i = 0; i < 2; i++) {
for (int i = 0; i < len; i++) {
byte[] bytes = Arrays.copyOfRange(bigdata, 1024 * 7 * i, 1024 * 7 * (i + 1));
hashReq.setPlainData(CodecUtils.encodeBase64(bytes));
hashResp = execute("/multi/package/hash/update", hashReq, HashResp.class);
}
@ -53,7 +59,7 @@ public class HashTest extends BaseTest {
log.info("hash: {}", hashResp);
byte[] bcHash = BCSM3Utils.hash(LangUtils.merge(plain, plain));
byte[] bcHash = BCSM3Utils.hash(bigdata);
log.info("bc hash: {}", CodecUtils.encodeBase64(bcHash));
Assertions.assertEquals(CodecUtils.encodeBase64(bcHash), hashResp.getHash());
}

View File

@ -23,10 +23,11 @@ public class KeyManageTest extends BaseTest {
@Test
public void keyLifeTest() {
Long sm4KeyId = execute("/key/gen", KeyCreateReq.builder().keyTemplateCode(keyTemplate).genNumber(1).build(), Long.class);
Assertions.assertTrue(sm4KeyId > 0);
Assertions.assertTrue(sm4KeyId != null &&sm4KeyId > 0);
//
KeyInfo keyInfo = execute("/key/info", sm4KeyId, KeyInfo.class);
Assertions.assertNotNull(keyInfo);
Assertions.assertEquals(KeyAlg.SM4.getCode(), keyInfo.getKeyAlg());
Assertions.assertEquals(KeyStatus.ENABLED.getCode(), keyInfo.getStatus());
LocalDateTime now = LocalDateTime.now();
@ -38,18 +39,22 @@ public class KeyManageTest extends BaseTest {
execute("/key/disable", keyManageReq, Void.class);
keyInfo = execute("/key/info", sm4KeyId, KeyInfo.class);
Assertions.assertNotNull(keyInfo);
Assertions.assertEquals(KeyStatus.DISABLED.getCode(), keyInfo.getStatus());
//
execute("/key/enable", keyManageReq, Void.class);
keyInfo = execute("/key/info", sm4KeyId, KeyInfo.class);
Assertions.assertNotNull(keyInfo);
Assertions.assertEquals(KeyStatus.ENABLED.getCode(), keyInfo.getStatus());
execute("/key/disable", keyManageReq, Void.class);
keyInfo = execute("/key/info", sm4KeyId, KeyInfo.class);
Assertions.assertNotNull(keyInfo);
Assertions.assertEquals(KeyStatus.DISABLED.getCode(), keyInfo.getStatus());
execute("/key/archive", keyManageReq, Void.class);
keyInfo = execute("/key/info", sm4KeyId, KeyInfo.class);
Assertions.assertNotNull(keyInfo);
Assertions.assertEquals(KeyStatus.ARCHIVED.getCode(), keyInfo.getStatus());

View File

@ -0,0 +1,33 @@
package api;
import com.sunyard.chsm.param.GenRandomReq;
import com.sunyard.chsm.param.GenRandomResp;
import com.sunyard.chsm.utils.CodecUtils;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
/**
* @author liulu
* @since 2024/12/27
*/
@Slf4j
public class RandomTest extends BaseTest{
@Test
public void testRandom() {
GenRandomReq randomReq = new GenRandomReq();
randomReq.setLength(1024);
GenRandomResp genRandomResp = execute("/gen/random", randomReq, GenRandomResp.class);
Assertions.assertNotNull(genRandomResp);
log.info("random: {}", genRandomResp.getRandom());
byte[] bytes = CodecUtils.decodeBase64(genRandomResp.getRandom());
Assertions.assertEquals(1024, bytes.length);
}
}

View File

@ -40,7 +40,7 @@ public class SymKeyTest extends BaseTest {
}
@Test
public void testEncrypt() {
public void testEncAndDecCBC() {
SymEncryptReq symEncryptReq = new SymEncryptReq();
symEncryptReq.setKeyId(keyId);
@ -49,11 +49,9 @@ public class SymKeyTest extends BaseTest {
symEncryptReq.setMode(AlgMode.CBC);
SymEncryptResp symEncryptResp = execute("/sym/encrypt", symEncryptReq, SymEncryptResp.class);
log.info("SymEncryptResp: {}", symEncryptResp);
Assertions.assertNotNull(symEncryptResp);
log.info("SymEncryptResp: {}", symEncryptResp);
Assertions.assertTrue(StringUtils.hasText(symEncryptResp.getKeyIndex()));
byte[] cipherData = CodecUtils.decodeBase64(symEncryptResp.getCipherData());
// Assertions.assertEquals(32, cipherData.length);
SymDecryptReq decryptReq = new SymDecryptReq();
decryptReq.setKeyId(keyId);
@ -61,12 +59,64 @@ public class SymKeyTest extends BaseTest {
decryptReq.setIv(CodecUtils.encodeBase64(iv));
decryptReq.setMode(AlgMode.CBC);
decryptReq.setCipherData(symEncryptResp.getCipherData());
SymDecryptResp decryptResp = execute("/sym/decrypt", decryptReq, SymDecryptResp.class);
Assertions.assertNotNull(decryptResp);
Assertions.assertNotNull(decryptResp);
byte[] calPlain = CodecUtils.decodeBase64(decryptResp.getPlainData());
log.info("SymDecryptResp: {}, {}", calPlain, decryptResp);
Assertions.assertNotNull(decryptResp);
Assertions.assertArrayEquals(plain, calPlain);
}
@Test
public void testHmac() {
SymHmacReq hmacReq = new SymHmacReq();
hmacReq.setKeyId(keyId);
hmacReq.setPlainData(CodecUtils.encodeBase64(plain));
SymHmacResp hmacResp = execute("/sym/hmac", hmacReq, SymHmacResp.class);
Assertions.assertNotNull(hmacResp);
log.info("SymHmacResp: {}", hmacResp);
byte[] bytes = CodecUtils.decodeBase64(hmacResp.getHmac());
Assertions.assertEquals(32, bytes.length);
SymHmacCheckReq checkReq = new SymHmacCheckReq();
checkReq.setKeyId(keyId);
checkReq.setKeyIndex(hmacResp.getKeyIndex());
checkReq.setHmac(hmacResp.getHmac());
checkReq.setPlainData(CodecUtils.encodeBase64(plain));
VerifyResp verifyResp = execute("/sym/hmac/check", checkReq, VerifyResp.class);
Assertions.assertNotNull(verifyResp);
log.info("VerifyResp: {}", verifyResp);
Assertions.assertTrue(verifyResp.getVerified());
}
@Test
public void testMac() {
SymMacReq macReq = new SymMacReq();
macReq.setKeyId(keyId);
macReq.setIv(CodecUtils.encodeBase64(iv));
macReq.setPlainData(CodecUtils.encodeBase64(plain));
SymMacResp hmacResp = execute("/sym/mac", macReq, SymMacResp.class);
Assertions.assertNotNull(hmacResp);
log.info("SymMacResp: {}", hmacResp);
byte[] bytes = CodecUtils.decodeBase64(hmacResp.getMac());
Assertions.assertEquals(16, bytes.length);
SymMacCheckReq checkReq = new SymMacCheckReq();
checkReq.setKeyId(keyId);
checkReq.setKeyIndex(hmacResp.getKeyIndex());
checkReq.setIv(CodecUtils.encodeBase64(iv));
checkReq.setMac(hmacResp.getMac());
checkReq.setPlainData(CodecUtils.encodeBase64(plain));
VerifyResp verifyResp = execute("/sym/mac/check", checkReq, VerifyResp.class);
Assertions.assertNotNull(verifyResp);
log.info("VerifyResp: {}", verifyResp);
Assertions.assertTrue(verifyResp.getVerified());
}
}