|
|
|
@@ -14,9 +14,16 @@ import com.sunyard.chsm.sdf.context.AlgId;
|
|
|
|
|
import com.sunyard.chsm.sdf.model.DeviceInfo;
|
|
|
|
|
import com.sunyard.chsm.sdf.model.EccCipher;
|
|
|
|
|
import com.sunyard.chsm.sdf.model.EccPubKey;
|
|
|
|
|
import com.sunyard.chsm.sdf.util.LangUtils;
|
|
|
|
|
import com.sunyard.chsm.utils.CodecUtils;
|
|
|
|
|
import com.sunyard.chsm.utils.gm.BCECUtils;
|
|
|
|
|
import com.sunyard.chsm.utils.gm.BCSM2Utils;
|
|
|
|
|
import com.sunyard.chsm.utils.gm.BCSM3Utils;
|
|
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.apache.commons.lang3.tuple.Pair;
|
|
|
|
|
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
|
|
|
|
|
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
|
|
|
|
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
|
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
import org.springframework.util.Assert;
|
|
|
|
@@ -59,6 +66,8 @@ public class TmkService {
|
|
|
|
|
byte[] prk = sdfApi.symDecrypt(hs, hk, AlgId.SGD_SM4_ECB, new byte[0], encrk);
|
|
|
|
|
Assert.isTrue(Arrays.equals(rk, prk), "密码机加解密异常");
|
|
|
|
|
|
|
|
|
|
byte[] hash = BCSM3Utils.hash(rk);
|
|
|
|
|
|
|
|
|
|
sdfApi.destroyKey(hs, hk);
|
|
|
|
|
sdfApi.closeSession(hs);
|
|
|
|
|
sdfApi.closeDevice(hd);
|
|
|
|
@@ -72,7 +81,7 @@ public class TmkService {
|
|
|
|
|
up.setTmkStatus(DeviceTmkStatus.finished.name());
|
|
|
|
|
spDeviceMapper.updateById(up);
|
|
|
|
|
}
|
|
|
|
|
updateTmkInit(true);
|
|
|
|
|
updateTmkInit(true, hash);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -82,6 +91,10 @@ public class TmkService {
|
|
|
|
|
if (init) {
|
|
|
|
|
status.setHasDevice(true);
|
|
|
|
|
status.setTmkInit(true);
|
|
|
|
|
ParamConf paramConf = paramConfMapper.selectByKey(ParamConfKeyConstant.TMK_CHECK_VALUE);
|
|
|
|
|
if (paramConf != null) {
|
|
|
|
|
status.setCheckValue(paramConf.getValue());
|
|
|
|
|
}
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
status.setTmkInit(false);
|
|
|
|
@@ -90,6 +103,88 @@ public class TmkService {
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String backup(String pubKey) {
|
|
|
|
|
|
|
|
|
|
boolean tmkInit = isTmkInit();
|
|
|
|
|
Assert.isTrue(tmkInit, "主密钥未初始化");
|
|
|
|
|
Device device = getOneByStatus(DeviceTmkStatus.finished);
|
|
|
|
|
Assert.notNull(device, "没有可以用于备份主密钥的设备");
|
|
|
|
|
byte[] xy;
|
|
|
|
|
try {
|
|
|
|
|
String pubBase6 = pubKey.replace("-----BEGIN ECDSA PUBLIC KEY-----", "").replace("-----END ECDSA PUBLIC KEY-----", "")
|
|
|
|
|
.replace("\n", "");
|
|
|
|
|
byte[] pubBytes = CodecUtils.decodeBase64(pubBase6);
|
|
|
|
|
SubjectPublicKeyInfo keyInfo = SubjectPublicKeyInfo.getInstance(pubBytes);
|
|
|
|
|
BCECPublicKey key = BCECUtils.createPublicKeyFromSubjectPublicKeyInfo(keyInfo);
|
|
|
|
|
xy = LangUtils.merge(key.getQ().getXCoord().getEncoded(), key.getQ().getYCoord().getEncoded());
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw new IllegalArgumentException(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SdfApiAdapter sdfApi = SdfApiAdapterFactory.newInstance(device.getManufacturerModel(), device.getServiceIp(), device.getServicePort());
|
|
|
|
|
|
|
|
|
|
String hd = sdfApi.openDevice();
|
|
|
|
|
String hs = sdfApi.openSession(hd);
|
|
|
|
|
sdfApi.getPrivateKeyAccessRight(hs, device.getEncKeyIdx(), device.getAccessCredentials().getBytes());
|
|
|
|
|
|
|
|
|
|
EccCipher cipher = sdfApi.exchangeDigitEnvelopeBaseOnECC(hs, device.getEncKeyIdx(), EccPubKey.fromBytes(xy), EccCipher.fromHex(device.getEncTmk()));
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
byte[] der = BCSM2Utils.encodeSM2CipherToDER(LangUtils.merge(new byte[]{0x04}, cipher.getC1C3C2Bytes()));
|
|
|
|
|
return CodecUtils.encodeBase64(der);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw new IllegalArgumentException(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Pair<Long, String> getDevicePubKey() {
|
|
|
|
|
Device device = getOneByStatus(DeviceTmkStatus.available);
|
|
|
|
|
Assert.notNull(device, "没有可以用于导入主密钥的设备");
|
|
|
|
|
SdfApiAdapter sdfApi = SdfApiAdapterFactory.newInstance(device.getManufacturerModel(), device.getServiceIp(), device.getServicePort());
|
|
|
|
|
String hd = sdfApi.openDevice();
|
|
|
|
|
String hs = sdfApi.openSession(hd);
|
|
|
|
|
EccPubKey pubKey = sdfApi.exportEncPublicKeyECC(hs, device.getEncKeyIdx());
|
|
|
|
|
|
|
|
|
|
BCECPublicKey publicKey = BCECUtils.createPublicKey(pubKey.getPubKeyHex());
|
|
|
|
|
return Pair.of(device.getId(), CodecUtils.encodeBase64(publicKey.getEncoded()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void importTmk(Long deviceId, String encTmk) {
|
|
|
|
|
boolean tmkInit = isTmkInit();
|
|
|
|
|
Assert.isTrue(!tmkInit, "主密钥已经初始化");
|
|
|
|
|
|
|
|
|
|
Device device = getOneByStatus(DeviceTmkStatus.available);
|
|
|
|
|
Assert.notNull(device, "没有可以用于导入主密钥的设备");
|
|
|
|
|
SdfApiAdapter sdfApi = SdfApiAdapterFactory.newInstance(device.getManufacturerModel(), device.getServiceIp(), device.getServicePort());
|
|
|
|
|
String hd = sdfApi.openDevice();
|
|
|
|
|
String hs = sdfApi.openSession(hd);
|
|
|
|
|
byte[] rk = CodecUtils.decodeBase64(encTmk);
|
|
|
|
|
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), "密码机加解密异常");
|
|
|
|
|
|
|
|
|
|
byte[] hash = BCSM3Utils.hash(rk);
|
|
|
|
|
|
|
|
|
|
sdfApi.destroyKey(hs, hk);
|
|
|
|
|
sdfApi.closeSession(hs);
|
|
|
|
|
sdfApi.closeDevice(hd);
|
|
|
|
|
|
|
|
|
|
if (Objects.equals(device.getManufacturerModel(), BouncyCastleProvider.PROVIDER_NAME)) {
|
|
|
|
|
updateSoftDeviceEncTmk(cipher.getC1C3C2Bytes());
|
|
|
|
|
} else {
|
|
|
|
|
Device up = new Device();
|
|
|
|
|
up.setId(device.getId());
|
|
|
|
|
up.setEncTmk(cipher.getC1C3C2Hex());
|
|
|
|
|
up.setTmkStatus(DeviceTmkStatus.finished.name());
|
|
|
|
|
spDeviceMapper.updateById(up);
|
|
|
|
|
}
|
|
|
|
|
updateTmkInit(true, hash);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public DeviceCheckRes checkDevice(Device check) {
|
|
|
|
|
|
|
|
|
@@ -209,6 +304,7 @@ public class TmkService {
|
|
|
|
|
}
|
|
|
|
|
if (isEnableSoftDevice()) {
|
|
|
|
|
device = new Device();
|
|
|
|
|
device.setId(0L);
|
|
|
|
|
device.setManufacturerModel(BouncyCastleProvider.PROVIDER_NAME);
|
|
|
|
|
device.setEncKeyIdx(1);
|
|
|
|
|
device.setServiceIp("127.0.0.1");
|
|
|
|
@@ -241,7 +337,7 @@ public class TmkService {
|
|
|
|
|
return conf != null && String.valueOf(true).equals(conf.getValue());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateTmkInit(boolean value) {
|
|
|
|
|
private void updateTmkInit(boolean value, byte[] hash) {
|
|
|
|
|
ParamConf conf = paramConfMapper.selectByKey(ParamConfKeyConstant.TMK_INIT);
|
|
|
|
|
if (conf == null) {
|
|
|
|
|
conf = new ParamConf();
|
|
|
|
@@ -253,6 +349,18 @@ public class TmkService {
|
|
|
|
|
conf.setValue(String.valueOf(value));
|
|
|
|
|
paramConfMapper.updateById(conf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ParamConf check = paramConfMapper.selectByKey(ParamConfKeyConstant.TMK_CHECK_VALUE);
|
|
|
|
|
if (check == null) {
|
|
|
|
|
check = new ParamConf();
|
|
|
|
|
check.setValue(CodecUtils.encodeHex(hash));
|
|
|
|
|
check.setKey(ParamConfKeyConstant.TMK_CHECK_VALUE);
|
|
|
|
|
check.setCreatTime(LocalDateTime.now());
|
|
|
|
|
paramConfMapper.insert(conf);
|
|
|
|
|
} else {
|
|
|
|
|
check.setValue(CodecUtils.encodeHex(hash));
|
|
|
|
|
paramConfMapper.updateById(conf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public synchronized byte[] getSoftDeviceEncTmk() {
|
|
|
|
|