hash 运算
This commit is contained in:
parent
182918a7b9
commit
6cdf222def
@ -63,7 +63,7 @@ public class SdfApiAdapterFactory {
|
|||||||
new Class[]{SdfApiAdapter.class},
|
new Class[]{SdfApiAdapter.class},
|
||||||
(proxy, method, args) -> {
|
(proxy, method, args) -> {
|
||||||
if (Objects.equals(method.getName(), "openDevice")) {
|
if (Objects.equals(method.getName(), "openDevice")) {
|
||||||
return rpcSdfAdapter.openDevice(ip, port, 3000, 3000, 0);
|
return rpcSdfAdapter.openDevice(ip, port, 3000, 10000, 0);
|
||||||
}
|
}
|
||||||
return method.invoke(rpcSdfAdapter, args);
|
return method.invoke(rpcSdfAdapter, args);
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ public class SunyardJnaSdfAdaptor extends JnaSdfAdaptor {
|
|||||||
private final Integer dealTimeout;
|
private final Integer dealTimeout;
|
||||||
|
|
||||||
public SunyardJnaSdfAdaptor(String ip, int port) {
|
public SunyardJnaSdfAdaptor(String ip, int port) {
|
||||||
this(ip, port, 3000, 3000);
|
this(ip, port, 3000, 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SunyardJnaSdfAdaptor(String ip, int port, int connTimeout, int dealTimeout) {
|
public SunyardJnaSdfAdaptor(String ip, int port, int connTimeout, int dealTimeout) {
|
||||||
|
@ -23,7 +23,7 @@ public class AppTokenReq {
|
|||||||
* 时间戳毫秒数,与服务器时间不能超过5分钟
|
* 时间戳毫秒数,与服务器时间不能超过5分钟
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
private Long random;
|
private Long timestamp;
|
||||||
/**
|
/**
|
||||||
* 使用appKey+random+appSecret作为原文,使用appSecret作为key,根据HmacSM3算法计算得到hmac值,转为Hex编码
|
* 使用appKey+random+appSecret作为原文,使用appSecret作为key,根据HmacSM3算法计算得到hmac值,转为Hex编码
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.sunyard.chsm.param;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.Max;
|
||||||
|
import javax.validation.constraints.Min;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liulu
|
||||||
|
* @since 2024/12/25
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class GenRandomReq {
|
||||||
|
|
||||||
|
// 随机数长度, 最大10240
|
||||||
|
@NotNull(message = "随机数长度不能为空")
|
||||||
|
@Min(value = 1L, message = "随机数长度最小为1")
|
||||||
|
@Max(value = 10240L, message = "随机数长度最大为10240")
|
||||||
|
private Integer length;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.sunyard.chsm.param;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liulu
|
||||||
|
* @since 2024/12/25
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class GenRandomResp {
|
||||||
|
|
||||||
|
// 随机数, base64编码
|
||||||
|
private String random;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -3,15 +3,14 @@ package com.sunyard.chsm.param;
|
|||||||
import com.sunyard.chsm.enums.HashAlg;
|
import com.sunyard.chsm.enums.HashAlg;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class HashReq {
|
public class HashReq {
|
||||||
|
|
||||||
// 明文,使用Base64编码
|
// 明文,使用Base64编码
|
||||||
@NotBlank(message = "明文不能为空")
|
|
||||||
private String plainData;
|
private String plainData;
|
||||||
|
|
||||||
|
// 句柄, 多包计算Init后返回
|
||||||
|
private String handle;
|
||||||
// Hash算法, 默认SM3
|
// Hash算法, 默认SM3
|
||||||
private HashAlg alg = HashAlg.SM3;
|
private HashAlg alg = HashAlg.SM3;
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@ import lombok.Data;
|
|||||||
@Data
|
@Data
|
||||||
public class HashResp {
|
public class HashResp {
|
||||||
|
|
||||||
|
// 句柄, 多包计算Init后返回
|
||||||
|
private String handle;
|
||||||
|
|
||||||
// mac值,使用Base64编码
|
// mac值,使用Base64编码
|
||||||
private String hash;
|
private String hash;
|
||||||
|
|
||||||
|
@ -41,11 +41,5 @@ public class AppLoginController {
|
|||||||
return R.data(appToken);
|
return R.data(appToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/appUser/getAppTokenTest")
|
|
||||||
public R<AppTokenResp> getAppTokenForTest(@Valid @RequestBody AppTokenReq appTokenReq) {
|
|
||||||
AppTokenResp appToken = appLoginService.getAppTokenForTest(appTokenReq);
|
|
||||||
return R.data(appToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,29 @@ package com.sunyard.chsm.controller;
|
|||||||
|
|
||||||
import com.sunyard.chsm.auth.AuthCode;
|
import com.sunyard.chsm.auth.AuthCode;
|
||||||
import com.sunyard.chsm.constant.AuthCodeConst;
|
import com.sunyard.chsm.constant.AuthCodeConst;
|
||||||
|
import com.sunyard.chsm.constant.CryptoConst;
|
||||||
import com.sunyard.chsm.model.R;
|
import com.sunyard.chsm.model.R;
|
||||||
import com.sunyard.chsm.param.HashReq;
|
import com.sunyard.chsm.param.HashReq;
|
||||||
import com.sunyard.chsm.param.HashResp;
|
import com.sunyard.chsm.param.HashResp;
|
||||||
|
import com.sunyard.chsm.pool.DeviceManager;
|
||||||
|
import com.sunyard.chsm.pool.TMKContext;
|
||||||
import com.sunyard.chsm.sdf.SdfApiService;
|
import com.sunyard.chsm.sdf.SdfApiService;
|
||||||
|
import com.sunyard.chsm.sdf.adapter.SdfApiAdapter;
|
||||||
|
import com.sunyard.chsm.sdf.context.AlgId;
|
||||||
|
import com.sunyard.chsm.sdf.model.EccPubKey;
|
||||||
import com.sunyard.chsm.utils.CodecUtils;
|
import com.sunyard.chsm.utils.CodecUtils;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 杂凑运算类接口
|
* 杂凑运算类接口
|
||||||
@ -25,6 +37,8 @@ public class HashController {
|
|||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SdfApiService sdfApiService;
|
private SdfApiService sdfApiService;
|
||||||
|
@Resource
|
||||||
|
private DeviceManager deviceManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算Hash
|
* 计算Hash
|
||||||
@ -35,7 +49,9 @@ public class HashController {
|
|||||||
@PostMapping("/hash")
|
@PostMapping("/hash")
|
||||||
@AuthCode(AuthCodeConst.cal_hash)
|
@AuthCode(AuthCodeConst.cal_hash)
|
||||||
public R<HashResp> hash(@Valid @RequestBody HashReq req) {
|
public R<HashResp> hash(@Valid @RequestBody HashReq req) {
|
||||||
|
Assert.hasText(req.getPlainData(), "原文不能为空");
|
||||||
byte[] bytes = CodecUtils.decodeBase64(req.getPlainData());
|
byte[] bytes = CodecUtils.decodeBase64(req.getPlainData());
|
||||||
|
Assert.isTrue(bytes.length <= 8192, "原文长度最大支持8192");
|
||||||
byte[] pubkey = CodecUtils.decodeBase64(req.getPubKey());
|
byte[] pubkey = CodecUtils.decodeBase64(req.getPubKey());
|
||||||
byte[] userId = CodecUtils.decodeBase64(req.getUserId());
|
byte[] userId = CodecUtils.decodeBase64(req.getUserId());
|
||||||
byte[] hash = sdfApiService.hash(bytes, pubkey, userId);
|
byte[] hash = sdfApiService.hash(bytes, pubkey, userId);
|
||||||
@ -44,5 +60,89 @@ public class HashController {
|
|||||||
return R.data(resp);
|
return R.data(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Map<String, TMKContext> HANDLE_MAP = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多包HashInit
|
||||||
|
*
|
||||||
|
* @param req
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@PostMapping("/multi/package/hash/init")
|
||||||
|
@AuthCode(AuthCodeConst.cal_hash)
|
||||||
|
public R<HashResp> hashInit(@Valid @RequestBody HashReq req) {
|
||||||
|
byte[] pubKey = CodecUtils.decodeBase64(req.getPubKey());
|
||||||
|
byte[] userId = CodecUtils.decodeBase64(req.getUserId());
|
||||||
|
TMKContext context = deviceManager.chooseOne();
|
||||||
|
try {
|
||||||
|
SdfApiAdapter sdf = context.getSdfApiAdapter();
|
||||||
|
TMKContext newContext = new TMKContext();
|
||||||
|
newContext.setDeviceHandle(context.getDeviceHandle());
|
||||||
|
newContext.setSdfApiAdapter(sdf);
|
||||||
|
String hs = sdf.openSession(context.getDeviceHandle());
|
||||||
|
newContext.setSessionHandle(hs);
|
||||||
|
EccPubKey eccPubKey = pubKey == null || pubKey.length == 0 ? null : EccPubKey.fromBytes(pubKey);
|
||||||
|
byte[] finalUserId = Objects.nonNull(pubKey) && Objects.isNull(userId) ? CryptoConst.USER_ID : userId;
|
||||||
|
sdf.hashInit(hs, AlgId.SGD_SM3, eccPubKey, finalUserId);
|
||||||
|
String handle = UUID.randomUUID().toString();
|
||||||
|
HANDLE_MAP.put(handle, newContext);
|
||||||
|
|
||||||
|
HashResp resp = new HashResp();
|
||||||
|
resp.setHandle(handle);
|
||||||
|
return R.data(resp);
|
||||||
|
} finally {
|
||||||
|
Optional.ofNullable(context.getPool())
|
||||||
|
.ifPresent(it -> {
|
||||||
|
context.setPool(null);
|
||||||
|
it.returnObject(context);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多包Hash update
|
||||||
|
*
|
||||||
|
* @param req
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@PostMapping("/multi/package/hash/update")
|
||||||
|
@AuthCode(AuthCodeConst.cal_hash)
|
||||||
|
public R<HashResp> hashUpdate(@Valid @RequestBody HashReq req) {
|
||||||
|
Assert.hasText(req.getPlainData(), "原文不能为空");
|
||||||
|
Assert.hasText(req.getHandle(), "句柄不能为空");
|
||||||
|
byte[] bytes = CodecUtils.decodeBase64(req.getPlainData());
|
||||||
|
Assert.isTrue(bytes.length <= 8192, "原文长度最大支持8192");
|
||||||
|
TMKContext context = HANDLE_MAP.get(req.getHandle());
|
||||||
|
Assert.notNull(context, "句柄引用不存在");
|
||||||
|
SdfApiAdapter sdf = context.getSdfApiAdapter();
|
||||||
|
sdf.hashUpdate(context.getSessionHandle(), bytes);
|
||||||
|
HashResp resp = new HashResp();
|
||||||
|
resp.setHandle(req.getHandle());
|
||||||
|
return R.data(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多包Hash finish
|
||||||
|
*
|
||||||
|
* @param req
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@PostMapping("/multi/package/hash/finish")
|
||||||
|
@AuthCode(AuthCodeConst.cal_hash)
|
||||||
|
public R<HashResp> hashFinish(@Valid @RequestBody HashReq req) {
|
||||||
|
Assert.hasText(req.getHandle(), "句柄不能为空");
|
||||||
|
TMKContext context = HANDLE_MAP.remove(req.getHandle());
|
||||||
|
Assert.notNull(context, "句柄引用不存在");
|
||||||
|
SdfApiAdapter sdf = context.getSdfApiAdapter();
|
||||||
|
byte[] hash = sdf.hashFinish(context.getSessionHandle());
|
||||||
|
sdf.closeSession(context.getSessionHandle());
|
||||||
|
HashResp resp = new HashResp();
|
||||||
|
resp.setHandle(req.getHandle());
|
||||||
|
resp.setHash(CodecUtils.encodeBase64(hash));
|
||||||
|
return R.data(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.sunyard.chsm.controller;
|
||||||
|
|
||||||
|
import com.sunyard.chsm.auth.AuthCode;
|
||||||
|
import com.sunyard.chsm.constant.AuthCodeConst;
|
||||||
|
import com.sunyard.chsm.model.R;
|
||||||
|
import com.sunyard.chsm.param.GenRandomReq;
|
||||||
|
import com.sunyard.chsm.param.GenRandomResp;
|
||||||
|
import com.sunyard.chsm.sdf.SdfApiService;
|
||||||
|
import com.sunyard.chsm.utils.CodecUtils;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 随机数接口
|
||||||
|
*
|
||||||
|
* @author liulu
|
||||||
|
* @since 2024/12/25
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class RandomController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SdfApiService sdfApiService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取随机数
|
||||||
|
*
|
||||||
|
* @param req
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@PostMapping("/gen/random")
|
||||||
|
@AuthCode(AuthCodeConst.gen_random)
|
||||||
|
public R<GenRandomResp> hash(@RequestBody GenRandomReq req) {
|
||||||
|
byte[] random = sdfApiService.generateRandom(req.getLength());
|
||||||
|
GenRandomResp resp = new GenRandomResp();
|
||||||
|
resp.setRandom(CodecUtils.encodeBase64(random));
|
||||||
|
return R.data(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -21,14 +21,7 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.Valid;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,7 +43,7 @@ public class AppLoginService {
|
|||||||
private AppServiceMapper appServiceMapper;
|
private AppServiceMapper appServiceMapper;
|
||||||
|
|
||||||
public AppTokenResp getAppToken(AppTokenReq req) {
|
public AppTokenResp getAppToken(AppTokenReq req) {
|
||||||
Long random = req.getRandom();
|
Long random = req.getTimestamp();
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
Assert.isTrue(now - random <= 5 * 60 * 1000, "请求已超时");
|
Assert.isTrue(now - random <= 5 * 60 * 1000, "请求已超时");
|
||||||
String appKey = req.getAppKey();
|
String appKey = req.getAppKey();
|
||||||
@ -58,7 +51,7 @@ public class AppLoginService {
|
|||||||
Assert.isTrue(EnableStatus.ENABLED.getCode().equals(application.getStatus()), "此应用已停用");
|
Assert.isTrue(EnableStatus.ENABLED.getCode().equals(application.getStatus()), "此应用已停用");
|
||||||
String data = appKey + random + application.getAppSecret();
|
String data = appKey + random + application.getAppSecret();
|
||||||
byte[] hmac = BCSM3Utils.hmac(application.getAppSecret().getBytes(), data.getBytes());
|
byte[] hmac = BCSM3Utils.hmac(application.getAppSecret().getBytes(), data.getBytes());
|
||||||
String serverHmac = CodecUtils.encodeHex(hmac);
|
String serverHmac = CodecUtils.encodeBase64(hmac);
|
||||||
if (!Objects.equals(req.getHmac(), serverHmac)) {
|
if (!Objects.equals(req.getHmac(), serverHmac)) {
|
||||||
log.warn("appKey: {}, req hmac: {}, server hmac: {}", appKey, req.getHmac(), serverHmac);
|
log.warn("appKey: {}, req hmac: {}, server hmac: {}", appKey, req.getHmac(), serverHmac);
|
||||||
throw new IllegalArgumentException("应用认证失败");
|
throw new IllegalArgumentException("应用认证失败");
|
||||||
@ -86,22 +79,6 @@ public class AppLoginService {
|
|||||||
.compact();
|
.compact();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AppTokenResp getAppTokenForTest(@Valid AppTokenReq req) {
|
|
||||||
|
|
||||||
// Long random = req.getRandom();
|
|
||||||
// long now = System.currentTimeMillis();
|
|
||||||
// Assert.isTrue(now - random <= 5 * 60 * 1000, "请求已超时");
|
|
||||||
Application application = applicationMapper.selectByAppKey(req.getAppKey());
|
|
||||||
Assert.isTrue(EnableStatus.ENABLED.getCode().equals(application.getStatus()), "此应用已停用");
|
|
||||||
if (!Objects.equals(req.getHmac(), application.getAppSecret())) {
|
|
||||||
log.warn("appKey: {}, req hmac: {},", req.getAppKey(), req.getHmac());
|
|
||||||
throw new IllegalArgumentException("应用认证失败");
|
|
||||||
}
|
|
||||||
AppTokenResp resp = new AppTokenResp();
|
|
||||||
resp.setToken(genToken(application));
|
|
||||||
return resp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public AppUser verifyToken(String token) {
|
public AppUser verifyToken(String token) {
|
||||||
Claims claims = Jwts.parser()
|
Claims claims = Jwts.parser()
|
||||||
|
@ -1,27 +1,12 @@
|
|||||||
package com.sunyard.chsm.service;
|
package com.sunyard.chsm.service;
|
||||||
|
|
||||||
import com.sunyard.chsm.auth.UserContext;
|
import com.sunyard.chsm.auth.UserContext;
|
||||||
import com.sunyard.chsm.enums.AlgMode;
|
import com.sunyard.chsm.enums.*;
|
||||||
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.KeyInfoMapper;
|
||||||
import com.sunyard.chsm.mapper.SpKeyRecordMapper;
|
import com.sunyard.chsm.mapper.SpKeyRecordMapper;
|
||||||
import com.sunyard.chsm.model.entity.KeyInfo;
|
import com.sunyard.chsm.model.entity.KeyInfo;
|
||||||
import com.sunyard.chsm.model.entity.KeyRecord;
|
import com.sunyard.chsm.model.entity.KeyRecord;
|
||||||
import com.sunyard.chsm.param.SymDecryptReq;
|
import com.sunyard.chsm.param.*;
|
||||||
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.SymHmacReq;
|
|
||||||
import com.sunyard.chsm.param.SymHmacResp;
|
|
||||||
import com.sunyard.chsm.param.SymMacCheckReq;
|
|
||||||
import com.sunyard.chsm.param.SymMacReq;
|
|
||||||
import com.sunyard.chsm.param.SymMacResp;
|
|
||||||
import com.sunyard.chsm.param.VerifyResp;
|
|
||||||
import com.sunyard.chsm.sdf.SdfApiService;
|
import com.sunyard.chsm.sdf.SdfApiService;
|
||||||
import com.sunyard.chsm.sdf.context.AlgId;
|
import com.sunyard.chsm.sdf.context.AlgId;
|
||||||
import com.sunyard.chsm.utils.CodecUtils;
|
import com.sunyard.chsm.utils.CodecUtils;
|
||||||
@ -55,6 +40,7 @@ public class SymKeyService {
|
|||||||
iv = bytes;
|
iv = bytes;
|
||||||
}
|
}
|
||||||
byte[] plain = CodecUtils.decodeBase64(req.getPlainData());
|
byte[] plain = CodecUtils.decodeBase64(req.getPlainData());
|
||||||
|
Assert.isTrue(plain.length <= 7680, "明文长度最大支持7680");
|
||||||
KeyInfo keyInfo = checkKey(req.getKeyId(), KeyUsage.ENCRYPT_DECRYPT);
|
KeyInfo keyInfo = checkKey(req.getKeyId(), KeyUsage.ENCRYPT_DECRYPT);
|
||||||
KeyAlg keyAlg = KeyAlg.of(keyInfo.getKeyAlg());
|
KeyAlg keyAlg = KeyAlg.of(keyInfo.getKeyAlg());
|
||||||
Assert.notNull(keyAlg, "数据异常");
|
Assert.notNull(keyAlg, "数据异常");
|
||||||
@ -98,6 +84,7 @@ public class SymKeyService {
|
|||||||
iv = bytes;
|
iv = bytes;
|
||||||
}
|
}
|
||||||
byte[] cipher = CodecUtils.decodeBase64(req.getCipherData());
|
byte[] cipher = CodecUtils.decodeBase64(req.getCipherData());
|
||||||
|
Assert.isTrue(cipher.length <= 7696, "密文长度最大支持7696");
|
||||||
KeyInfo keyInfo = checkKey(req.getKeyId(), KeyUsage.ENCRYPT_DECRYPT);
|
KeyInfo keyInfo = checkKey(req.getKeyId(), KeyUsage.ENCRYPT_DECRYPT);
|
||||||
KeyAlg keyAlg = KeyAlg.of(keyInfo.getKeyAlg());
|
KeyAlg keyAlg = KeyAlg.of(keyInfo.getKeyAlg());
|
||||||
Assert.notNull(keyAlg, "数据异常");
|
Assert.notNull(keyAlg, "数据异常");
|
||||||
|
@ -6,7 +6,9 @@ import com.fasterxml.jackson.databind.JsonNode;
|
|||||||
import com.sunyard.chsm.model.R;
|
import com.sunyard.chsm.model.R;
|
||||||
import com.sunyard.chsm.param.AppTokenReq;
|
import com.sunyard.chsm.param.AppTokenReq;
|
||||||
import com.sunyard.chsm.param.AppTokenResp;
|
import com.sunyard.chsm.param.AppTokenResp;
|
||||||
|
import com.sunyard.chsm.utils.CodecUtils;
|
||||||
import com.sunyard.chsm.utils.JsonUtils;
|
import com.sunyard.chsm.utils.JsonUtils;
|
||||||
|
import com.sunyard.chsm.utils.gm.BCSM3Utils;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
@ -27,17 +29,18 @@ public abstract class BaseTest {
|
|||||||
protected static final String keyTemplate = "sym-sm4-001";
|
protected static final String keyTemplate = "sym-sm4-001";
|
||||||
protected static final String ak = "216205d408130d83d13c5072305b8b65";
|
protected static final String ak = "216205d408130d83d13c5072305b8b65";
|
||||||
protected static final String sk = "ae64515d1d5adec2cc6ae8726d0c1bbc";
|
protected static final String sk = "ae64515d1d5adec2cc6ae8726d0c1bbc";
|
||||||
protected static final String server = "http://172.16.18.46:8900";
|
protected static final String server = "http://127.0.0.1:8900";
|
||||||
protected static final RestTemplate restTemplate;
|
protected static final RestTemplate restTemplate;
|
||||||
protected static final String token;
|
protected static final String token;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
AppTokenReq req = new AppTokenReq();
|
AppTokenReq req = new AppTokenReq();
|
||||||
req.setAppKey(ak);
|
req.setAppKey(ak);
|
||||||
req.setHmac(sk);
|
req.setTimestamp(System.currentTimeMillis());
|
||||||
req.setRandom(System.currentTimeMillis());
|
byte[] hmac = BCSM3Utils.hmac(sk.getBytes(), (ak + req.getTimestamp() + sk).getBytes());
|
||||||
|
req.setHmac(CodecUtils.encodeBase64(hmac));
|
||||||
|
|
||||||
RequestEntity<byte[]> request = RequestEntity.post(server + "/appUser/getAppTokenTest")
|
RequestEntity<byte[]> request = RequestEntity.post(server + "/appUser/getAppToken")
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.body(JsonUtils.toJsonBytes(req));
|
.body(JsonUtils.toJsonBytes(req));
|
||||||
ResponseEntity<String> response = new RestTemplate().exchange(request, String.class);
|
ResponseEntity<String> response = new RestTemplate().exchange(request, String.class);
|
||||||
@ -70,7 +73,7 @@ public abstract class BaseTest {
|
|||||||
}
|
}
|
||||||
JsonNode result = jsonNode.get("result");
|
JsonNode result = jsonNode.get("result");
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
JsonParser returnJsonParser = JsonUtils.objectMapper().treeAsTokens(result);
|
JsonParser returnJsonParser = JsonUtils.objectMapper().treeAsTokens(result);
|
||||||
return JsonUtils.objectMapper().readValue(returnJsonParser, tClass);
|
return JsonUtils.objectMapper().readValue(returnJsonParser, tClass);
|
||||||
|
62
chsm-web-server/src/test/java/api/HashTest.java
Normal file
62
chsm-web-server/src/test/java/api/HashTest.java
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
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;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liulu
|
||||||
|
* @since 2024/12/25
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class HashTest extends BaseTest {
|
||||||
|
|
||||||
|
private static final byte[] plain = new byte[1024 * 7];
|
||||||
|
|
||||||
|
static {
|
||||||
|
Arrays.fill(plain, (byte) 0x04);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSingleHash() {
|
||||||
|
HashReq hashReq = new HashReq();
|
||||||
|
hashReq.setPlainData(CodecUtils.encodeBase64(plain));
|
||||||
|
HashResp hashResp = execute("/hash", hashReq, HashResp.class);
|
||||||
|
log.info("hash: {}", hashResp.getHash());
|
||||||
|
|
||||||
|
byte[] bcHash = BCSM3Utils.hash(plain);
|
||||||
|
log.info("bc hash: {}", CodecUtils.encodeBase64(bcHash));
|
||||||
|
Assertions.assertEquals(CodecUtils.encodeBase64(bcHash), hashResp.getHash());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultiHash() {
|
||||||
|
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++) {
|
||||||
|
hashResp = execute("/multi/package/hash/update", hashReq, HashResp.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
hashResp = execute("/multi/package/hash/finish", hashReq, HashResp.class);
|
||||||
|
log.info("hash: {}", hashResp);
|
||||||
|
|
||||||
|
|
||||||
|
byte[] bcHash = BCSM3Utils.hash(LangUtils.merge(plain, plain));
|
||||||
|
log.info("bc hash: {}", CodecUtils.encodeBase64(bcHash));
|
||||||
|
Assertions.assertEquals(CodecUtils.encodeBase64(bcHash), hashResp.getHash());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,12 +1,7 @@
|
|||||||
package api;
|
package api;
|
||||||
|
|
||||||
import com.sunyard.chsm.enums.AlgMode;
|
import com.sunyard.chsm.enums.AlgMode;
|
||||||
import com.sunyard.chsm.param.KeyCreateReq;
|
import com.sunyard.chsm.param.*;
|
||||||
import com.sunyard.chsm.param.KeyManageReq;
|
|
||||||
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.utils.CodecUtils;
|
import com.sunyard.chsm.utils.CodecUtils;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
@ -15,6 +10,7 @@ import org.junit.jupiter.api.BeforeAll;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,12 +20,13 @@ import java.util.Collections;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class SymKeyTest extends BaseTest {
|
public class SymKeyTest extends BaseTest {
|
||||||
|
|
||||||
private static final String plain = "hjsu234127qikqwndqqw13412as324";
|
private static final byte[] plain = new byte[1024 * 7];
|
||||||
private final static byte[] iv = "ghwikdhj1234713v".getBytes();
|
private final static byte[] iv = "ghwikdhj1234713v".getBytes();
|
||||||
private static Long keyId;
|
private static Long keyId;
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void beforeAll() {
|
public static void beforeAll() {
|
||||||
|
Arrays.fill(plain, (byte) 0x04);
|
||||||
keyId = execute("/key/gen", KeyCreateReq.builder().keyTemplateCode(keyTemplate).genNumber(1).build(), Long.class);
|
keyId = execute("/key/gen", KeyCreateReq.builder().keyTemplateCode(keyTemplate).genNumber(1).build(), Long.class);
|
||||||
Assertions.assertTrue(keyId > 0);
|
Assertions.assertTrue(keyId > 0);
|
||||||
}
|
}
|
||||||
@ -47,7 +44,7 @@ public class SymKeyTest extends BaseTest {
|
|||||||
|
|
||||||
SymEncryptReq symEncryptReq = new SymEncryptReq();
|
SymEncryptReq symEncryptReq = new SymEncryptReq();
|
||||||
symEncryptReq.setKeyId(keyId);
|
symEncryptReq.setKeyId(keyId);
|
||||||
symEncryptReq.setPlainData(CodecUtils.encodeBase64(plain.getBytes()));
|
symEncryptReq.setPlainData(CodecUtils.encodeBase64(plain));
|
||||||
symEncryptReq.setIv(CodecUtils.encodeBase64(iv));
|
symEncryptReq.setIv(CodecUtils.encodeBase64(iv));
|
||||||
symEncryptReq.setMode(AlgMode.CBC);
|
symEncryptReq.setMode(AlgMode.CBC);
|
||||||
|
|
||||||
@ -56,7 +53,7 @@ public class SymKeyTest extends BaseTest {
|
|||||||
Assertions.assertNotNull(symEncryptResp);
|
Assertions.assertNotNull(symEncryptResp);
|
||||||
Assertions.assertTrue(StringUtils.hasText(symEncryptResp.getKeyIndex()));
|
Assertions.assertTrue(StringUtils.hasText(symEncryptResp.getKeyIndex()));
|
||||||
byte[] cipherData = CodecUtils.decodeBase64(symEncryptResp.getCipherData());
|
byte[] cipherData = CodecUtils.decodeBase64(symEncryptResp.getCipherData());
|
||||||
Assertions.assertEquals(32, cipherData.length);
|
// Assertions.assertEquals(32, cipherData.length);
|
||||||
|
|
||||||
SymDecryptReq decryptReq = new SymDecryptReq();
|
SymDecryptReq decryptReq = new SymDecryptReq();
|
||||||
decryptReq.setKeyId(keyId);
|
decryptReq.setKeyId(keyId);
|
||||||
@ -65,10 +62,10 @@ public class SymKeyTest extends BaseTest {
|
|||||||
decryptReq.setMode(AlgMode.CBC);
|
decryptReq.setMode(AlgMode.CBC);
|
||||||
decryptReq.setCipherData(symEncryptResp.getCipherData());
|
decryptReq.setCipherData(symEncryptResp.getCipherData());
|
||||||
SymDecryptResp decryptResp = execute("/sym/decrypt", decryptReq, SymDecryptResp.class);
|
SymDecryptResp decryptResp = execute("/sym/decrypt", decryptReq, SymDecryptResp.class);
|
||||||
String calPlain = new String(CodecUtils.decodeBase64(decryptResp.getPlainData()));
|
byte[] calPlain = CodecUtils.decodeBase64(decryptResp.getPlainData());
|
||||||
log.info("SymDecryptResp: {}, {}", calPlain, decryptResp);
|
log.info("SymDecryptResp: {}, {}", calPlain, decryptResp);
|
||||||
Assertions.assertNotNull(decryptResp);
|
Assertions.assertNotNull(decryptResp);
|
||||||
Assertions.assertEquals(plain, calPlain);
|
Assertions.assertArrayEquals(plain, calPlain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user