sdf
This commit is contained in:
parent
48fb1db044
commit
9e8b3fa5c8
@ -12,6 +12,8 @@ public interface ParamConfKeyConstant {
|
||||
*/
|
||||
String IP_WHITELIST_SWITCH = "ipWhitelistSwitch";
|
||||
|
||||
String TMK_INIT = "tmk_init";
|
||||
|
||||
/**
|
||||
* 通讯超时时间
|
||||
*/
|
||||
@ -105,18 +107,20 @@ public interface ParamConfKeyConstant {
|
||||
/**
|
||||
* 系统初始化配置文件路劲
|
||||
*/
|
||||
String SYS_PARAM_CONFIG_FILE_PATH = System.getProperty("user.dir") + "/config/sysParam.config.json";
|
||||
String SYS_PARAM_CONFIG_FILE_PATH = System.getProperty("user.dir") + "/config/sysParam.config.json";
|
||||
|
||||
/**
|
||||
* 调试模式开关枚举
|
||||
*/
|
||||
enum SYS_DEBUG_SWITCH_VALUE{
|
||||
enum SYS_DEBUG_SWITCH_VALUE {
|
||||
DEV("dev"), CONFIG("config"), PRODUCT("product");
|
||||
private String value;
|
||||
private SYS_DEBUG_SWITCH_VALUE(String value){
|
||||
|
||||
private SYS_DEBUG_SWITCH_VALUE(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
public String getValue(){
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,14 @@
|
||||
package com.sunyard.chsm.enums;
|
||||
|
||||
/**
|
||||
* @author liulu
|
||||
* @since 2024/12/7
|
||||
*/
|
||||
public enum TmkStatusEnum {
|
||||
|
||||
device_error,
|
||||
key_error,
|
||||
available,
|
||||
finished,
|
||||
|
||||
}
|
@ -13,7 +13,6 @@ import com.sunyard.chsm.sdf.model.SDF_DeviceInfo;
|
||||
import com.sunyard.chsm.sdf.util.LangUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Map;
|
||||
@ -35,6 +34,7 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
|
||||
protected final SdfLibrary sdfLibrary;
|
||||
|
||||
protected abstract int getAlgId(AlgId alg);
|
||||
protected abstract void checkRes(int res);
|
||||
|
||||
@Override
|
||||
public String openDevice() {
|
||||
@ -126,7 +126,6 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
|
||||
byte[] pubKey = new byte[132];
|
||||
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||
sdfLibrary.SDF_ExportEncPublicKey_ECC(hSessionHandle, uiKeyIndex, pubKey);
|
||||
log.info("sdf pubkey: {}", Hex.toHexString(pubKey));
|
||||
return EccPubKey.fromBytes(pubKey);
|
||||
}
|
||||
|
||||
@ -139,7 +138,6 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
|
||||
public boolean getPrivateKeyAccessRight(String sessionHandle, int uiKeyIndex, byte[] pucPassword) {
|
||||
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||
int res = sdfLibrary.SDF_GetPrivateKeyAccessRight(hSessionHandle, uiKeyIndex, pucPassword, pucPassword.length);
|
||||
log.info("SDF_GetPrivateKeyAccessRight: {}, {}", res, Integer.toHexString(res));
|
||||
return res == 0;
|
||||
}
|
||||
|
||||
@ -148,8 +146,7 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
|
||||
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||
PointerByReference phKeyHandle = new PointerByReference();
|
||||
|
||||
int res = sdfLibrary.SDF_ImportKeyWithISK_ECC(hSessionHandle, uiIskIndex, eccCipher.toSdfData(), phKeyHandle);
|
||||
log.info("SDF_ImportKeyWithISK_ECC: {}, {}", res, Integer.toHexString(res));
|
||||
sdfLibrary.SDF_ImportKeyWithISK_ECC(hSessionHandle, uiIskIndex, eccCipher.toSdfData(), phKeyHandle);
|
||||
String key = UUID.randomUUID().toString();
|
||||
KEY_HANDLE_CONTEXT.put(key, phKeyHandle.getValue());
|
||||
return key;
|
||||
@ -176,9 +173,8 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
|
||||
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||
|
||||
byte[] pucEncDateOut = new byte[164 + pucEncDateIn.getL()];
|
||||
int res = sdfLibrary.SDF_ExchangeDigitEnvelopeBaseOnECC(hSessionHandle, uiKeyIndex, getAlgId(AlgId.SGD_SM2_1),
|
||||
sdfLibrary.SDF_ExchangeDigitEnvelopeBaseOnECC(hSessionHandle, uiKeyIndex, getAlgId(AlgId.SGD_SM2_1),
|
||||
pubKey.toSdfData(), pucEncDateIn.toSdfData(), pucEncDateOut);
|
||||
log.info("SDF_ExchangeDigitEnvelopeBaseOnECC: {}, {}", res, Integer.toHexString(res));
|
||||
return EccCipher.fromBytes(pucEncDateOut);
|
||||
}
|
||||
|
||||
@ -187,7 +183,6 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
|
||||
byte[] encData = new byte[128 + 32 + 4 + pucData.length];
|
||||
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||
sdfLibrary.SDF_ExternalEncrypt_ECC(hSessionHandle, getAlgId(AlgId.SGD_SM2_3), pubKey.toSdfData(), pucData, pucData.length, encData);
|
||||
log.info("sdfEncryptECC: {}", Hex.toHexString(encData));
|
||||
return EccCipher.fromBytes(encData);
|
||||
}
|
||||
|
||||
|
@ -31,4 +31,7 @@ public class SdfApiAdapterFactory {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -3,9 +3,17 @@ package com.sunyard.chsm.sdf.adapter;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.ptr.PointerByReference;
|
||||
import com.sunyard.chsm.sdf.context.AlgId;
|
||||
import com.sunyard.chsm.sdf.context.SdrCode;
|
||||
import com.sunyard.chsm.sdf.context.SunyardAlgId;
|
||||
import com.sunyard.chsm.sdf.lib.SdfLibrary;
|
||||
import com.sunyard.chsm.sdf.lib.SunyardSdfLibrary;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -14,6 +22,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* @author liulu
|
||||
* @since 2024/11/4
|
||||
*/
|
||||
@Slf4j
|
||||
public class SunyardJnaSdfAdaptor extends JnaSdfAdaptor {
|
||||
|
||||
private static final Map<String, SunyardSdfLibrary> SDF_LIB_MAP = new ConcurrentHashMap<>();
|
||||
@ -37,7 +46,30 @@ public class SunyardJnaSdfAdaptor extends JnaSdfAdaptor {
|
||||
}
|
||||
|
||||
public SunyardJnaSdfAdaptor(String ip, int port, String libName, int connTimeout, int dealTimeout) {
|
||||
super(SDF_LIB_MAP.computeIfAbsent(libName, k -> Native.load(libName, SunyardSdfLibrary.class)));
|
||||
super((SdfLibrary) Proxy.newProxyInstance(ClassUtils.getDefaultClassLoader(),
|
||||
new Class[]{SdfLibrary.class},
|
||||
new InvocationHandler() {
|
||||
private final SunyardSdfLibrary sunyardSdfLibrary;
|
||||
|
||||
{
|
||||
sunyardSdfLibrary = SDF_LIB_MAP.computeIfAbsent(libName, k -> Native.load(libName, SunyardSdfLibrary.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
Object res = method.invoke(sunyardSdfLibrary, args);
|
||||
if (method.getName().startsWith("SDF_") && res instanceof Integer) {
|
||||
int resInt = (Integer) res;
|
||||
if (resInt != SdrCode.SDR_OK.getCode()) {
|
||||
log.warn("调用异常: {}, 返回值: {} -{}", method.getName(), Integer.toHexString(resInt), resInt);
|
||||
SdrCode sdrCode = SdrCode.of((Integer) res);
|
||||
throw new IllegalArgumentException(sdrCode != null ? sdrCode.getMsg() : "调用sdf接口异常: " + Integer.toHexString(resInt));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
));
|
||||
this.ip = ip;
|
||||
this.port = port;
|
||||
this.connTimeout = connTimeout;
|
||||
@ -59,6 +91,11 @@ public class SunyardJnaSdfAdaptor extends JnaSdfAdaptor {
|
||||
return SunyardAlgId.valueOf(alg.name()).getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkRes(int res) {
|
||||
|
||||
}
|
||||
|
||||
public static byte[] safeStringBytes(String str) {
|
||||
if (null == str || str.isEmpty()) {
|
||||
return new byte[]{0x30};
|
||||
@ -69,4 +106,15 @@ public class SunyardJnaSdfAdaptor extends JnaSdfAdaptor {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public static class CheckProxy implements InvocationHandler {
|
||||
private final SdfLibrary sdfLibrary;
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,90 @@
|
||||
package com.sunyard.chsm.sdf.context;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author liulu
|
||||
* @since 2024/12/7
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum SdrCode {
|
||||
|
||||
SDR_OK(0x0, "操作成功"),
|
||||
SDR_BASE(0x01000000, "错误码基础值"),
|
||||
|
||||
SDR_UNKNOWER(SDR_BASE.code + 0x00000001, "未知错误"),
|
||||
SDR_NOTSUPPORT(SDR_BASE.code + 0x00000002, "不支持的接口调用"),
|
||||
SDR_COMMFAIL(SDR_BASE.code + 0x00000003, "与设备通信失败"),
|
||||
SDR_HARDFAIL(SDR_BASE.code + 0x00000004, "运算模块无响应"),
|
||||
SDR_OPENDEVICE(SDR_BASE.code + 0x00000005, "打开设备失败"),
|
||||
SDR_OPENSESSION(SDR_BASE.code + 0x00000006, "创建会话失败"),
|
||||
SDR_PARDENY(SDR_BASE.code + 0x00000007, "无私钥使用权限"),
|
||||
SDR_KEYNOTEXIST(SDR_BASE.code + 0x00000008, "不存在的密钥调用"),
|
||||
SDR_ALGNOTSUPPORT(SDR_BASE.code + 0x00000009, "不支持的算法调用"),
|
||||
SDR_ALGMODNOTSUPPORT(SDR_BASE.code + 0x0000000A, "不支持的算法模式调用"),
|
||||
SDR_PKOPERR(SDR_BASE.code + 0x0000000B, "公钥运算失败"),
|
||||
SDR_SKOPERR(SDR_BASE.code + 0x0000000C, "私钥运算失败"),
|
||||
SDR_SIGNERR(SDR_BASE.code + 0x0000000D, "签名运算失败"),
|
||||
SDR_VERIFYERR(SDR_BASE.code + 0x0000000E, "验证签名失败"),
|
||||
SDR_SYMOPERR(SDR_BASE.code + 0x0000000F, "对称算法运算失败"),
|
||||
SDR_STEPERR(SDR_BASE.code + 0x00000010, "多步运算步骤错误"),
|
||||
SDR_FILESIZEERR(SDR_BASE.code + 0x00000011, "文件长度超出限制"),
|
||||
SDR_FILENOEXIST(SDR_BASE.code + 0x00000012, "指定的文件不存在"),
|
||||
SDR_FILEOFSERR(SDR_BASE.code + 0x00000013, "文件起始位置错误"),
|
||||
SDR_KEYTYPEERR(SDR_BASE.code + 0x00000014, "密钥类型错误"),
|
||||
SDR_KEYERR(SDR_BASE.code + 0x00000015, "密钥错误"),
|
||||
SDR_ENCDATAERR(SDR_BASE.code + 0x00000016, "ECC加密数据错误"),
|
||||
SDR_RANDERR(SDR_BASE.code + 0x00000017, "随机数产生失败"),
|
||||
SDR_PRKERR(SDR_BASE.code + 0x00000018, "私钥使用权限获取失败"),
|
||||
SDR_MACERR(SDR_BASE.code + 0x00000019, "MAC运算失败"),
|
||||
SDR_FILEEXISTS(SDR_BASE.code + 0x0000001A, "指定文件已存在"),
|
||||
SDR_FILEWERR(SDR_BASE.code + 0x0000001B, "文件写入失败"),
|
||||
SDR_NOBUFFER(SDR_BASE.code + 0x0000001C, "存储空间不足"),
|
||||
SDR_INARGERR(SDR_BASE.code + 0x0000001D, "输入参数错误"),
|
||||
SDR_OUTARGERR(SDR_BASE.code + 0x0000001E, "输出参数错误"),
|
||||
SDR_FILERDERR(SDR_BASE.code + 0x0000001F, "文件读取失败"),
|
||||
SDR_CONSULTERR(SDR_BASE.code + 0x00000020, "密钥协商错误"),
|
||||
SDR_LEVELERR(SDR_BASE.code + 0x00000021, "权限不足"),
|
||||
SDR_INDEXERR(SDR_BASE.code + 0x00000022, "索引错误"),
|
||||
SDR_KEYLENERR(SDR_BASE.code + 0x00000023, "密钥长度错误"),
|
||||
SDR_DATALENERR(SDR_BASE.code + 0x00000024, "数据长度错误"),
|
||||
SDR_RIGHTLENERR(SDR_BASE.code + 0x00000025, "私钥授权码长度错误"),
|
||||
SDR_RIGHTERR(SDR_BASE.code + 0x00000026, "私钥授权码错误"),
|
||||
SDR_FILEEMPTYERR(SDR_BASE.code + 0x00000027, "文件为空"),
|
||||
SDR_ERRSTATE(SDR_BASE.code + 0x00000028, "处于错误状态"),
|
||||
SDR_INITSTATE(SDR_BASE.code + 0x00000029, "处于初始状态"),
|
||||
SDR_RPRKERR(SDR_BASE.code + 0x0000002A, "私钥使用权限释放失败"),
|
||||
SDR_SIGNPRKERR(SDR_BASE.code + 0x0000002B, "签名公钥导出失败"),
|
||||
SDR_ENCPRKERR(SDR_BASE.code + 0x0000002C, "加密公钥导出失败"),
|
||||
SDR_KPERR(SDR_BASE.code + 0x0000002D, "密钥对生成失败"),
|
||||
SDR_GENERATEKEYERR(SDR_BASE.code + 0x0000002E, "会话密钥生成失败"),
|
||||
SDR_IMKEYERR(SDR_BASE.code + 0x0000002F, "导入密钥失败"),
|
||||
SDR_INTOEXERR(SDR_BASE.code + 0x00000030, "数字信封转换失败"),
|
||||
|
||||
/* API新增错误码 */
|
||||
SRD_DEV_FILE_CONFIG_ERR(SDR_BASE.code + 0x00000040, "配置文件信息错误(请检查配置文件的信息是否有误)"),
|
||||
SDR_DEVICEHANDLE_INVAILD(SDR_BASE.code + 0x00000041, "设备句柄错误(请检查句柄是否初始化或已经被释放)"),
|
||||
SDR_SESSIONHANLE_INVAILD(SDR_BASE.code + 0x00000042, "会话句柄错误(请检查句柄是否初始化或已经被释放)"),
|
||||
SDR_KEYHANLE_INVAILD(SDR_BASE.code + 0x00000043, "密钥句柄错误(请检查句柄是否初始化或已经被释放)"),
|
||||
SDR_AGREEMENTHANLE_INVAILD(SDR_BASE.code + 0x00000044, "协商句柄错误(请检查句柄是否初始化或已经被释放)"),
|
||||
SDR_UNKNOWN_HANDLE(SDR_BASE.code + 0x00000045, "未知的句柄"),
|
||||
SDR_NO_AVAILABL_DEVICE(SDR_BASE.code + 0x00000046, "此设备无法连接, 请检查IP和端口是否正确"),
|
||||
;
|
||||
|
||||
private final int code;
|
||||
private final String msg;
|
||||
|
||||
public static SdrCode of(int code) {
|
||||
|
||||
return Arrays.stream(SdrCode.values())
|
||||
.filter(it -> Objects.equals(it.code, code))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
}
|
@ -8,6 +8,7 @@ import com.sunyard.chsm.dto.DeviceDTO;
|
||||
import com.sunyard.chsm.dto.TmkStatus;
|
||||
import com.sunyard.chsm.enums.ManufacturerEnum;
|
||||
import com.sunyard.chsm.enums.ManufacturerModelEnum;
|
||||
import com.sunyard.chsm.enums.TmkStatusEnum;
|
||||
import com.sunyard.chsm.mapper.ParamConfMapper;
|
||||
import com.sunyard.chsm.mapper.SpDeviceMapper;
|
||||
import com.sunyard.chsm.mapper.TmkInfoMapper;
|
||||
@ -15,12 +16,15 @@ import com.sunyard.chsm.model.entity.Device;
|
||||
import com.sunyard.chsm.model.entity.ParamConf;
|
||||
import com.sunyard.chsm.model.entity.TmkInfo;
|
||||
import com.sunyard.chsm.sdf.adapter.BcSdfApiAdaptor;
|
||||
import com.sunyard.chsm.sdf.adapter.SdfApiAdapter;
|
||||
import com.sunyard.chsm.sdf.adapter.SdfApiAdapterFactory;
|
||||
import com.sunyard.chsm.sdf.model.EccCipher;
|
||||
import com.sunyard.chsm.sdf.model.EccPubKey;
|
||||
import com.sunyard.chsm.service.DeviceService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
@ -146,6 +150,10 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
device.setWeight(1);
|
||||
device.setCreateTime(LocalDateTime.now());
|
||||
|
||||
Pair<String, String> pair = checkDeviceSdf(save);
|
||||
device.setTmkStatus(TmkStatusEnum.available.name());
|
||||
device.setPubKey(pair.getFirst());
|
||||
|
||||
spDeviceMapper.insert(device);
|
||||
return device.getId();
|
||||
}
|
||||
@ -158,6 +166,22 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
Assert.isNull(exist, "设备IP和端口已存在");
|
||||
}
|
||||
|
||||
private Pair<String, String> checkDeviceSdf(DeviceDTO.DeviceSave save) {
|
||||
SdfApiAdapter sdfApiAdapter = SdfApiAdapterFactory.newInstance(save.getManufacturerModel(), save.getServiceIp(), save.getServicePort());
|
||||
|
||||
String hd = sdfApiAdapter.openDevice();
|
||||
String hs = null;
|
||||
try {
|
||||
hs = sdfApiAdapter.openSession(hd);
|
||||
EccPubKey eccPubKey = sdfApiAdapter.exportEncPublicKeyECC(hs, save.getEncKeyIdx());
|
||||
sdfApiAdapter.getPrivateKeyAccessRight(hs, save.getEncKeyIdx(), save.getAccessCredentials().getBytes());
|
||||
return Pair.of(eccPubKey.getPubKeyHex(), "");
|
||||
} finally {
|
||||
Optional.ofNullable(hs).ifPresent(sdfApiAdapter::closeSession);
|
||||
sdfApiAdapter.closeDevice(hd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(DeviceDTO.DeviceSave update) {
|
||||
Assert.notNull(update.getId(), "id不能为空");
|
||||
@ -167,8 +191,9 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
if (!Objects.equals(exist.getName(), update.getName())) {
|
||||
checkName(update.getName());
|
||||
}
|
||||
if (!Objects.equals(exist.getServiceIp(), update.getServiceIp())
|
||||
|| !Objects.equals(exist.getServicePort(), update.getServicePort())) {
|
||||
boolean ipChanged = !Objects.equals(exist.getServiceIp(), update.getServiceIp())
|
||||
|| !Objects.equals(exist.getServicePort(), update.getServicePort());
|
||||
if (ipChanged) {
|
||||
checkIpPort(update.getServiceIp(), update.getServicePort());
|
||||
}
|
||||
|
||||
@ -176,6 +201,13 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
BeanUtils.copyProperties(update, up);
|
||||
up.setUpdateTime(LocalDateTime.now());
|
||||
|
||||
if (ipChanged
|
||||
|| !Objects.equals(exist.getEncKeyIdx(), update.getEncKeyIdx())
|
||||
|| !Objects.equals(exist.getAccessCredentials(), update.getAccessCredentials())) {
|
||||
Pair<String, String> pair = checkDeviceSdf(update);
|
||||
up.setPubKey(pair.getFirst());
|
||||
}
|
||||
|
||||
spDeviceMapper.updateById(up);
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ public class AuthHandler implements HandlerInterceptor, InitializingBean {
|
||||
Collectors.mapping(CryptoServiceApi::getCryptoServiceId, Collectors.toList())));
|
||||
});
|
||||
if (codeServiceMap == null || !codeServiceMap.containsKey(code)) {
|
||||
log.warn("app: {}-{}, 无权访问: {}", user.getAppId(), user.getName(), request.getRequestURI());
|
||||
log.warn("app: {}-{}, 无权访问: {} - {}", user.getAppId(), user.getName(), code, request.getRequestURI());
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
response.getOutputStream().write(JsonUtils.toJsonBytes(R.error("无权访问")));
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user