主密钥同步

This commit is contained in:
liulu
2024-12-09 17:15:57 +08:00
parent 258cd3ed81
commit f4361d2fd5
6 changed files with 216 additions and 87 deletions
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.constant.ParamConfKeyConstant;
import com.sunyard.chsm.dto.DeviceDTO;
import com.sunyard.chsm.dto.TmkStatus;
import com.sunyard.chsm.enums.ManufacturerEnum;
@@ -14,15 +15,15 @@ import com.sunyard.chsm.mapper.SpDeviceMapper;
import com.sunyard.chsm.mapper.TmkInfoMapper;
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.context.AlgId;
import com.sunyard.chsm.sdf.model.EccCipher;
import com.sunyard.chsm.sdf.model.EccPubKey;
import com.sunyard.chsm.service.DeviceService;
import com.sunyard.chsm.utils.CodecUtils;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.BeanUtils;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Service;
@@ -33,6 +34,7 @@ import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@@ -151,8 +153,9 @@ public class DeviceServiceImpl implements DeviceService {
device.setCreateTime(LocalDateTime.now());
Pair<String, String> pair = checkDeviceSdf(save);
device.setTmkStatus(TmkStatusEnum.available.name());
device.setTmkStatus(StringUtils.hasText(pair.getSecond()) ? TmkStatusEnum.finished.name() : TmkStatusEnum.available.name());
device.setPubKey(pair.getFirst());
device.setEncTmk(pair.getSecond());
spDeviceMapper.insert(device);
return device.getId();
@@ -172,10 +175,32 @@ public class DeviceServiceImpl implements DeviceService {
String hd = sdfApiAdapter.openDevice();
String hs = null;
try {
String encTmk = "";
hs = sdfApiAdapter.openSession(hd);
EccPubKey eccPubKey = sdfApiAdapter.exportEncPublicKeyECC(hs, save.getEncKeyIdx());
if (Arrays.equals(eccPubKey.getPubKeyBytes(), new byte[64])) {
throw new IllegalArgumentException("加密密钥索引不正确");
}
sdfApiAdapter.getPrivateKeyAccessRight(hs, save.getEncKeyIdx(), save.getAccessCredentials().getBytes());
return Pair.of(eccPubKey.getPubKeyHex(), "");
if (isTmkInit()) {
Device device = getOneByStatus(TmkStatusEnum.finished);
Assert.notNull(device, "系统主密钥设备异常");
SdfApiAdapter tmkAdapter = SdfApiAdapterFactory.newInstance(save.getManufacturerModel(), save.getServiceIp(), save.getServicePort());
String tmkHd = tmkAdapter.openDevice();
String tmkHs = tmkAdapter.openSession(tmkHd);
tmkAdapter.getPrivateKeyAccessRight(tmkHs, device.getEncKeyIdx(), device.getAccessCredentials().getBytes());
EccCipher cipher = tmkAdapter.exchangeDigitEnvelopeBaseOnECC(tmkHs, device.getEncKeyIdx(), eccPubKey, EccCipher.fromHex(device.getEncTmk()));
String hk = sdfApiAdapter.importKeyWithISKECC(hs, save.getEncKeyIdx(), cipher);
sdfApiAdapter.destroyKey(hs, hk);
encTmk = cipher.getC1C3C2Hex();
} else {
byte[] random = sdfApiAdapter.generateRandom(hs, 16);
EccCipher eccCipher = sdfApiAdapter.externalEncryptECC(hs, eccPubKey, random);
String hk = sdfApiAdapter.importKeyWithISKECC(hs, save.getEncKeyIdx(), eccCipher);
sdfApiAdapter.destroyKey(hs, hk);
}
return Pair.of(eccPubKey.getPubKeyHex(), encTmk);
} finally {
Optional.ofNullable(hs).ifPresent(sdfApiAdapter::closeSession);
sdfApiAdapter.closeDevice(hd);
@@ -205,9 +230,10 @@ public class DeviceServiceImpl implements DeviceService {
|| !Objects.equals(exist.getEncKeyIdx(), update.getEncKeyIdx())
|| !Objects.equals(exist.getAccessCredentials(), update.getAccessCredentials())) {
Pair<String, String> pair = checkDeviceSdf(update);
up.setTmkStatus(StringUtils.hasText(pair.getSecond()) ? TmkStatusEnum.finished.name() : TmkStatusEnum.available.name());
up.setPubKey(pair.getFirst());
up.setEncTmk(pair.getSecond());
}
spDeviceMapper.updateById(up);
}
@@ -219,90 +245,114 @@ public class DeviceServiceImpl implements DeviceService {
@Override
public TmkStatus getTMKStatus() {
TmkStatus status = new TmkStatus();
ParamConf tmkInit = paramConfMapper.selectByKey("tmk_init");
if (tmkInit != null && "true".equals(tmkInit.getValue())) {
boolean init = isTmkInit();
if (init) {
status.setHasDevice(true);
status.setTmkInit(true);
return status;
}
status.setTmkInit(false);
Long c = spDeviceMapper.selectCount(new LambdaQueryWrapper<>());
status.setHasDevice(c > 0L);
Device device = getOneByStatus(TmkStatusEnum.available);
status.setHasDevice(device != null);
return status;
}
@Override
public void initTmk() {
ParamConf tmkInit = paramConfMapper.selectByKey("tmk_init");
Assert.isTrue(tmkInit == null || !"true".equals(tmkInit.getValue()), "主密钥已经初始化");
// List<Device> conned = spDeviceMapper.selectConnedList();
//
LocalDateTime now = LocalDateTime.now();
// if (CollectionUtils.isEmpty(conned)) {
//
BcSdfApiAdaptor sdfApi = new BcSdfApiAdaptor();
byte[] sk = sdfApi.generateRandom("", 16);
boolean tmkInit = isTmkInit();
Assert.isTrue(!tmkInit, "主密钥已经初始化");
EccPubKey publicKey = sdfApi.exportEncPublicKeyECC("", 1);
EccCipher encSk = sdfApi.externalEncryptECC("", publicKey, sk);
Device device = getOneByStatus(TmkStatusEnum.available);
Assert.notNull(device, "没有可以用于初始化主密钥的设备");
SdfApiAdapter sdfApi = SdfApiAdapterFactory.newInstance(device.getManufacturerModel(), device.getServiceIp(), device.getServicePort());
TmkInfo info = new TmkInfo();
info.setId(IdWorker.getId());
info.setCreateTime(now);
info.setDeviceSerial(sdfApi.getDeviceInfo("").getDeviceSerial());
info.setEncTmk(Hex.toHexString(encSk.getC1C3C2Bytes()));
info.setPubKey(Hex.toHexString(publicKey.getPubKeyBytes()));
tmkInfoMapper.insert(info);
// return;
// }
// Device device = conned.iterator().next();
//
// DeviceContext context = new DeviceContext();
// context.setManufacturer(device.getManufacturer());
// context.setManufacturerModel(device.getManufacturerModel());
// context.setServiceIp(device.getServiceIp());
// context.setServicePort(device.getServicePort());
// SdfApiAdapter sdfApi = SdfApiAdapterFactory.newInstance(context);
// String dh = sdfApi.openDevice();
// String sh = sdfApi.openSession(dh);
// DeviceInfo deviceInfo = sdfApi.getDeviceInfo(sh);
//
// byte[] sk = sdfApi.generateRandom(sh, 16);
// byte[] publicKey = sdfApi.exportEncPublicKeyECC(sh, 1);
// byte[] encSk = sdfApi.externalEncryptECC(sh, publicKey, sk);
//
// TmkInfo info = new TmkInfo();
// info.setId(IdWorker.getId());
// info.setCreateTime(now);
// info.setDeviceSerial(deviceInfo.getDeviceSerial());
// info.setEncTmk(Hex.toHexString(encSk));
// info.setPubKey(Hex.toHexString(publicKey));
// tmkInfoMapper.insert(info);
String hd = sdfApi.openDevice();
String hs = sdfApi.openSession(hd);
byte[] rk = sdfApi.generateRandom(hs, 16);
EccPubKey pubKey = sdfApi.exportEncPublicKeyECC(hs, device.getEncKeyIdx());
EccCipher cipher = sdfApi.externalEncryptECC(hs, pubKey, rk);
sdfApi.getPrivateKeyAccessRight(hs, device.getEncKeyIdx(), device.getAccessCredentials().getBytes());
String hk = sdfApi.importKeyWithISKECC(hs, device.getEncKeyIdx(), cipher);
byte[] encrk = sdfApi.symEncrypt(hs, hk, AlgId.SGD_SM4_ECB, new byte[0], rk);
byte[] prk = sdfApi.symDecrypt(hs, hk, AlgId.SGD_SM4_ECB, new byte[0], encrk);
Assert.isTrue(Arrays.equals(rk, prk), "密码机加解密异常");
//
// BcSdfApiAdaptor bcApi = new BcSdfApiAdaptor();
// byte[] bcPubK = bcApi.exportEncPublicKeyECC("", 1);
// byte[] bcEncSk = sdfApi.exchangeDigitEnvelopeBaseOnECC(sh, 1, bcPubK, encSk);
//
// TmkInfo bcinfo = new TmkInfo();
// bcinfo.setId(IdWorker.getId());
// bcinfo.setCreateTime(now);
// bcinfo.setDeviceSerial(bcApi.getDeviceInfo("").getDeviceSerial());
// bcinfo.setEncTmk(Hex.toHexString(bcEncSk));
// bcinfo.setPubKey(Hex.toHexString(bcPubK));
// tmkInfoMapper.insert(bcinfo);
// sdfApi.closeSession(sh);
// sdfApi.closeDevice(dh);
sdfApi.destroyKey(hs, hk);
sdfApi.closeSession(hs);
sdfApi.closeDevice(hd);
if (tmkInit == null) {
tmkInit = new ParamConf();
tmkInit.setValue("true");
tmkInit.setKey("tmk_init");
tmkInit.setCreatTime(LocalDateTime.now());
paramConfMapper.insert(tmkInit);
if (enableSoftDevice()) {
updateSoftDeviceEncTmk(cipher.getC1C3C2Bytes());
} else {
tmkInit.setValue("true");
paramConfMapper.updateById(tmkInit);
Device up = new Device();
up.setId(device.getId());
up.setEncTmk(cipher.getC1C3C2Hex());
up.setTmkStatus(TmkStatusEnum.finished.name());
spDeviceMapper.updateById(up);
}
updateTmkInit(true);
}
private Device getOneByStatus(TmkStatusEnum status) {
if (enableSoftDevice()) {
Device device = new Device();
device.setManufacturerModel(BouncyCastleProvider.PROVIDER_NAME);
device.setEncKeyIdx(1);
device.setServiceIp("127.0.0.1");
device.setServicePort(8889);
device.setAccessCredentials("543");
device.setEncTmk(CodecUtils.encodeHex(getSoftDeviceEncTmk()));
return device;
}
return spDeviceMapper.selectOneByStatus(status);
}
private boolean isTmkInit() {
ParamConf conf = paramConfMapper.selectByKey(ParamConfKeyConstant.TMK_INIT);
return conf != null && String.valueOf(true).equals(conf.getValue());
}
private void updateTmkInit(boolean value) {
ParamConf conf = paramConfMapper.selectByKey(ParamConfKeyConstant.TMK_INIT);
if (conf == null) {
conf = new ParamConf();
conf.setValue(String.valueOf(value));
conf.setKey(ParamConfKeyConstant.TMK_INIT);
conf.setCreatTime(LocalDateTime.now());
paramConfMapper.insert(conf);
} else {
conf.setValue(String.valueOf(value));
paramConfMapper.updateById(conf);
}
}
private boolean enableSoftDevice() {
ParamConf conf = paramConfMapper.selectByKey(ParamConfKeyConstant.ENABLE_SOFT_DEVICE);
return conf != null && String.valueOf(true).equals(conf.getValue());
}
private byte[] getSoftDeviceEncTmk() {
boolean tmkInit = isTmkInit();
Assert.isTrue(tmkInit, "主密钥未初始化");
boolean enabled = enableSoftDevice();
Assert.isTrue(enabled, "未启用软设备");
ParamConf conf = paramConfMapper.selectByKey(ParamConfKeyConstant.SOFT_ENC_TMK);
Assert.notNull(conf, "数据异常, 未找到软设备主密钥记录");
return CodecUtils.decodeBase64(conf.getValue());
}
private void updateSoftDeviceEncTmk(byte[] encTmk) {
ParamConf conf = paramConfMapper.selectByKey(ParamConfKeyConstant.SOFT_ENC_TMK);
if (conf == null) {
conf = new ParamConf();
conf.setValue(CodecUtils.encodeBase64(encTmk));
conf.setKey(ParamConfKeyConstant.SOFT_ENC_TMK);
conf.setCreatTime(LocalDateTime.now());
paramConfMapper.insert(conf);
} else {
conf.setValue(CodecUtils.encodeBase64(encTmk));
paramConfMapper.updateById(conf);
}
}