对称运算类接口

This commit is contained in:
liulu
2024-12-18 09:25:41 +08:00
parent bd099ba04e
commit 9cb9b43052
39 changed files with 891 additions and 119 deletions
-5
View File
@@ -24,11 +24,6 @@
<artifactId>chsm-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.sunyard.chsm</groupId>
<artifactId>chsm-params</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.dm</groupId>
@@ -1,5 +1,6 @@
package com.sunyard.chsm.controller;
import com.sunyard.chsm.model.R;
import com.sunyard.chsm.param.AppTokenReq;
import com.sunyard.chsm.param.AppTokenResp;
import com.sunyard.chsm.service.AppLoginService;
@@ -35,15 +36,16 @@ public class AppLoginController {
* @return
*/
@PostMapping("/appUser/getAppToken")
public AppTokenResp getAppToken(@Valid @RequestBody AppTokenReq appTokenReq) {
return appLoginService.getAppToken(appTokenReq);
public R<AppTokenResp> getAppToken(@Valid @RequestBody AppTokenReq appTokenReq) {
AppTokenResp appToken = appLoginService.getAppToken(appTokenReq);
return R.data(appToken);
}
@PostMapping("/appUser/getAppTokenTest")
public AppTokenResp getAppTokenForTest(@Valid @RequestBody AppTokenReq appTokenReq) {
return appLoginService.getAppTokenForTest(appTokenReq);
public R<AppTokenResp> getAppTokenForTest(@Valid @RequestBody AppTokenReq appTokenReq) {
AppTokenResp appToken = appLoginService.getAppTokenForTest(appTokenReq);
return R.data(appToken);
}
}
@@ -51,7 +51,7 @@ public class KeyManageController {
* @return 分页列表
*/
@PostMapping("/info")
public R<KeyInfoResp> queryInfo(Long id) {
public R<KeyInfoResp> queryInfo(@RequestBody Long id) {
Assert.notNull(id, "密钥id不能为空");
KeyInfoResp resp = keyManageService.queryInfo(id);
return R.data(resp);
@@ -0,0 +1,110 @@
package com.sunyard.chsm.controller;
import com.sunyard.chsm.model.R;
import com.sunyard.chsm.param.SymDecryptReq;
import com.sunyard.chsm.param.SymDecryptResp;
import com.sunyard.chsm.param.SymEncryptReq;
import com.sunyard.chsm.param.SymEncryptResp;
import com.sunyard.chsm.param.SymHmacCheckReq;
import com.sunyard.chsm.param.SymHmacCheckResp;
import com.sunyard.chsm.param.SymHmacReq;
import com.sunyard.chsm.param.SymHmacResp;
import com.sunyard.chsm.param.SymMacCheckReq;
import com.sunyard.chsm.param.SymMacCheckResp;
import com.sunyard.chsm.param.SymMacReq;
import com.sunyard.chsm.param.SymMacResp;
import com.sunyard.chsm.service.SymKeyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
/**
* 对称运算类接口
*
* @author liulu
* @since 2024/12/17
*/
@RestController
@RequestMapping("/sym")
public class SymKeyController {
@Autowired
private SymKeyService symKeyService;
/**
* 对称加密
*
* @param req
* @return
*/
@PostMapping("/encrypt")
public R<SymEncryptResp> encrypt(@Valid @RequestBody SymEncryptReq req) {
SymEncryptResp resp = symKeyService.encrypt(req);
return R.data(resp);
}
/**
* 对称解密
*
* @param req
* @return
*/
@PostMapping("/decrypt")
public R<SymDecryptResp> decrypt(@Valid @RequestBody SymDecryptReq req) {
SymDecryptResp resp = symKeyService.decrypt(req);
return R.data(resp);
}
/**
* 计算Hmac
*
* @param req
* @return
*/
@PostMapping("/hmac")
public R<SymHmacResp> hmac(@Valid @RequestBody SymHmacReq req) {
SymHmacResp resp = symKeyService.hmac(req);
return R.data(resp);
}
/**
* 验证Hmac
*
* @param req
* @return
*/
@PostMapping("/hmac/check")
public R<SymHmacCheckResp> macCheck(@Valid @RequestBody SymHmacCheckReq req) {
SymHmacCheckResp resp = symKeyService.hmacCheck(req);
return R.data(resp);
}
/**
* 计算Hmac
*
* @param req
* @return
*/
@PostMapping("/mac")
public R<SymMacResp> mac(@Valid @RequestBody SymMacReq req) {
SymMacResp resp = symKeyService.mac(req);
return R.data(resp);
}
/**
* 验证Hmac
*
* @param req
* @return
*/
@PostMapping("/mac/check")
public R<SymMacCheckResp> macCheck(@Valid @RequestBody SymMacCheckReq req) {
SymMacCheckResp resp = symKeyService.macCheck(req);
return R.data(resp);
}
}
@@ -1,33 +0,0 @@
package com.sunyard.chsm.param;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* @author liulu
* @since 2024/11/13
*/
@Data
public class AppTokenReq {
/**
* 平台分配的appKey
*/
@NotBlank
@Size(min = 16, max = 64, message = "appKey长度必须为16-64")
private String appKey;
/**
* 时间戳毫秒数,与服务器时间不能超过5分钟
*/
@NotNull
private Long random;
/**
* 使用appKey+random+appSecret作为原文,使用appSecret作为key,根据HmacSM3算法计算得到hmac值,转为Hex编码
*/
@NotBlank
@Size(min = 32, max = 64, message = "hmac长度在60-64之间")
private String hmac;
}
@@ -1,15 +0,0 @@
package com.sunyard.chsm.param;
import lombok.Data;
/**
* @author liulu
* @since 2024/11/13
*/
@Data
public class AppTokenResp {
/**
* 获取的token的值
*/
private String token;
}
@@ -1,26 +0,0 @@
package com.sunyard.chsm.param;
import lombok.Data;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
/**
* @author liulu
* @since 2024/12/17
*/
@Data
public class KeyCreateReq {
/**
* 密钥模版编码
*/
@NotNull(message = "密钥模版不能为空")
private String keyTemplateCode;
/**
* 生成数量
*/
@NotNull(message = "生成数量不能为空")
@Max(value = 100, message = "一次最多生成100个密钥")
private Integer genNumber;
}
@@ -1,32 +0,0 @@
package com.sunyard.chsm.param;
import com.sunyard.chsm.enums.KeyCategory;
import com.sunyard.chsm.enums.KeyStatus;
import lombok.Data;
/**
* @author liulu
* @since 2024/12/17
*/
@Data
public class KeyInfoQuery {
/**
* 当前页
*/
private int pageNumber = 1;
/**
* 每页大小
*/
private int pageSize = 10;
/**
* 密钥状态
*/
private KeyStatus status;
/**
* 密钥类型
*/
private KeyCategory keyType;
}
@@ -1,56 +0,0 @@
package com.sunyard.chsm.param;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author liulu
* @since 2024/12/17
*/
@Data
public class KeyInfoResp {
/**
* 密钥ID
*/
private String KeyId;
/**
* 密钥算法
*/
private String keyAlg;
/**
* 密钥类型
*/
private String keyType;
private String keyTypeText;
/**
* 密钥用途
*/
private List<String> keyUsages;
private String keyUsageText;
/**
* 校验算法
*/
private String checkAlg;
/**
* 校验值
*/
private String checkValue;
/**
* 密钥状态
*/
private String status;
private String statusText;
/**
* 生效时间
*/
private LocalDateTime effectiveTime;
/**
* 过期时间
*/
private LocalDateTime expiredTime;
private LocalDateTime createTime;
}
@@ -1,22 +0,0 @@
package com.sunyard.chsm.param;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.List;
/**
* @author liulu
* @since 2024/12/17
*/
@Data
public class KeyManageReq {
/**
* 密钥id列表
*/
@Size(min = 1, max = 100, message = "密钥id列表长度在1-100之间")
@NotNull(message = "密钥id列表不能为空")
private List<Long> ids;
}
@@ -1,28 +0,0 @@
package com.sunyard.chsm.param;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.time.LocalDate;
import java.util.List;
/**
* @author liulu
* @since 2024/12/17
*/
@Data
public class KeyUpdateReq {
/**
* 密钥id列表
*/
@Size(min = 1, max = 100, message = "密钥id列表长度在1-100之间")
@NotNull(message = "密钥id列表不能为空")
private List<Long> ids;
/**
* 新密钥生效时间 yyyy-MM-dd
*/
private LocalDate effectiveTime;
}
@@ -1,5 +1,6 @@
package com.sunyard.chsm.pool;
import com.sunyard.chsm.enums.Padding;
import com.sunyard.chsm.sdf.SdfApiService;
import com.sunyard.chsm.sdf.context.AlgId;
import com.sunyard.chsm.sdf.model.EccCipher;
@@ -46,24 +47,25 @@ public class LoadBalancedSdfApiService implements SdfApiService {
}
@Override
public byte[] symEncrypt(AlgId alg, byte[] key, byte[] iv, byte[] data) {
public byte[] symEncrypt(AlgId alg, Padding padding, byte[] key, byte[] iv, byte[] data) {
byte[] paddingData = PaddingUtil.padding(padding, data);
return apply(s -> {
String keyHandle = s.getSdfApiAdapter().importKey(s.getSessionHandle(), key);
byte[] encrypt = s.getSdfApiAdapter().symEncrypt(s.getSessionHandle(), keyHandle, alg, iv, PaddingUtil.PKCS7Padding(data));
byte[] encrypt = s.getSdfApiAdapter().symEncrypt(s.getSessionHandle(), keyHandle, alg, iv, paddingData);
s.getSdfApiAdapter().destroyKey(s.getSessionHandle(), keyHandle);
return encrypt;
});
}
@Override
public byte[] symDecrypt(AlgId alg, byte[] key, byte[] iv, byte[] data) {
public byte[] symDecrypt(AlgId alg, Padding padding, byte[] key, byte[] iv, byte[] data) {
byte[] decrypt = apply(s -> {
String keyHandle = s.getSdfApiAdapter().importKey(s.getSessionHandle(), key);
byte[] d = s.getSdfApiAdapter().symDecrypt(s.getSessionHandle(), keyHandle, alg, iv, data);
s.getSdfApiAdapter().destroyKey(s.getSessionHandle(), keyHandle);
return d;
});
return PaddingUtil.PKCS7Unpadding(decrypt);
return PaddingUtil.unpadding(padding, decrypt);
}
@Override
@@ -125,10 +127,11 @@ public class LoadBalancedSdfApiService implements SdfApiService {
}
@Override
public byte[] calculateMAC(byte[] symKey, byte[] pucIv, byte[] pucData) {
public byte[] calculateMAC(AlgId algId, Padding padding, byte[] symKey, byte[] pucIv, byte[] pucData) {
byte[] pad = PaddingUtil.padding(padding, pucData);
return apply(s -> {
String keyHandle = s.getSdfApiAdapter().importKey(s.getSessionHandle(), symKey);
byte[] mac = s.getSdfApiAdapter().calculateMAC(s.getSessionHandle(), keyHandle, AlgId.SGD_SM4_MAC, pucIv, PaddingUtil.PKCS7Padding(pucData));
byte[] mac = s.getSdfApiAdapter().calculateMAC(s.getSessionHandle(), keyHandle, algId, pucIv, pad);
s.getSdfApiAdapter().destroyKey(s.getSessionHandle(), keyHandle);
return mac;
});
@@ -3,6 +3,8 @@ package com.sunyard.chsm.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sunyard.chsm.auth.AppUser;
import com.sunyard.chsm.auth.UserContext;
import com.sunyard.chsm.enums.KeyCategory;
import com.sunyard.chsm.enums.KeyStatus;
import com.sunyard.chsm.mapper.KeyInfoMapper;
import com.sunyard.chsm.model.dto.KeyInfoDTO;
import com.sunyard.chsm.model.entity.KeyInfo;
@@ -22,6 +24,7 @@ import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
/**
@@ -40,7 +43,8 @@ public class KeyManageService {
public Page<KeyInfoResp> queryPageList(KeyInfoQuery query) {
KeyInfoDTO.Query nq = new KeyInfoDTO.Query();
BeanUtils.copyProperties(query, nq);
nq.setKeyType(Optional.ofNullable(query.getKeyType()).map(KeyCategory::getCode).orElse(null));
nq.setStatus(Optional.ofNullable(query.getStatus()).map(KeyStatus::getCode).orElse(null));
nq.setAppId(UserContext.getCurrentAppId());
Page<KeyInfoDTO.KeyView> page = keyInfoService.selectPageList(nq);
List<KeyInfoDTO.KeyView> records = page.getRecords();
@@ -51,7 +55,7 @@ public class KeyManageService {
.map(it -> {
KeyInfoResp resp = new KeyInfoResp();
BeanUtils.copyProperties(it, resp);
resp.setKeyId(it.getCode());
resp.setKeyId(it.getId());
return resp;
})
.collect(Collectors.toList());
@@ -64,7 +68,7 @@ public class KeyManageService {
KeyInfoDTO.KeyView view = keyInfoService.selectById(id);
KeyInfoResp resp = new KeyInfoResp();
BeanUtils.copyProperties(view, resp);
resp.setKeyId(view.getCode());
resp.setKeyId(view.getId());
return resp;
}
@@ -0,0 +1,231 @@
package com.sunyard.chsm.service;
import com.sunyard.chsm.auth.UserContext;
import com.sunyard.chsm.enums.AlgMode;
import com.sunyard.chsm.enums.KeyAlg;
import com.sunyard.chsm.enums.KeyCategory;
import com.sunyard.chsm.enums.KeyStatus;
import com.sunyard.chsm.enums.KeyUsage;
import com.sunyard.chsm.enums.Padding;
import com.sunyard.chsm.mapper.KeyInfoMapper;
import com.sunyard.chsm.mapper.SpKeyRecordMapper;
import com.sunyard.chsm.model.entity.KeyInfo;
import com.sunyard.chsm.model.entity.KeyRecord;
import com.sunyard.chsm.param.SymDecryptReq;
import com.sunyard.chsm.param.SymDecryptResp;
import com.sunyard.chsm.param.SymEncryptReq;
import com.sunyard.chsm.param.SymEncryptResp;
import com.sunyard.chsm.param.SymHmacCheckReq;
import com.sunyard.chsm.param.SymHmacCheckResp;
import com.sunyard.chsm.param.SymHmacReq;
import com.sunyard.chsm.param.SymHmacResp;
import com.sunyard.chsm.param.SymMacCheckReq;
import com.sunyard.chsm.param.SymMacCheckResp;
import com.sunyard.chsm.param.SymMacReq;
import com.sunyard.chsm.param.SymMacResp;
import com.sunyard.chsm.sdf.SdfApiService;
import com.sunyard.chsm.sdf.context.AlgId;
import com.sunyard.chsm.utils.CodecUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Objects;
/**
* @author liulu
* @since 2024/12/17
*/
@Service
@RequiredArgsConstructor
public class SymKeyService {
private final KeyInfoMapper keyInfoMapper;
private final SpKeyRecordMapper spKeyRecordMapper;
private final SdfApiService sdfApiService;
public SymEncryptResp encrypt(SymEncryptReq req) {
byte[] iv = new byte[0];
if (AlgMode.CBC == req.getMode()) {
Assert.hasText(req.getIv(), "CBC模式iv不能为空");
byte[] bytes = CodecUtils.decodeBase64(req.getIv());
Assert.isTrue(bytes.length >= 16, "iv长度至少为16");
iv = bytes;
}
byte[] plain = CodecUtils.decodeBase64(req.getPlainData());
KeyInfo keyInfo = checkKey(req.getKeyId(), KeyUsage.ENCRYPT_DECRYPT);
KeyAlg keyAlg = KeyAlg.of(keyInfo.getKeyAlg());
Assert.notNull(keyAlg, "数据异常");
AlgId algId = null;
switch (keyAlg) {
case SM4:
if (Padding.PCKS5Padding == req.getPadding()) {
req.setPadding(Padding.PCKS7Padding);
}
switch (req.getMode()) {
case ECB:
algId = AlgId.SGD_SM4_ECB;
break;
case CBC:
algId = AlgId.SGD_SM4_CBC;
break;
}
break;
default:
throw new UnsupportedOperationException("不支持的密钥算法:" + keyAlg.getCode());
}
KeyRecord keyRecord = spKeyRecordMapper.selectUsedByKeyId(keyInfo.getId());
Assert.notNull(keyRecord, "数据异常");
byte[] symKey = sdfApiService.decryptByTMK(CodecUtils.decodeHex(keyRecord.getKeyData()));
byte[] cipherData = sdfApiService.symEncrypt(algId, req.getPadding(), symKey, iv, plain);
SymEncryptResp resp = new SymEncryptResp();
resp.setKeyId(keyInfo.getId());
resp.setKeyIndex(keyRecord.getKeyIndex());
resp.setCipherData(CodecUtils.encodeBase64(cipherData));
return resp;
}
public SymDecryptResp decrypt(SymDecryptReq req) {
byte[] iv = new byte[0];
if (AlgMode.CBC == req.getMode()) {
Assert.hasText(req.getIv(), "CBC模式iv不能为空");
byte[] bytes = CodecUtils.decodeBase64(req.getIv());
Assert.isTrue(bytes.length >= 16, "iv长度至少为16");
iv = bytes;
}
byte[] cipher = CodecUtils.decodeBase64(req.getCipherData());
KeyInfo keyInfo = checkKey(req.getKeyId(), KeyUsage.ENCRYPT_DECRYPT);
KeyAlg keyAlg = KeyAlg.of(keyInfo.getKeyAlg());
Assert.notNull(keyAlg, "数据异常");
AlgId algId = null;
switch (keyAlg) {
case SM4:
if (Padding.PCKS5Padding == req.getPadding()) {
req.setPadding(Padding.PCKS7Padding);
}
switch (req.getMode()) {
case ECB:
algId = AlgId.SGD_SM4_ECB;
break;
case CBC:
algId = AlgId.SGD_SM4_CBC;
break;
}
break;
default:
throw new UnsupportedOperationException("不支持的密钥算法:" + keyAlg.getCode());
}
KeyRecord keyRecord = spKeyRecordMapper.selectById(Long.valueOf(req.getKeyIndex()));
Assert.notNull(keyRecord, "数据异常");
Assert.isTrue(Objects.equals(keyRecord.getKeyId(), keyInfo.getId()), "密钥Id和密钥索引不匹配");
byte[] symKey = sdfApiService.decryptByTMK(CodecUtils.decodeHex(keyRecord.getKeyData()));
byte[] plain = sdfApiService.symDecrypt(algId, req.getPadding(), symKey, iv, cipher);
SymDecryptResp resp = new SymDecryptResp();
resp.setKeyId(keyInfo.getId());
resp.setKeyIndex(keyRecord.getKeyIndex());
resp.setPlainData(CodecUtils.encodeBase64(plain));
return resp;
}
public SymHmacResp hmac(SymHmacReq req) {
byte[] plain = CodecUtils.decodeBase64(req.getPlainData());
KeyInfo keyInfo = checkKey(req.getKeyId(), KeyUsage.HMAC);
KeyRecord keyRecord = spKeyRecordMapper.selectUsedByKeyId(keyInfo.getId());
byte[] symKey = sdfApiService.decryptByTMK(CodecUtils.decodeHex(keyRecord.getKeyData()));
byte[] hmac = sdfApiService.hmac(symKey, plain);
SymHmacResp resp = new SymHmacResp();
resp.setKeyId(keyInfo.getId());
resp.setKeyIndex(keyRecord.getKeyIndex());
resp.setHmac(CodecUtils.encodeBase64(hmac));
return resp;
}
public SymHmacCheckResp hmacCheck(SymHmacCheckReq req) {
byte[] plain = CodecUtils.decodeBase64(req.getPlainData());
byte[] originHmac = CodecUtils.decodeBase64(req.getHmac());
KeyInfo keyInfo = checkKey(req.getKeyId(), KeyUsage.HMAC);
KeyRecord keyRecord = spKeyRecordMapper.selectById(Long.valueOf(req.getKeyIndex()));
Assert.notNull(keyRecord, "数据异常");
Assert.isTrue(Objects.equals(keyRecord.getKeyId(), keyInfo.getId()), "密钥Id和密钥索引不匹配");
byte[] symKey = sdfApiService.decryptByTMK(CodecUtils.decodeHex(keyRecord.getKeyData()));
byte[] hmac = sdfApiService.hmac(symKey, plain);
SymHmacCheckResp resp = new SymHmacCheckResp();
resp.setValid(Arrays.equals(hmac, originHmac));
return resp;
}
public SymMacResp mac(SymMacReq req) {
byte[] plain = CodecUtils.decodeBase64(req.getPlainData());
byte[] iv = CodecUtils.decodeBase64(req.getIv());
Assert.isTrue(iv.length >= 16, "iv长度至少为16");
KeyInfo keyInfo = checkKey(req.getKeyId(), KeyUsage.MAC);
KeyRecord keyRecord = spKeyRecordMapper.selectUsedByKeyId(keyInfo.getId());
Assert.notNull(keyRecord, "数据异常");
if (Padding.PCKS5Padding == req.getPadding()) {
req.setPadding(Padding.PCKS7Padding);
}
byte[] symKey = sdfApiService.decryptByTMK(CodecUtils.decodeHex(keyRecord.getKeyData()));
byte[] mac = sdfApiService.calculateMAC(AlgId.SGD_SM4_MAC, req.getPadding(), symKey, iv, plain);
SymMacResp resp = new SymMacResp();
resp.setKeyId(keyInfo.getId());
resp.setKeyIndex(keyRecord.getKeyIndex());
resp.setMac(CodecUtils.encodeBase64(mac));
return resp;
}
public SymMacCheckResp macCheck(SymMacCheckReq req) {
byte[] plain = CodecUtils.decodeBase64(req.getPlainData());
byte[] iv = CodecUtils.decodeBase64(req.getIv());
byte[] originMac = CodecUtils.decodeBase64(req.getMac());
KeyInfo keyInfo = checkKey(req.getKeyId(), KeyUsage.MAC);
KeyRecord keyRecord = spKeyRecordMapper.selectById(Long.valueOf(req.getKeyIndex()));
Assert.notNull(keyRecord, "数据异常");
Assert.isTrue(Objects.equals(keyRecord.getKeyId(), keyInfo.getId()), "密钥Id和密钥索引不匹配");
if (Padding.PCKS5Padding == req.getPadding()) {
req.setPadding(Padding.PCKS7Padding);
}
byte[] symKey = sdfApiService.decryptByTMK(CodecUtils.decodeHex(keyRecord.getKeyData()));
byte[] mac = sdfApiService.calculateMAC(AlgId.SGD_SM4_MAC, req.getPadding(), symKey, iv, plain);
SymMacCheckResp resp = new SymMacCheckResp();
resp.setValid(Arrays.equals(mac, originMac));
return resp;
}
private KeyInfo checkKey(Long keyId, KeyUsage usage) {
KeyInfo keyInfo = keyInfoMapper.selectById(keyId);
Assert.notNull(keyInfo, "密钥ID不存在");
Assert.isTrue(Objects.equals(keyInfo.getApplicationId(), UserContext.getCurrentAppId()), "您无权使用此密钥ID");
Assert.isTrue(KeyCategory.SYM_KEY.getCode().equals(keyInfo.getKeyType()), "此密钥不是对称密钥");
KeyStatus status = KeyStatus.of(keyInfo.getCode());
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() + "操作");
return keyInfo;
}
}
@@ -0,0 +1,70 @@
package api;
import com.fasterxml.jackson.core.type.TypeReference;
import com.sunyard.chsm.model.R;
import com.sunyard.chsm.param.AppTokenReq;
import com.sunyard.chsm.param.AppTokenResp;
import com.sunyard.chsm.utils.JsonUtils;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
/**
* @author liulu
* @since 2024/12/17
*/
public abstract class BaseTest {
protected static final String ak = "216205d408130d83d13c5072305b8b65";
protected static final String sk = "ae64515d1d5adec2cc6ae8726d0c1bbc";
protected static final String server = "http://127.0.0.1:8900";
protected static final RestTemplate restTemplate;
protected static final String token;
static {
AppTokenReq req = new AppTokenReq();
req.setAppKey(ak);
req.setHmac(sk);
req.setRandom(System.currentTimeMillis());
RequestEntity<byte[]> request = RequestEntity.post(server + "/appUser/getAppTokenTest")
.contentType(MediaType.APPLICATION_JSON)
.body(JsonUtils.toJsonBytes(req));
ResponseEntity<String> response = new RestTemplate().exchange(request, String.class);
try {
R<AppTokenResp> r = JsonUtils.objectMapper()
.readValue(response.getBody(), new TypeReference<R<AppTokenResp>>() {
});
token = r.getResult().getToken();
restTemplate = new RestTemplateBuilder()
.rootUri(server)
.defaultHeader("Authorization", "Bearer " + token)
.defaultHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
.build();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
protected static <T> T execute(String url, Object req, Class<T> tClass) {
try {
RequestEntity<byte[]> request = RequestEntity.post("/appUser/getAppTokenTest")
.contentType(MediaType.APPLICATION_JSON)
.header("Authorization", "Bearer " + token)
.body(JsonUtils.toJsonBytes(req));
byte[] res = restTemplate.postForObject(url, JsonUtils.toJsonBytes(req), byte[].class);
R<T> r = JsonUtils.objectMapper()
.readValue(res, new TypeReference<R<T>>() {
});
return r.getResult();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@@ -0,0 +1,48 @@
package api;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.sunyard.chsm.model.R;
import com.sunyard.chsm.model.entity.KeyInfo;
import com.sunyard.chsm.param.KeyInfoQuery;
import com.sunyard.chsm.param.KeyInfoResp;
import com.sunyard.chsm.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.util.CollectionUtils;
import java.util.List;
/**
* @author liulu
* @since 2024/12/17
*/
@Slf4j
public class KeyManageTest extends BaseTest {
private static Long keyId;
@BeforeAll
public static void before() throws Exception {
KeyInfoQuery query = new KeyInfoQuery();
byte[] res = restTemplate.postForObject("/key/pageList", JsonUtils.toJsonBytes(query), byte[].class);
R<Page<KeyInfoResp>> r = JsonUtils.objectMapper()
.readValue(res, new TypeReference<R<Page<KeyInfoResp>>>() {
});
Assertions.assertTrue(r.isSuccess());
List<KeyInfoResp> records = r.getResult().getRecords();
Assertions.assertFalse(CollectionUtils.isEmpty(records));
keyId = records.iterator().next().getKeyId();
}
@Test
public void keyInfoTest(){
KeyInfo res = execute("/key/info", keyId, KeyInfo.class);
log.info("keyInfoTest: {}", JsonUtils.toJsonString(res));
}
}