This commit is contained in:
liulu 2024-12-11 11:49:40 +08:00
parent 63fce073dd
commit 3dc061907f
18 changed files with 264 additions and 104 deletions

View File

@ -15,6 +15,7 @@ import java.util.Objects;
public enum Padding {
NOPadding("NoPadding", "NoPadding"),
PCKS5Padding( "PKCS5Padding", "PKCS5Padding"),
PCKS7Padding( "PKCS7Padding", "PKCS7Padding"),
;
private final String code;

View File

@ -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];
}
/**
* 对称加解密的统一实现

View File

@ -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);
/**

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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 {
}
}

View File

@ -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);
/**

View File

@ -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));
}
}

View File

@ -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);
}

View File

@ -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();

View File

@ -22,4 +22,6 @@ public interface DeviceService {
void delete(Long id);
void checkDeviceStatus();
}

View File

@ -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);
}
}
}
}

View File

@ -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"));

View File

@ -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;
});
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}