sdf api
This commit is contained in:
parent
63fce073dd
commit
3dc061907f
@ -15,6 +15,7 @@ import java.util.Objects;
|
||||
public enum Padding {
|
||||
NOPadding("NoPadding", "NoPadding"),
|
||||
PCKS5Padding( "PKCS5Padding", "PKCS5Padding"),
|
||||
PCKS7Padding( "PKCS7Padding", "PKCS7Padding"),
|
||||
;
|
||||
|
||||
private final String code;
|
||||
|
@ -5,6 +5,7 @@ import com.sunyard.chsm.enums.AlgMode;
|
||||
import com.sunyard.chsm.enums.KeyAlg;
|
||||
import com.sunyard.chsm.enums.KeyCategory;
|
||||
import com.sunyard.chsm.enums.Padding;
|
||||
import com.sunyard.chsm.sdf.context.AlgId;
|
||||
import com.sunyard.chsm.sdf.model.EccKey;
|
||||
import com.sunyard.chsm.sdf.util.LangUtils;
|
||||
import com.sunyard.chsm.utils.gm.BCSM2Utils;
|
||||
@ -21,7 +22,11 @@ import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.security.*;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
|
||||
/**
|
||||
@ -86,12 +91,22 @@ public class BCSdfApiService extends AbstractSdfApiService {
|
||||
return symCalc(Cipher.ENCRYPT_MODE, alg, mode, padding, key, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] symEncrypt(AlgId alg, byte[] key, byte[] iv, byte[] data) {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] symDecrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
||||
return symCalc(Cipher.DECRYPT_MODE, alg, mode, padding, key, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] symDecrypt(AlgId alg, byte[] key, byte[] iv, byte[] data) {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 对称加解密的统一实现
|
||||
|
@ -4,6 +4,7 @@ package com.sunyard.chsm.sdf;
|
||||
import com.sunyard.chsm.enums.AlgMode;
|
||||
import com.sunyard.chsm.enums.KeyAlg;
|
||||
import com.sunyard.chsm.enums.Padding;
|
||||
import com.sunyard.chsm.sdf.context.AlgId;
|
||||
import com.sunyard.chsm.sdf.model.EccKey;
|
||||
|
||||
|
||||
@ -23,41 +24,48 @@ public interface SdfApiService {
|
||||
byte[] generateRandom(int len);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 生成对称密钥
|
||||
* @param alg 算法,只支持对称算法
|
||||
*
|
||||
* @param alg 算法,只支持对称算法
|
||||
* @param keyLen 密钥长度(bit),只针对密钥长度可变的算法。
|
||||
* 禁止传 null
|
||||
* @return 对称密钥
|
||||
*/
|
||||
byte[] genSymKey(KeyAlg alg, Integer keyLen);
|
||||
|
||||
byte[] genSymKey(KeyAlg alg);
|
||||
|
||||
|
||||
/**
|
||||
* 对称加密
|
||||
* @param alg 算法,只支持对称算法
|
||||
* @param mode 轮模式
|
||||
*
|
||||
* @param alg 算法,只支持对称算法
|
||||
* @param mode 轮模式
|
||||
* @param padding 填充模式
|
||||
* @param key 密钥值,明文
|
||||
* @param data 原始数据
|
||||
* @param key 密钥值,明文
|
||||
* @param data 原始数据
|
||||
*/
|
||||
byte[] symEncrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data);
|
||||
|
||||
byte[] symEncrypt(KeyAlg alg, byte[] key, byte[] data);
|
||||
|
||||
byte[] symEncrypt(AlgId alg, byte[] key, byte[] iv, byte[] data);
|
||||
|
||||
/**
|
||||
* 对称解密
|
||||
* @param alg 算法,只支持对称算法
|
||||
* @param key 密钥值,明文
|
||||
* @param mode 轮模式
|
||||
*
|
||||
* @param alg 算法,只支持对称算法
|
||||
* @param key 密钥值,明文
|
||||
* @param mode 轮模式
|
||||
* @param padding 填充模式
|
||||
* @param data 密文数据
|
||||
* @param data 密文数据
|
||||
*/
|
||||
byte[] symDecrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data);
|
||||
|
||||
byte[] symDecrypt(KeyAlg alg, byte[] key, byte[] data);
|
||||
|
||||
|
||||
byte[] symDecrypt(AlgId alg, byte[] key, byte[] iv, byte[] data);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -98,7 +98,7 @@ public class BcSdfApiAdaptor implements SdfApiAdapter {
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public EccKey generateKeyPairECC(String sessionHandle, String alg, int uiKeyBits) {
|
||||
public EccKey generateKeyPairECC(String sessionHandle, AlgId alg) {
|
||||
// 生成密钥对
|
||||
KeyPair keyPair = BCSM2Utils.generateKeyPair();
|
||||
BCECPublicKey pubKey = (BCECPublicKey) keyPair.getPublic();
|
||||
@ -171,9 +171,14 @@ public class BcSdfApiAdaptor implements SdfApiAdapter {
|
||||
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public byte[] symEncrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucData) {
|
||||
byte[] symKey = getSymKey(keyHandle);
|
||||
return externalSymEncrypt(sessionHandle, symKey, alg, pucIv, pucData);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public byte[] externalSymEncrypt(String sessionHandle, byte[] symKey, AlgId alg, byte[] pucIv, byte[] pucData) {
|
||||
switch (alg) {
|
||||
case SGD_SM4_ECB:
|
||||
return BCSM4Utils.encrypt_ECB_NoPadding(symKey, pucData);
|
||||
@ -185,9 +190,14 @@ public class BcSdfApiAdaptor implements SdfApiAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public byte[] symDecrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucEncData) {
|
||||
byte[] symKey = getSymKey(keyHandle);
|
||||
return externalSymDecrypt(sessionHandle, symKey, alg, pucIv, pucEncData);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public byte[] externalSymDecrypt(String sessionHandle, byte[] symKey, AlgId alg, byte[] pucIv, byte[] pucEncData) {
|
||||
switch (alg) {
|
||||
case SGD_SM4_ECB:
|
||||
return BCSM4Utils.decrypt_ECB_NoPadding(symKey, pucEncData);
|
||||
|
@ -8,6 +8,7 @@ import com.sunyard.chsm.sdf.lib.SdfLibrary;
|
||||
import com.sunyard.chsm.sdf.model.DeviceInfo;
|
||||
import com.sunyard.chsm.sdf.model.EccCipher;
|
||||
import com.sunyard.chsm.sdf.model.EccKey;
|
||||
import com.sunyard.chsm.sdf.model.EccPriKey;
|
||||
import com.sunyard.chsm.sdf.model.EccPubKey;
|
||||
import com.sunyard.chsm.sdf.model.SDF_DeviceInfo;
|
||||
import com.sunyard.chsm.sdf.util.LangUtils;
|
||||
@ -129,8 +130,13 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public EccKey generateKeyPairECC(String sessionHandle, String alg, int uiKeyBits) {
|
||||
return null;
|
||||
public EccKey generateKeyPairECC(String sessionHandle, AlgId alg) {
|
||||
byte[] sdfPubKey = new byte[132];
|
||||
byte[] sdfPriKey = new byte[68];
|
||||
|
||||
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||
sdfLibrary.SDF_GenerateKeyPair_ECC(hSessionHandle, getAlgId(alg), 256, sdfPubKey, sdfPriKey);
|
||||
return new EccKey(EccPubKey.fromBytes(sdfPubKey).getPubKeyBytes(), EccPriKey.fromBytes(sdfPriKey).getD());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -200,6 +206,25 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
|
||||
return pucEncData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] externalSymEncrypt(String sessionHandle, byte[] symKey, AlgId alg, byte[] pucIv, byte[] pucData) {
|
||||
int uiDataLength = pucData.length;
|
||||
byte[] pucEncData = new byte[uiDataLength];
|
||||
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||
int length = symKey.length;
|
||||
PointerByReference phKeyHandle = new PointerByReference();
|
||||
// 先导入密钥
|
||||
sdfLibrary.SDF_ImportKey(hSessionHandle, symKey, length, phKeyHandle);
|
||||
//加密
|
||||
Pointer hKeyHandle = phKeyHandle.getValue();
|
||||
IntByReference puiLength = new IntByReference();
|
||||
sdfLibrary.SDF_Encrypt(hSessionHandle, hKeyHandle, getAlgId(alg),
|
||||
pucIv, pucData, uiDataLength, pucEncData, puiLength);
|
||||
// 使用后销毁密钥
|
||||
sdfLibrary.SDF_DestroyKey(hSessionHandle, hKeyHandle);
|
||||
return pucEncData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] symDecrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucEncData) {
|
||||
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||
@ -212,4 +237,24 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
|
||||
pucIv, pucEncData, uiEncDataLength, pucData, puiLength);
|
||||
return pucData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] externalSymDecrypt(String sessionHandle, byte[] symKey, AlgId alg, byte[] pucIv, byte[] pucEncData) {
|
||||
int uiEncDataLength = pucEncData.length;
|
||||
byte[] pucData = new byte[uiEncDataLength];
|
||||
|
||||
PointerByReference phKeyHandle = new PointerByReference();
|
||||
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||
int length = symKey.length;
|
||||
// 导入会话密钥
|
||||
sdfLibrary.SDF_ImportKey(hSessionHandle, symKey, length, phKeyHandle);
|
||||
// 解密
|
||||
Pointer hKeyHandle = phKeyHandle.getValue();
|
||||
IntByReference puiLength = new IntByReference();
|
||||
sdfLibrary.SDF_Decrypt(hSessionHandle, hKeyHandle, getAlgId(alg),
|
||||
pucIv, pucEncData, uiEncDataLength, pucData, puiLength);
|
||||
// 销毁会话密钥
|
||||
sdfLibrary.SDF_DestroyKey(hSessionHandle, hKeyHandle);
|
||||
return pucData;
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ public interface SdfApiAdapter {
|
||||
* @return pucRandom 返回随机数
|
||||
*/
|
||||
byte[] generateRandom(String sessionHandle, int uiLength);
|
||||
|
||||
|
||||
/**
|
||||
* 导出ECC加密公钥
|
||||
*
|
||||
@ -61,13 +61,12 @@ public interface SdfApiAdapter {
|
||||
EccPubKey exportEncPublicKeyECC(String sessionHandle, int uiKeyIndex);
|
||||
|
||||
/**
|
||||
* 产生ECC密钥对并输出
|
||||
* 产生ECC密钥对并输出 密钥模长 256
|
||||
*
|
||||
* @param alg 指定算法标识 SGD_SM2_1
|
||||
* @param uiKeyBits 指定密钥模长
|
||||
* @return pucPublicKeyEcc 返回公钥 | pucPrivateKeyEcc 返回私钥
|
||||
*/
|
||||
EccKey generateKeyPairECC(String sessionHandle, String alg, int uiKeyBits);
|
||||
EccKey generateKeyPairECC(String sessionHandle, AlgId alg);
|
||||
|
||||
boolean getPrivateKeyAccessRight(String hSessionHandle, int uiKeyIndex, byte[] pucPassword);
|
||||
|
||||
@ -75,7 +74,7 @@ public interface SdfApiAdapter {
|
||||
* 导入会话密钥并用内部ECC私钥解密
|
||||
*
|
||||
* @param uiIskIndex 密码设备内部存储加密私钥的索引值,对应于加密时的公钥
|
||||
* @param eccCipher 缓冲区指针,用于存放返回的密钥密文
|
||||
* @param eccCipher 缓冲区指针,用于存放返回的密钥密文
|
||||
* @return phKeyHandle 返回密钥句柄
|
||||
*/
|
||||
String importKeyWithISKECC(String sessionHandle, int uiIskIndex, EccCipher eccCipher);
|
||||
@ -103,8 +102,8 @@ public interface SdfApiAdapter {
|
||||
/**
|
||||
* 外部密钥ECC公钥加密
|
||||
*
|
||||
* @param pubKey 外部ECC公钥结构
|
||||
* @param pucData 缓冲区指针,用于存放外部输入的数据
|
||||
* @param pubKey 外部ECC公钥结构
|
||||
* @param pucData 缓冲区指针,用于存放外部输入的数据
|
||||
* @return pucEncData 返回数据密文
|
||||
*/
|
||||
EccCipher externalEncryptECC(String sessionHandle, EccPubKey pubKey, byte[] pucData);
|
||||
@ -121,6 +120,8 @@ public interface SdfApiAdapter {
|
||||
*/
|
||||
byte[] symEncrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucData);
|
||||
|
||||
byte[] externalSymEncrypt(String sessionHandle, byte[] symKey, AlgId alg, byte[] pucIv, byte[] pucData);
|
||||
|
||||
/**
|
||||
* 对称解密
|
||||
*
|
||||
@ -133,4 +134,5 @@ public interface SdfApiAdapter {
|
||||
*/
|
||||
byte[] symDecrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucEncData);
|
||||
|
||||
byte[] externalSymDecrypt(String sessionHandle, byte[] symKey, AlgId alg, byte[] pucIv, byte[] pucEncData);
|
||||
}
|
||||
|
@ -13,6 +13,10 @@ import java.util.Objects;
|
||||
public class SdfApiAdapterFactory {
|
||||
|
||||
|
||||
public static SdfApiAdapter getBcAdapter() {
|
||||
return BcSdfApiAdaptor.INSTANCE;
|
||||
}
|
||||
|
||||
public static SdfApiAdapter newInstance(String model, String ip, Integer port) {
|
||||
|
||||
Assert.hasText(model, "设备型号不能为空");
|
||||
@ -31,7 +35,4 @@ public class SdfApiAdapterFactory {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ public interface SdfLibrary extends Library {
|
||||
* @param phKeyhandle
|
||||
* @return
|
||||
*/
|
||||
int SDF_DestroyKey(Pointer phSessionHandle, PointerByReference phKeyhandle);
|
||||
int SDF_DestroyKey(Pointer phSessionHandle, Pointer phKeyhandle);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -3,6 +3,10 @@ package com.sunyard.chsm.sdf.model;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author liulu
|
||||
@ -18,5 +22,17 @@ public class EccPriKey {
|
||||
// 私 钥
|
||||
private byte[] D;
|
||||
|
||||
public static EccPriKey fromBytes(byte[] priKey) {
|
||||
Assert.notNull(priKey, "公钥数据不能为null");
|
||||
if (Objects.equals(priKey.length, 132)) {
|
||||
// 00010000
|
||||
priKey = Arrays.copyOfRange(priKey, 4, priKey.length);
|
||||
}
|
||||
Assert.isTrue(Objects.equals(priKey.length, 32) || Objects.equals(priKey.length, 64), "Ecc私钥数据格式错误");
|
||||
if (Objects.equals(priKey.length, 32)) {
|
||||
return new EccPriKey(256, priKey);
|
||||
}
|
||||
return new EccPriKey(256, Arrays.copyOfRange(priKey, 32, 64));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public abstract class PaddingUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] PKCS5Padding(byte[] content) throws Exception {
|
||||
public static byte[] PKCS5Padding(byte[] content) {
|
||||
return PKCS7Padding(content, 8);
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ public class TmkService {
|
||||
log.warn("data error, no tmk found in system");
|
||||
return;
|
||||
}
|
||||
SdfApiAdapter softAdapter = SdfApiAdapterFactory.newInstance(BouncyCastleProvider.PROVIDER_NAME, "", 0);
|
||||
SdfApiAdapter softAdapter = SdfApiAdapterFactory.getBcAdapter();
|
||||
EccPubKey pubKey = softAdapter.exportEncPublicKeyECC("", 1);
|
||||
|
||||
SdfApiAdapter tmkAdapter = SdfApiAdapterFactory.newInstance(device.getManufacturerModel(), device.getServiceIp(), device.getServicePort());
|
||||
@ -244,7 +244,7 @@ public class TmkService {
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getSoftDeviceEncTmk() {
|
||||
public byte[] getSoftDeviceEncTmk() {
|
||||
boolean tmkInit = isTmkInit();
|
||||
Assert.isTrue(tmkInit, "主密钥未初始化");
|
||||
boolean enabled = isEnableSoftDevice();
|
||||
|
@ -22,4 +22,6 @@ public interface DeviceService {
|
||||
|
||||
void delete(Long id);
|
||||
|
||||
void checkDeviceStatus();
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.sunyard.chsm.dto.DeviceDTO;
|
||||
import com.sunyard.chsm.enums.DeviceTmkStatus;
|
||||
import com.sunyard.chsm.enums.ManufacturerEnum;
|
||||
import com.sunyard.chsm.enums.ManufacturerModelEnum;
|
||||
import com.sunyard.chsm.mapper.SpDeviceMapper;
|
||||
@ -203,4 +204,37 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
Assert.isNull(exist, "设备名称已存在");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkDeviceStatus() {
|
||||
|
||||
for (int i = 1; i < 500; i++) {
|
||||
Page<Device> devicePage = spDeviceMapper.selectPage(
|
||||
new Page<>(i, 20L),
|
||||
new LambdaQueryWrapper<Device>().orderByAsc(Device::getId)
|
||||
);
|
||||
List<Device> records = devicePage.getRecords();
|
||||
if (CollectionUtils.isEmpty(records)) {
|
||||
break;
|
||||
}
|
||||
for (Device record : records) {
|
||||
DeviceCheckRes checkRes = tmkService.checkDevice(record);
|
||||
Device up = new Device();
|
||||
up.setId(record.getId());
|
||||
up.setConnected(checkRes.getStatus() != DeviceTmkStatus.device_error);
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
if (up.getConnected()) {
|
||||
up.setLastConnectedTime(now);
|
||||
}
|
||||
up.setLastCheckTime(now);
|
||||
|
||||
up.setTmkStatus(checkRes.getStatus().name());
|
||||
up.setDeviceSerial(checkRes.getDeviceSerial());
|
||||
if (!Objects.equals(checkRes.getPubKey(), record.getPubKey())) {
|
||||
up.setPubKey(checkRes.getPubKey());
|
||||
}
|
||||
up.setEncTmk(checkRes.getEncTmk());
|
||||
spDeviceMapper.updateById(up);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +1,15 @@
|
||||
package com.sunyard.chsm.task;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.sun.jna.Platform;
|
||||
import com.sunyard.chsm.enums.DeviceTmkStatus;
|
||||
import com.sunyard.chsm.mapper.SpDeviceMapper;
|
||||
import com.sunyard.chsm.model.dto.DeviceCheckRes;
|
||||
import com.sunyard.chsm.model.entity.Device;
|
||||
import com.sunyard.chsm.service.DeviceService;
|
||||
import com.sunyard.chsm.service.TmkService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author liulu
|
||||
@ -29,53 +19,17 @@ import java.util.Objects;
|
||||
@Component
|
||||
public class DeviceTask implements InitializingBean {
|
||||
|
||||
@Resource
|
||||
private SpDeviceMapper spDeviceMapper;
|
||||
@Resource
|
||||
private TmkService tmkService;
|
||||
@Resource
|
||||
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
|
||||
private DeviceService deviceService;
|
||||
@Resource
|
||||
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
|
||||
|
||||
|
||||
private void checkDeviceStatus() {
|
||||
|
||||
for (int i = 1; i < 500; i++) {
|
||||
Page<Device> devicePage = spDeviceMapper.selectPage(
|
||||
new Page<>(i, 20L),
|
||||
new LambdaQueryWrapper<Device>().orderByAsc(Device::getId)
|
||||
);
|
||||
List<Device> records = devicePage.getRecords();
|
||||
if (CollectionUtils.isEmpty(records)) {
|
||||
break;
|
||||
}
|
||||
for (Device record : records) {
|
||||
DeviceCheckRes checkRes = tmkService.checkDevice(record);
|
||||
Device up = new Device();
|
||||
up.setId(record.getId());
|
||||
up.setConnected(checkRes.getStatus() != DeviceTmkStatus.device_error);
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
if (up.getConnected()) {
|
||||
up.setLastConnectedTime(now);
|
||||
}
|
||||
up.setLastCheckTime(now);
|
||||
|
||||
up.setTmkStatus(checkRes.getStatus().name());
|
||||
up.setDeviceSerial(checkRes.getDeviceSerial());
|
||||
if (!Objects.equals(checkRes.getPubKey(), record.getPubKey())) {
|
||||
up.setPubKey(checkRes.getPubKey());
|
||||
}
|
||||
up.setEncTmk(checkRes.getEncTmk());
|
||||
spDeviceMapper.updateById(up);
|
||||
}
|
||||
}
|
||||
}
|
||||
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (Platform.isLinux() || Platform.isWindows()) {
|
||||
threadPoolTaskScheduler.scheduleWithFixedDelay(this::checkDeviceStatus, Duration.ofMinutes(5L));
|
||||
threadPoolTaskScheduler.scheduleWithFixedDelay(deviceService::checkDeviceStatus, Duration.ofMinutes(5L));
|
||||
threadPoolTaskScheduler.scheduleWithFixedDelay(tmkService::checkSoftDeviceTmk, Duration.ofMinutes(5L));
|
||||
} else {
|
||||
log.warn("操作系统: {} 不支持启动检查设备状态定时任务", System.getProperty("os.name"));
|
||||
|
@ -9,6 +9,9 @@ import com.sunyard.chsm.mapper.SpDeviceMapper;
|
||||
import com.sunyard.chsm.model.dto.DeviceCheckRes;
|
||||
import com.sunyard.chsm.model.entity.CryptoServiceDeviceGroup;
|
||||
import com.sunyard.chsm.model.entity.Device;
|
||||
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.service.TmkService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -48,13 +51,22 @@ public class DeviceManager implements ApplicationRunner {
|
||||
private Map<Long, List<DeviceContext>> deviceMap = new HashMap<>();
|
||||
|
||||
private boolean enableSoftDevice = false;
|
||||
private TMKContext softContext;
|
||||
|
||||
private final TmkService tmkService;
|
||||
private final SpDeviceMapper spDeviceMapper;
|
||||
private final CryptoServiceDeviceGroupMapper cryptoServiceDeviceGroupMapper;
|
||||
|
||||
|
||||
private TMKContext chooseOne() {
|
||||
public void returnContextToPool(TMKContext context) {
|
||||
Optional.ofNullable(context.getPool())
|
||||
.ifPresent(it -> {
|
||||
context.setPool(null);
|
||||
it.returnObject(context);
|
||||
});
|
||||
}
|
||||
|
||||
public TMKContext chooseOne() {
|
||||
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
|
||||
AppUser user = (AppUser) attributes.getAttribute(SecurityConstant.ATTRIBUTE_APP_USER, RequestAttributes.SCOPE_REQUEST);
|
||||
Assert.notNull(user, "登录用户不能为空");
|
||||
@ -71,16 +83,40 @@ public class DeviceManager implements ApplicationRunner {
|
||||
Optional.ofNullable(deviceMap.get(serviceId))
|
||||
.ifPresent(contexts::addAll);
|
||||
}
|
||||
|
||||
DeviceContext device = getNextDevice(contexts, atomicInteger.getAndIncrement());
|
||||
|
||||
try {
|
||||
return device.getPool().borrowObject();
|
||||
} catch (Exception e) {
|
||||
|
||||
|
||||
throw new RuntimeException(e);
|
||||
TMKContext tmkContext;
|
||||
if (device == null) {
|
||||
tmkContext = getSoftContext();
|
||||
} else {
|
||||
try {
|
||||
GenericObjectPool<TMKContext> pool = device.getPool();
|
||||
tmkContext = pool.borrowObject(2000);
|
||||
tmkContext.setPool(pool);
|
||||
} catch (Exception e) {
|
||||
tmkContext = getSoftContext();
|
||||
}
|
||||
}
|
||||
Assert.notNull(tmkContext, "应用: " + user.getName() + "没有可用的密码设备");
|
||||
return tmkContext;
|
||||
}
|
||||
|
||||
public synchronized TMKContext getSoftContext() {
|
||||
if (!enableSoftDevice) {
|
||||
return null;
|
||||
}
|
||||
if (Objects.nonNull(softContext)) {
|
||||
return softContext;
|
||||
}
|
||||
byte[] softEncTmk = tmkService.getSoftDeviceEncTmk();
|
||||
if (softEncTmk == null || softEncTmk.length == 0) {
|
||||
return null;
|
||||
}
|
||||
SdfApiAdapter bcAdapter = SdfApiAdapterFactory.getBcAdapter();
|
||||
String hk = bcAdapter.importKeyWithISKECC("", 1, EccCipher.fromBytes(softEncTmk));
|
||||
softContext = new TMKContext();
|
||||
softContext.setSdfApiAdapter(bcAdapter);
|
||||
softContext.setKeyHandle(hk);
|
||||
return softContext;
|
||||
}
|
||||
|
||||
|
||||
@ -146,7 +182,7 @@ public class DeviceManager implements ApplicationRunner {
|
||||
.map(DeviceContext::getDeviceSerial)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<DeviceContext> noChanged = old.stream()
|
||||
List<DeviceContext> nc = old.stream()
|
||||
.filter(it -> newSerials.contains(it.getDeviceSerial()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
@ -154,8 +190,8 @@ public class DeviceManager implements ApplicationRunner {
|
||||
.filter(it -> !oldSerials.contains(it.getDeviceSerial()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
noChanged.addAll(waitSync.stream().map(this::mapToContext).filter(Objects::nonNull).collect(Collectors.toList()));
|
||||
return noChanged;
|
||||
nc.addAll(waitSync.stream().map(this::mapToContext).filter(Objects::nonNull).collect(Collectors.toList()));
|
||||
return nc;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -4,10 +4,13 @@ import com.sunyard.chsm.enums.AlgMode;
|
||||
import com.sunyard.chsm.enums.KeyAlg;
|
||||
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.EccKey;
|
||||
import com.sunyard.chsm.sdf.util.PaddingUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* @author liulu
|
||||
@ -17,32 +20,51 @@ import javax.annotation.Resource;
|
||||
public class LoadBalancedSdfApiService implements SdfApiService {
|
||||
|
||||
|
||||
|
||||
@Resource
|
||||
private DeviceManager deviceManager;
|
||||
|
||||
|
||||
private <T> T apply(Function<TMKContext, T> fun) {
|
||||
TMKContext context = deviceManager.chooseOne();
|
||||
try {
|
||||
return fun.apply(context);
|
||||
} finally {
|
||||
deviceManager.returnContextToPool(context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] generateRandom(int len) {
|
||||
|
||||
|
||||
return new byte[0];
|
||||
return apply(s -> s.getSdfApiAdapter().generateRandom(s.getSessionHandle(), len));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] genSymKey(KeyAlg alg, Integer keyLen) {
|
||||
return new byte[0];
|
||||
return generateRandom(keyLen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] genSymKey(KeyAlg alg) {
|
||||
return new byte[0];
|
||||
return generateRandom(16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] symEncrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
||||
return new byte[0];
|
||||
byte[] paddingData = null;
|
||||
switch (padding) {
|
||||
case NOPadding:
|
||||
paddingData = data;
|
||||
break;
|
||||
case PCKS5Padding:
|
||||
paddingData = PaddingUtil.PKCS5Padding(data);
|
||||
break;
|
||||
case PCKS7Padding:
|
||||
paddingData = PaddingUtil.PKCS7Padding(data);
|
||||
break;
|
||||
}
|
||||
byte[] finalPaddingData = paddingData;
|
||||
return apply(s -> s.getSdfApiAdapter()
|
||||
.externalSymEncrypt(s.getSessionHandle(), key, null, null, finalPaddingData));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -50,6 +72,11 @@ public class LoadBalancedSdfApiService implements SdfApiService {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] symEncrypt(AlgId alg, byte[] key, byte[] iv, byte[] data) {
|
||||
return apply(s -> s.getSdfApiAdapter().externalSymEncrypt(s.getSessionHandle(), key, alg, iv, PaddingUtil.PKCS7Padding(data)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] symDecrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
||||
return new byte[0];
|
||||
@ -60,9 +87,15 @@ public class LoadBalancedSdfApiService implements SdfApiService {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] symDecrypt(AlgId alg, byte[] key, byte[] iv, byte[] data) {
|
||||
byte[] decrypt = apply(s -> s.getSdfApiAdapter().externalSymDecrypt(s.getSessionHandle(), key, alg, iv, data));
|
||||
return PaddingUtil.PKCS7Unpadding(decrypt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EccKey genKeyPairEcc() {
|
||||
return null;
|
||||
return apply(s -> s.getSdfApiAdapter().generateKeyPairECC(s.getSessionHandle(), AlgId.SGD_SM2_1));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.sunyard.chsm.pool;
|
||||
|
||||
import com.sunyard.chsm.sdf.adapter.SdfApiAdapter;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPool;
|
||||
|
||||
/**
|
||||
* @author liulu
|
||||
@ -9,13 +11,13 @@ import lombok.Data;
|
||||
@Data
|
||||
public class TMKContext {
|
||||
|
||||
|
||||
private String encTmk;
|
||||
private String deviceHandle;
|
||||
private String sessionHandle;
|
||||
private String keyHandle;
|
||||
|
||||
|
||||
|
||||
private SdfApiAdapter sdfApiAdapter;
|
||||
private GenericObjectPool<TMKContext> pool;
|
||||
|
||||
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ public class TMKContextFactory extends BasePooledObjectFactory<TMKContext> {
|
||||
sdfApiAdapter.getPrivateKeyAccessRight(hs, context.getEncKeyIdx(), context.getAccessCredentials().getBytes());
|
||||
String hk = sdfApiAdapter.importKeyWithISKECC(hs, context.getEncKeyIdx(), EccCipher.fromHex(context.getEncTmk()));
|
||||
keyHandle.setKeyHandle(hk);
|
||||
keyHandle.setSdfApiAdapter(sdfApiAdapter);
|
||||
log.info("create key handle with isk for {}", context.getIpPort());
|
||||
return keyHandle;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user