diff --git a/chsm-common/src/main/java/com/sunyard/chsm/constant/ParamConfKeyConstant.java b/chsm-common/src/main/java/com/sunyard/chsm/constant/ParamConfKeyConstant.java index d32c124..053c73f 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/constant/ParamConfKeyConstant.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/constant/ParamConfKeyConstant.java @@ -14,6 +14,10 @@ public interface ParamConfKeyConstant { String TMK_INIT = "tmk_init"; + String ENABLE_SOFT_DEVICE = "enable_soft_device"; + + String SOFT_ENC_TMK = "soft_enc_tmk"; + /** * 通讯超时时间 */ diff --git a/chsm-common/src/main/java/com/sunyard/chsm/mapper/SpDeviceMapper.java b/chsm-common/src/main/java/com/sunyard/chsm/mapper/SpDeviceMapper.java index 95ac364..39da966 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/mapper/SpDeviceMapper.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/mapper/SpDeviceMapper.java @@ -2,6 +2,8 @@ package com.sunyard.chsm.mapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.sunyard.chsm.enums.TmkStatusEnum; import com.sunyard.chsm.model.entity.Device; import org.apache.ibatis.annotations.Mapper; @@ -21,5 +23,17 @@ public interface SpDeviceMapper extends BaseMapper { ); } + default Device selectOneByStatus(TmkStatusEnum status) { + Page devicePage = selectPage( + Page.of(1L, 1L), + new LambdaQueryWrapper().eq(Device::getTmkStatus, status.name()) + ); + List records = devicePage.getRecords(); + if (records.isEmpty()) { + return null; + } + return records.iterator().next(); + }; + } diff --git a/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/BcSdfApiAdaptor.java b/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/BcSdfApiAdaptor.java index 67153e1..abba1f8 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/BcSdfApiAdaptor.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/BcSdfApiAdaptor.java @@ -8,17 +8,23 @@ import com.sunyard.chsm.sdf.model.EccPubKey; import com.sunyard.chsm.sdf.util.LangUtils; import com.sunyard.chsm.utils.gm.BCECUtils; import com.sunyard.chsm.utils.gm.BCSM2Utils; +import com.sunyard.chsm.utils.gm.BCSM4Utils; import lombok.SneakyThrows; import org.bouncycastle.crypto.InvalidCipherTextException; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey; import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.util.BigIntegers; +import org.springframework.util.Assert; import java.math.BigInteger; import java.security.KeyPair; import java.security.SecureRandom; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; /** * @author liulu @@ -26,6 +32,7 @@ import java.security.SecureRandom; */ public class BcSdfApiAdaptor implements SdfApiAdapter { + protected static final Map KEY_HANDLE_CONTEXT = new ConcurrentHashMap<>(); private static final DeviceInfo deviceInfo; @@ -41,6 +48,8 @@ public class BcSdfApiAdaptor implements SdfApiAdapter { deviceInfo.setHashAlgAbility(7010608454676760881L); } + protected static final BcSdfApiAdaptor INSTANCE = new BcSdfApiAdaptor(); + @Override public String openDevice() { return "c95a78d9c04a557b7b46dbcb5f36cc66"; @@ -102,38 +111,58 @@ public class BcSdfApiAdaptor implements SdfApiAdapter { @Override public boolean getPrivateKeyAccessRight(String hSessionHandle, int uiKeyIndex, byte[] pucPassword) { - return false; + return true; } @Override public EccCipher exchangeDigitEnvelopeBaseOnECC(String sessionHandle, int uiKeyIndex, EccPubKey pubKey, EccCipher pucEncDateIn) { - return null; + + ECPublicKeyParameters pub = BCECUtils.createECPublicKeyParameters(pubKey.getX(), pubKey.getY()); + ECPrivateKeyParameters pri = BCECUtils.createECPrivateKeyParameters(getD()); + try { + byte[] k = BCSM2Utils.decrypt(pri, pucEncDateIn.getC1C3C2Bytes()); + byte[] encrypt = BCSM2Utils.encrypt(pub, k); + return EccCipher.fromBytes(encrypt); + } catch (InvalidCipherTextException e) { + throw new IllegalArgumentException(e); + } } @Override public String importKeyWithISKECC(String sessionHandle, int uiIskIndex, EccCipher eccCipher) { - return ""; + ECPrivateKeyParameters pri = BCECUtils.createECPrivateKeyParameters(getD()); + + try { + byte[] pucKey = BCSM2Utils.decrypt(pri, eccCipher.getC1C3C2Bytes()); + Assert.isTrue(pucKey.length == 16, "密钥长度错误"); + String key = UUID.randomUUID().toString(); + KEY_HANDLE_CONTEXT.put(key, pucKey); + return key; + } catch (InvalidCipherTextException e) { + throw new IllegalArgumentException(e); + } } @Override public String importKey(String sessionHandle, byte[] pucKey) { - return ""; + Assert.isTrue(pucKey.length == 16, "密钥长度错误"); + String key = UUID.randomUUID().toString(); + KEY_HANDLE_CONTEXT.put(key, pucKey); + return key; } @Override public int destroyKey(String sessionHandle, String hKeyHandle) { + KEY_HANDLE_CONTEXT.remove(hKeyHandle); return 0; } @Override public EccCipher externalEncryptECC(String sessionHandle, EccPubKey pubKey, byte[] pucData) { - ECPublicKeyParameters parameters = BCECUtils.createECPublicKeyParameters( - pubKey.getX(), - pubKey.getY() - ); + ECPublicKeyParameters pub = BCECUtils.createECPublicKeyParameters(pubKey.getX(), pubKey.getY()); try { - byte[] encrypt = BCSM2Utils.encrypt(parameters, pucData); + byte[] encrypt = BCSM2Utils.encrypt(pub, pucData); return EccCipher.fromBytes(encrypt); } catch (InvalidCipherTextException e) { throw new IllegalArgumentException(e); @@ -142,12 +171,36 @@ public class BcSdfApiAdaptor implements SdfApiAdapter { @Override + @SneakyThrows public byte[] symEncrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucData) { - return new byte[0]; + byte[] symKey = getSymKey(keyHandle); + switch (alg) { + case SGD_SM4_ECB: + return BCSM4Utils.encrypt_ECB_NoPadding(symKey, pucData); + case SGD_SM4_CBC: + return BCSM4Utils.encrypt_CBC_NoPadding(symKey, pucIv, pucData); + default: + throw new IllegalArgumentException("不支持的算法:" + alg.name()); + } } @Override + @SneakyThrows public byte[] symDecrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucEncData) { - return new byte[0]; + byte[] symKey = getSymKey(keyHandle); + switch (alg) { + case SGD_SM4_ECB: + return BCSM4Utils.decrypt_ECB_NoPadding(symKey, pucEncData); + case SGD_SM4_CBC: + return BCSM4Utils.decrypt_CBC_NoPadding(symKey, pucIv, pucEncData); + default: + throw new IllegalArgumentException("不支持的算法:" + alg.name()); + } + } + + protected byte[] getSymKey(String keyHandle) { + byte[] key = KEY_HANDLE_CONTEXT.get(keyHandle); + Assert.notNull(key, "密钥句柄不存在"); + return key; } } diff --git a/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/SdfApiAdapterFactory.java b/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/SdfApiAdapterFactory.java index cd3492d..4e4cd67 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/SdfApiAdapterFactory.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/SdfApiAdapterFactory.java @@ -20,7 +20,7 @@ public class SdfApiAdapterFactory { if (Objects.isNull(modelEnum) && Objects.equals(BouncyCastleProvider.PROVIDER_NAME, model)) { // bc adaptor - return new BcSdfApiAdaptor(); + return BcSdfApiAdaptor.INSTANCE; } switch (modelEnum) { case enc001: diff --git a/chsm-common/src/main/java/com/sunyard/chsm/sdf/model/EccCipher.java b/chsm-common/src/main/java/com/sunyard/chsm/sdf/model/EccCipher.java index 346909e..5b6967c 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/sdf/model/EccCipher.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/sdf/model/EccCipher.java @@ -1,5 +1,6 @@ package com.sunyard.chsm.sdf.model; +import com.sunyard.chsm.utils.CodecUtils; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -30,6 +31,9 @@ public class EccCipher { // 密文数据 private byte[] C; + public String getC1C3C2Hex() { + return CodecUtils.encodeHex(getC1C3C2Bytes()); + } public byte[] getC1C3C2Bytes() { int xLen = x.length; @@ -57,6 +61,10 @@ public class EccCipher { return d; } + public static EccCipher fromHex(String hex) { + return fromBytes(CodecUtils.decodeHex(hex)); + } + public static EccCipher fromBytes(byte[] cipher) { Assert.notNull(cipher, "Ecc密文数据不能为null"); if (cipher[0] == 0x04) { diff --git a/chsm-web-manage/src/main/java/com/sunyard/chsm/service/impl/DeviceServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/chsm/service/impl/DeviceServiceImpl.java index 2b5e392..db099aa 100644 --- a/chsm-web-manage/src/main/java/com/sunyard/chsm/service/impl/DeviceServiceImpl.java +++ b/chsm-web-manage/src/main/java/com/sunyard/chsm/service/impl/DeviceServiceImpl.java @@ -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 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 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 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); } }