From c05423c0a3629088c2db697c16a56d4967ad674f Mon Sep 17 00:00:00 2001 From: liulu Date: Mon, 30 Dec 2024 09:06:11 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=BC=E5=87=BA=E5=85=AC=E9=92=A5=E5=92=8C?= =?UTF-8?q?=E8=AF=81=E4=B9=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sunyard/chsm/mapper/AppCertMapper.java | 4 +- .../chsm/service/impl/AppCertServiceImpl.java | 16 +- .../com/sunyard/chsm/param/ExportCertReq.java | 26 +++ .../sunyard/chsm/param/ExportCertResp.java | 15 ++ .../sunyard/chsm/param/ExportPubKeyReq.java | 18 ++ .../sunyard/chsm/param/ExportPubKeyResp.java | 21 ++ .../com/sunyard/chsm/param/GenRandomReq.java | 2 +- .../com/sunyard/chsm/param/ImportCertReq.java | 45 ++++ .../chsm/controller/AsymKeyController.java | 12 ++ .../chsm/controller/CertController.java | 32 ++- .../chsm/pool/LoadBalancedSdfApiService.java | 11 - .../sunyard/chsm/service/AsymKeyService.java | 17 +- .../com/sunyard/chsm/service/CertService.java | 37 +++- .../src/test/java/api/AsymKeyTest.java | 99 +++++++-- .../src/test/java/api/BaseTest.java | 1 + .../src/test/java/api/BigDataTest.java | 197 ++++++++++++++++++ .../src/test/java/api/HashTest.java | 14 +- .../src/test/java/api/KeyManageTest.java | 7 +- .../src/test/java/api/RandomTest.java | 33 +++ .../src/test/java/api/SymKeyTest.java | 60 +++++- 20 files changed, 597 insertions(+), 70 deletions(-) create mode 100644 chsm-params/src/main/java/com/sunyard/chsm/param/ExportCertReq.java create mode 100644 chsm-params/src/main/java/com/sunyard/chsm/param/ExportCertResp.java create mode 100644 chsm-params/src/main/java/com/sunyard/chsm/param/ExportPubKeyReq.java create mode 100644 chsm-params/src/main/java/com/sunyard/chsm/param/ExportPubKeyResp.java create mode 100644 chsm-params/src/main/java/com/sunyard/chsm/param/ImportCertReq.java create mode 100644 chsm-web-server/src/test/java/api/BigDataTest.java create mode 100644 chsm-web-server/src/test/java/api/RandomTest.java diff --git a/chsm-common/src/main/java/com/sunyard/chsm/mapper/AppCertMapper.java b/chsm-common/src/main/java/com/sunyard/chsm/mapper/AppCertMapper.java index 234709a..a53aa06 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/mapper/AppCertMapper.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/mapper/AppCertMapper.java @@ -43,12 +43,12 @@ public interface AppCertMapper extends BaseMapper { 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 certs = selectList(new LambdaQueryWrapper() .eq(AppCert::getSubject, subject) - .eq(AppCert::getCertType, KeyUsage.ENCRYPT_DECRYPT.getCode()) + .eq(AppCert::getCertType, type) ); if (CollectionUtils.isEmpty(certs)) { return null; diff --git a/chsm-common/src/main/java/com/sunyard/chsm/service/impl/AppCertServiceImpl.java b/chsm-common/src/main/java/com/sunyard/chsm/service/impl/AppCertServiceImpl.java index c04cc31..e24059e 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/service/impl/AppCertServiceImpl.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/service/impl/AppCertServiceImpl.java @@ -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); diff --git a/chsm-params/src/main/java/com/sunyard/chsm/param/ExportCertReq.java b/chsm-params/src/main/java/com/sunyard/chsm/param/ExportCertReq.java new file mode 100644 index 0000000..7f9b12b --- /dev/null +++ b/chsm-params/src/main/java/com/sunyard/chsm/param/ExportCertReq.java @@ -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; + +} diff --git a/chsm-params/src/main/java/com/sunyard/chsm/param/ExportCertResp.java b/chsm-params/src/main/java/com/sunyard/chsm/param/ExportCertResp.java new file mode 100644 index 0000000..d0ed3a9 --- /dev/null +++ b/chsm-params/src/main/java/com/sunyard/chsm/param/ExportCertResp.java @@ -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; + +} diff --git a/chsm-params/src/main/java/com/sunyard/chsm/param/ExportPubKeyReq.java b/chsm-params/src/main/java/com/sunyard/chsm/param/ExportPubKeyReq.java new file mode 100644 index 0000000..c84858b --- /dev/null +++ b/chsm-params/src/main/java/com/sunyard/chsm/param/ExportPubKeyReq.java @@ -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; + +} diff --git a/chsm-params/src/main/java/com/sunyard/chsm/param/ExportPubKeyResp.java b/chsm-params/src/main/java/com/sunyard/chsm/param/ExportPubKeyResp.java new file mode 100644 index 0000000..04a7437 --- /dev/null +++ b/chsm-params/src/main/java/com/sunyard/chsm/param/ExportPubKeyResp.java @@ -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; + +} diff --git a/chsm-params/src/main/java/com/sunyard/chsm/param/GenRandomReq.java b/chsm-params/src/main/java/com/sunyard/chsm/param/GenRandomReq.java index 486a5f6..f509de9 100644 --- a/chsm-params/src/main/java/com/sunyard/chsm/param/GenRandomReq.java +++ b/chsm-params/src/main/java/com/sunyard/chsm/param/GenRandomReq.java @@ -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; diff --git a/chsm-params/src/main/java/com/sunyard/chsm/param/ImportCertReq.java b/chsm-params/src/main/java/com/sunyard/chsm/param/ImportCertReq.java new file mode 100644 index 0000000..12adaef --- /dev/null +++ b/chsm-params/src/main/java/com/sunyard/chsm/param/ImportCertReq.java @@ -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; +} diff --git a/chsm-web-server/src/main/java/com/sunyard/chsm/controller/AsymKeyController.java b/chsm-web-server/src/main/java/com/sunyard/chsm/controller/AsymKeyController.java index 1e20aed..1989b46 100644 --- a/chsm-web-server/src/main/java/com/sunyard/chsm/controller/AsymKeyController.java +++ b/chsm-web-server/src/main/java/com/sunyard/chsm/controller/AsymKeyController.java @@ -26,6 +26,18 @@ public class AsymKeyController { @Autowired private AsymKeyService asymKeyService; + /** + * 导出非对称公钥 + * + * @param req + * @return + */ + @PostMapping("/exportPubKey") + public R exportPubKey(@Valid @RequestBody ExportPubKeyReq req) { + ExportPubKeyResp resp = asymKeyService.exportPubKey(req); + return R.data(resp); + } + /** * 非对称加密 * diff --git a/chsm-web-server/src/main/java/com/sunyard/chsm/controller/CertController.java b/chsm-web-server/src/main/java/com/sunyard/chsm/controller/CertController.java index d6f6db3..2d62f83 100644 --- a/chsm-web-server/src/main/java/com/sunyard/chsm/controller/CertController.java +++ b/chsm-web-server/src/main/java/com/sunyard/chsm/controller/CertController.java @@ -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,13 +27,24 @@ public class CertController { @Resource private CertService certService; + /** + * 导出证书 + * + * @param req + * @return + */ + @PostMapping("/exportCert") + public R exportCert(@Valid @RequestBody ExportCertReq req) { + ExportCertResp resp = certService.exportCert(req); + return R.data(resp); + } /** * 获取证书信息 * * @param certString 证书内容 */ - @GetMapping ("/info") + @GetMapping("/info") public R getCertInfo(@RequestParam String certString) { CertInfoResp certInfo = certService.getCertInfo(certString); return R.data(certInfo); @@ -45,7 +55,7 @@ public class CertController { * * @param certString 证书内容 */ - @GetMapping ("/exinfo") + @GetMapping("/exinfo") public R getCertExinfo(@RequestParam String certString) { CertExinfoResp certExinfo = certService.getCertExinfo(certString); return R.data(certExinfo); @@ -57,22 +67,22 @@ public class CertController { * * @param certString 证书内容 */ - @GetMapping ("/check") + @GetMapping("/check") public R certCheck(@RequestParam String certString) { Boolean res = certService.checkCert(certString); return R.data(res); } - - /** * 导入证书 * - * @param importCert 证书 + * @param req 证书 */ - @GetMapping ("/import") - public R importCert(@Valid @RequestBody CertDTO.ImportCert importCert) { + @PostMapping("/import") + public R importCert(@Valid @RequestBody ImportCertReq req) { + CertDTO.ImportCert importCert = new CertDTO.ImportCert(); + BeanUtils.copyProperties(req, importCert); appCertService.importCert(importCert); return R.ok(); } diff --git a/chsm-web-server/src/main/java/com/sunyard/chsm/pool/LoadBalancedSdfApiService.java b/chsm-web-server/src/main/java/com/sunyard/chsm/pool/LoadBalancedSdfApiService.java index 2ccc44e..c701cca 100644 --- a/chsm-web-server/src/main/java/com/sunyard/chsm/pool/LoadBalancedSdfApiService.java +++ b/chsm-web-server/src/main/java/com/sunyard/chsm/pool/LoadBalancedSdfApiService.java @@ -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); } } diff --git a/chsm-web-server/src/main/java/com/sunyard/chsm/service/AsymKeyService.java b/chsm-web-server/src/main/java/com/sunyard/chsm/service/AsymKeyService.java index 3efbe02..13c184c 100644 --- a/chsm-web-server/src/main/java/com/sunyard/chsm/service/AsymKeyService.java +++ b/chsm-web-server/src/main/java/com/sunyard/chsm/service/AsymKeyService.java @@ -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()), "此密钥不是启用状态, 无法操作"); - Assert.isTrue(KeyUsage.hasUsage(keyInfo.getKeyUsage(), usage), "此密钥无权进行" + usage.getDesc() + "操作"); + if (usage != null) { + Assert.isTrue(KeyUsage.hasUsage(keyInfo.getKeyUsage(), usage), "此密钥无权进行" + usage.getDesc() + "操作"); + } return keyInfo; } diff --git a/chsm-web-server/src/main/java/com/sunyard/chsm/service/CertService.java b/chsm-web-server/src/main/java/com/sunyard/chsm/service/CertService.java index ac724af..f82c698 100644 --- a/chsm-web-server/src/main/java/com/sunyard/chsm/service/CertService.java +++ b/chsm-web-server/src/main/java/com/sunyard/chsm/service/CertService.java @@ -1,22 +1,44 @@ 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 { - public CertInfoResp getCertInfo(String certString){ + + 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(); certInfo.setIssuerDN(x509Certificate.getIssuerDN().toString()); @@ -31,7 +53,7 @@ public class CertService { } - public CertExinfoResp getCertExinfo(String certString){ + public CertExinfoResp getCertExinfo(String certString) { X509Certificate x509Certificate = CertUtil.convertToX509Cert(certString); CertExinfoResp certExinfo = new CertExinfoResp(); certExinfo.setSigAlgOID(x509Certificate.getSigAlgOID()); @@ -40,8 +62,7 @@ public class CertService { } - - public Boolean checkCert(String certString){ + public Boolean checkCert(String certString) { X509Certificate x509Certificate = CertUtil.convertToX509Cert(certString); CertCheckResp certCheck = new CertCheckResp(); certCheck.setNotAfter(DateFormat.formDate(x509Certificate.getNotAfter())); @@ -57,6 +78,4 @@ public class CertService { } - - } diff --git a/chsm-web-server/src/test/java/api/AsymKeyTest.java b/chsm-web-server/src/test/java/api/AsymKeyTest.java index a978498..5bcac62 100644 --- a/chsm-web-server/src/test/java/api/AsymKeyTest.java +++ b/chsm-web-server/src/test/java/api/AsymKeyTest.java @@ -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())); } diff --git a/chsm-web-server/src/test/java/api/BaseTest.java b/chsm-web-server/src/test/java/api/BaseTest.java index d230486..9acef46 100644 --- a/chsm-web-server/src/test/java/api/BaseTest.java +++ b/chsm-web-server/src/test/java/api/BaseTest.java @@ -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"; diff --git a/chsm-web-server/src/test/java/api/BigDataTest.java b/chsm-web-server/src/test/java/api/BigDataTest.java new file mode 100644 index 0000000..66ed113 --- /dev/null +++ b/chsm-web-server/src/test/java/api/BigDataTest.java @@ -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); + } + } + + +} diff --git a/chsm-web-server/src/test/java/api/HashTest.java b/chsm-web-server/src/test/java/api/HashTest.java index f24397d..b558da4 100644 --- a/chsm-web-server/src/test/java/api/HashTest.java +++ b/chsm-web-server/src/test/java/api/HashTest.java @@ -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()); } diff --git a/chsm-web-server/src/test/java/api/KeyManageTest.java b/chsm-web-server/src/test/java/api/KeyManageTest.java index a881e52..5237c7e 100644 --- a/chsm-web-server/src/test/java/api/KeyManageTest.java +++ b/chsm-web-server/src/test/java/api/KeyManageTest.java @@ -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()); diff --git a/chsm-web-server/src/test/java/api/RandomTest.java b/chsm-web-server/src/test/java/api/RandomTest.java new file mode 100644 index 0000000..9fbf458 --- /dev/null +++ b/chsm-web-server/src/test/java/api/RandomTest.java @@ -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); + + } + + + +} diff --git a/chsm-web-server/src/test/java/api/SymKeyTest.java b/chsm-web-server/src/test/java/api/SymKeyTest.java index 150c8b7..26e46a4 100644 --- a/chsm-web-server/src/test/java/api/SymKeyTest.java +++ b/chsm-web-server/src/test/java/api/SymKeyTest.java @@ -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()); + } + }