Compare commits
10 Commits
5dd7b9ee7e
...
385a2a6ecc
Author | SHA1 | Date | |
---|---|---|---|
|
385a2a6ecc | ||
|
5ce75ed4ce | ||
|
a98659f3a9 | ||
|
5413fa2545 | ||
|
ba6c06a8b8 | ||
|
b500a4e9cc | ||
|
81759ed6c6 | ||
|
a9b35329ce | ||
|
c18cfda28b | ||
|
4ae46ed32d |
@ -45,6 +45,10 @@
|
|||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-pool2</artifactId>
|
<artifactId>commons-pool2</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.java.dev.jna</groupId>
|
<groupId>net.java.dev.jna</groupId>
|
||||||
<artifactId>jna</artifactId>
|
<artifactId>jna</artifactId>
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
package com.sunyard.chsm.enums;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 算法的轮模式
|
||||||
|
* @author Cheney
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum AlgMode {
|
||||||
|
ECB("ECB", "ECB"),
|
||||||
|
CBC( "CBC", "CBC"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
private final String desc;
|
||||||
|
|
||||||
|
|
||||||
|
public static AlgMode of(String code) {
|
||||||
|
if (code == null || code.trim().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Arrays.stream(AlgMode.values())
|
||||||
|
.filter(it -> Objects.equals(it.getCode(), code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.sunyard.chsm.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据的填充模式
|
||||||
|
* @author Cheney
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum Padding {
|
||||||
|
NOPadding("NoPadding", "NoPadding"),
|
||||||
|
PCKS5Padding( "PKCS5Padding", "PKCS5Padding"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
private final String desc;
|
||||||
|
|
||||||
|
|
||||||
|
public static Padding of(String code) {
|
||||||
|
if (code == null || code.trim().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Arrays.stream(Padding.values())
|
||||||
|
.filter(it -> Objects.equals(it.getCode(), code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.sunyard.chsm.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.sunyard.chsm.model.entity.CaCert;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liulu
|
||||||
|
* @since 2024/11/6
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface CaCertMapper extends BaseMapper<CaCert> {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.sunyard.chsm.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.sunyard.chsm.model.entity.KeyInfo;
|
||||||
|
import com.sunyard.chsm.model.entity.KeyRecord;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liulu
|
||||||
|
* @since 2024/10/22
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface KeyRecordMapper extends BaseMapper<KeyRecord> {
|
||||||
|
}
|
@ -1,13 +1,25 @@
|
|||||||
package com.sunyard.chsm.mapper;
|
package com.sunyard.chsm.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.sunyard.chsm.model.entity.Device;
|
import com.sunyard.chsm.model.entity.Device;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author liulu
|
* @author liulu
|
||||||
* @since 2024/10/17
|
* @since 2024/10/17
|
||||||
*/
|
*/
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface SpDeviceMapper extends BaseMapper<Device> {
|
public interface SpDeviceMapper extends BaseMapper<Device> {
|
||||||
|
|
||||||
|
default List<Device> selectConnedList() {
|
||||||
|
return selectList(
|
||||||
|
new LambdaQueryWrapper<Device>()
|
||||||
|
.eq(Device::getConnected, true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.sunyard.chsm.dto;
|
package com.sunyard.chsm.model.dto;
|
||||||
|
|
||||||
import com.sunyard.chsm.model.PageQuery;
|
import com.sunyard.chsm.model.PageQuery;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@ -95,8 +95,54 @@ public abstract class CertDTO {
|
|||||||
* 加密密钥信封
|
* 加密密钥信封
|
||||||
*/
|
*/
|
||||||
private String envelopedKey;
|
private String envelopedKey;
|
||||||
|
private String remark;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class CaInfo {
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 密钥算法 目前支持: SM2
|
||||||
|
*/
|
||||||
|
@NotEmpty(message = "密钥算法不能为空")
|
||||||
|
private String keyAlg;
|
||||||
|
@NotEmpty(message = "CA名称不能为空")
|
||||||
|
private String caName;
|
||||||
|
private String caUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根证书内容
|
||||||
|
*/
|
||||||
|
@NotEmpty(message = "根证书不能为空")
|
||||||
|
private String certText;
|
||||||
|
|
||||||
|
private String remark;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public static class CAQuery extends PageQuery {
|
||||||
|
|
||||||
|
private String caName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class CAView {
|
||||||
|
private Long id;
|
||||||
|
private String caName;
|
||||||
|
private String caUrl;
|
||||||
|
/**
|
||||||
|
* 密钥算法
|
||||||
|
*/
|
||||||
|
private String keyAlg;
|
||||||
|
/**
|
||||||
|
* 证书DN
|
||||||
|
*/
|
||||||
|
private String subject;
|
||||||
|
private String certText;
|
||||||
|
private String remark;
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.sunyard.chsm.dto;
|
package com.sunyard.chsm.model.dto;
|
||||||
|
|
||||||
import com.sunyard.chsm.model.PageQuery;
|
import com.sunyard.chsm.model.PageQuery;
|
||||||
import com.sunyard.chsm.model.Subject;
|
import com.sunyard.chsm.model.Subject;
|
||||||
@ -21,6 +21,7 @@ public abstract class KeyInfoDTO {
|
|||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Data
|
@Data
|
||||||
public static class Query extends PageQuery {
|
public static class Query extends PageQuery {
|
||||||
|
private Long appId;
|
||||||
private String status;
|
private String status;
|
||||||
private String keyType;
|
private String keyType;
|
||||||
}
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package com.sunyard.chsm.model.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liulu
|
||||||
|
* @since 2024/11/11
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("sp_ca_cert")
|
||||||
|
public class CaCert {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private String caName;
|
||||||
|
private String caUrl;
|
||||||
|
// SM2, RSA
|
||||||
|
private String keyAlg;
|
||||||
|
private String status;
|
||||||
|
private String subject;
|
||||||
|
private String serialNumber;
|
||||||
|
private String issuerDn;
|
||||||
|
private Date notBefore;
|
||||||
|
private Date notAfter;
|
||||||
|
private String pubKey;
|
||||||
|
|
||||||
|
private String certText;
|
||||||
|
|
||||||
|
private String remark;
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -17,6 +17,7 @@ public class TmkInfo {
|
|||||||
|
|
||||||
private String deviceSerial;
|
private String deviceSerial;
|
||||||
private String encTmk;
|
private String encTmk;
|
||||||
|
private String pubKey;
|
||||||
|
|
||||||
private String remark;
|
private String remark;
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
package com.sunyard.chsm.sdf;
|
||||||
|
|
||||||
|
import com.sunyard.chsm.enums.AlgMode;
|
||||||
|
import com.sunyard.chsm.enums.KeyAlg;
|
||||||
|
import com.sunyard.chsm.enums.Padding;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.sunyard.chsm.utils.gm.BCSM4Utils.DEFAULT_KEY_SIZE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实现 SdfApiService 接口中的通用逻辑
|
||||||
|
* 处理参数缺失时的默认参数,确保下层入参没有 null
|
||||||
|
* @author Cheney
|
||||||
|
*/
|
||||||
|
public abstract class AbstractSdfApiService implements SdfApiService {
|
||||||
|
|
||||||
|
private static final Map<KeyAlg, Integer> algKeyLen = new HashMap<>();
|
||||||
|
static {
|
||||||
|
algKeyLen.put( KeyAlg.SM4, DEFAULT_KEY_SIZE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理算法的默认密钥长度
|
||||||
|
* @param alg 算法,只支持对称算法
|
||||||
|
* 密钥长度根据 alg 指定的算法自动选择。
|
||||||
|
* @return 密钥
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public byte[] genSymKey(KeyAlg alg) {
|
||||||
|
return genSymKey( alg, algKeyLen.get( alg ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对称加密
|
||||||
|
* 内部实现和解密共用逻辑
|
||||||
|
* @param alg 算法,只支持对称算法
|
||||||
|
* @param key 密钥值,明文
|
||||||
|
* @param data 原始数据
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public byte[] symEncrypt(KeyAlg alg, byte[] key, byte[] data){
|
||||||
|
return symEncrypt( alg, AlgMode.ECB, Padding.PCKS5Padding, key, data );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对称解密
|
||||||
|
* 内部实现和加密共用逻辑
|
||||||
|
* @param alg 算法,只支持对称算法
|
||||||
|
* @param key 密钥值,明文
|
||||||
|
* @param data 密文数据
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public byte[] symDecrypt(KeyAlg alg, byte[] key, byte[] data) {
|
||||||
|
return symDecrypt( alg, AlgMode.ECB, Padding.PCKS5Padding, key, data );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,30 +1,50 @@
|
|||||||
package com.sunyard.chsm.sdf;
|
package com.sunyard.chsm.sdf;
|
||||||
|
|
||||||
|
|
||||||
|
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.model.EccKey;
|
import com.sunyard.chsm.sdf.model.EccKey;
|
||||||
import com.sunyard.chsm.sdf.model.EccPriKey;
|
import com.sunyard.chsm.sdf.util.LangUtils;
|
||||||
import com.sunyard.chsm.sdf.model.EccPubKey;
|
|
||||||
import com.sunyard.chsm.utils.gm.BCSM2Utils;
|
import com.sunyard.chsm.utils.gm.BCSM2Utils;
|
||||||
import com.sunyard.chsm.utils.gm.BCSM3Utils;
|
import com.sunyard.chsm.utils.gm.BCSM3Utils;
|
||||||
|
import com.sunyard.chsm.utils.gm.BCSM4Utils;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.bouncycastle.crypto.digests.SM3Digest;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.bouncycastle.crypto.macs.HMac;
|
|
||||||
import org.bouncycastle.crypto.params.KeyParameter;
|
|
||||||
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
|
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
|
||||||
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
|
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
|
||||||
import org.bouncycastle.util.BigIntegers;
|
import org.bouncycastle.util.BigIntegers;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.security.KeyPair;
|
import javax.crypto.BadPaddingException;
|
||||||
import java.security.SecureRandom;
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
import java.security.*;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author liulu
|
* 基于 BC 库的国密软算法实现
|
||||||
|
* 当前实现类的接口返回的对称密钥和私钥认为是明文,在上层 Service 进行使用和存储时的加密和解密运算。
|
||||||
|
* <p>
|
||||||
|
* 主密钥:
|
||||||
|
* - 生成。 软随机数。项目启动时不存在则自动生成。
|
||||||
|
* - 存储。 存储在 SC_PARAM_CONF 表, KEY 为 mk 的字段,值为固定的 48 字节,以 HEX 格式 96 字节存储。
|
||||||
|
* 前 16 字节为主密钥值,后 32 字节为主密钥值使用 SM3 计算的校验值。
|
||||||
|
* - 同步。基于数据库进行导入、导出、和备份、恢复。多台应用服务器连接同一个数据库,无需同步。
|
||||||
|
* - 使用。顶层密钥,用于保护其他存于数据的密钥。
|
||||||
|
*
|
||||||
|
* @author liulu 、Cheney
|
||||||
* @since 2024/10/23
|
* @since 2024/10/23
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class BCSdfApiService implements SdfApiService {
|
public class BCSdfApiService extends AbstractSdfApiService {
|
||||||
|
|
||||||
|
public BCSdfApiService() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] generateRandom(int len) {
|
public byte[] generateRandom(int len) {
|
||||||
@ -33,6 +53,82 @@ public class BCSdfApiService implements SdfApiService {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成对称算法密钥
|
||||||
|
*
|
||||||
|
* @param alg 算法,只支持对称算法
|
||||||
|
* @param keyLen 密钥长度(bit),只针对密钥长度可变的算法。
|
||||||
|
* 禁止传 null
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public byte[] genSymKey(KeyAlg alg, Integer keyLen) {
|
||||||
|
switch (alg) {
|
||||||
|
case SM4: {
|
||||||
|
if (null == keyLen || keyLen != BCSM4Utils.DEFAULT_KEY_SIZE) {
|
||||||
|
throw new IllegalArgumentException("Invalid key length: " + keyLen);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return BCSM4Utils.generateKey();
|
||||||
|
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
|
||||||
|
throw new RuntimeException("算法实现错误", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new IllegalArgumentException("Unsupported algorithm: " + alg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] symEncrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
||||||
|
return symCalc(Cipher.ENCRYPT_MODE, alg, mode, padding, key, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] symDecrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
||||||
|
return symCalc(Cipher.DECRYPT_MODE, alg, mode, padding, key, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对称加解密的统一实现
|
||||||
|
*
|
||||||
|
* @param alg 算法,只支持对称算法
|
||||||
|
* @param key 密钥值,明文
|
||||||
|
* @param data 加密时明文数据,解密时为密文数据
|
||||||
|
*/
|
||||||
|
private byte[] symCalc(int cipherMode, KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
||||||
|
if (alg.getCategory() != KeyCategory.SYM_KEY) {
|
||||||
|
throw new IllegalArgumentException("Must SYM_KEY, unsupported algorithm: " + alg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 算法
|
||||||
|
String algName = null;
|
||||||
|
if (alg == KeyAlg.SM4) {
|
||||||
|
algName = "SM4/";
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unsupported algorithm: " + alg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 算法轮模式
|
||||||
|
algName += mode.getCode() + "/";
|
||||||
|
|
||||||
|
// 填充模式
|
||||||
|
algName += padding.getCode();
|
||||||
|
|
||||||
|
|
||||||
|
Cipher cipher = null;
|
||||||
|
try {
|
||||||
|
cipher = BCSM4Utils.generateECBCipher(algName, cipherMode, key);
|
||||||
|
return cipher.doFinal(data);
|
||||||
|
} catch (IllegalBlockSizeException | BadPaddingException | NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException | InvalidKeyException e) {
|
||||||
|
throw new RuntimeException("算法执行错误", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@Override
|
@Override
|
||||||
public EccKey genKeyPairEcc() {
|
public EccKey genKeyPairEcc() {
|
||||||
@ -43,8 +139,7 @@ public class BCSdfApiService implements SdfApiService {
|
|||||||
byte[] x = pubKey.getQ().getXCoord().getEncoded();
|
byte[] x = pubKey.getQ().getXCoord().getEncoded();
|
||||||
byte[] y = pubKey.getQ().getYCoord().getEncoded();
|
byte[] y = pubKey.getQ().getYCoord().getEncoded();
|
||||||
byte[] d = BigIntegers.asUnsignedByteArray(32, priKey.getD());
|
byte[] d = BigIntegers.asUnsignedByteArray(32, priKey.getD());
|
||||||
|
return new EccKey(LangUtils.merge(x, y), d);
|
||||||
return new EccKey(new EccPubKey(256, x, y), new EccPriKey(256, d));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -55,14 +150,7 @@ public class BCSdfApiService implements SdfApiService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] hmac(byte[] key, byte[] srcData) {
|
public byte[] hmac(byte[] key, byte[] srcData) {
|
||||||
KeyParameter keyParameter = new KeyParameter(key);
|
return BCSM3Utils.hmac(key, srcData);
|
||||||
SM3Digest digest = new SM3Digest();
|
|
||||||
HMac mac = new HMac(digest);
|
|
||||||
mac.init(keyParameter);
|
|
||||||
mac.update(srcData, 0, srcData.length);
|
|
||||||
byte[] result = new byte[mac.getMacSize()];
|
|
||||||
mac.doFinal(result, 0);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
package com.sunyard.chsm.sdf;
|
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.model.EccKey;
|
import com.sunyard.chsm.sdf.model.EccKey;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author liulu
|
* @author liulu
|
||||||
* @since 2024/10/23
|
* @since 2024/10/23
|
||||||
@ -18,6 +22,44 @@ public interface SdfApiService {
|
|||||||
*/
|
*/
|
||||||
byte[] generateRandom(int len);
|
byte[] generateRandom(int len);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成对称密钥
|
||||||
|
* @param alg 算法,只支持对称算法
|
||||||
|
* @param keyLen 密钥长度(bit),只针对密钥长度可变的算法。
|
||||||
|
* 禁止传 null
|
||||||
|
* @return 对称密钥
|
||||||
|
*/
|
||||||
|
byte[] genSymKey(KeyAlg alg, Integer keyLen);
|
||||||
|
byte[] genSymKey(KeyAlg alg);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对称加密
|
||||||
|
* @param alg 算法,只支持对称算法
|
||||||
|
* @param mode 轮模式
|
||||||
|
* @param padding 填充模式
|
||||||
|
* @param key 密钥值,明文
|
||||||
|
* @param data 原始数据
|
||||||
|
*/
|
||||||
|
byte[] symEncrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data);
|
||||||
|
byte[] symEncrypt(KeyAlg alg, byte[] key, byte[] data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对称解密
|
||||||
|
* @param alg 算法,只支持对称算法
|
||||||
|
* @param key 密钥值,明文
|
||||||
|
* @param mode 轮模式
|
||||||
|
* @param padding 填充模式
|
||||||
|
* @param data 密文数据
|
||||||
|
*/
|
||||||
|
byte[] symDecrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data);
|
||||||
|
byte[] symDecrypt(KeyAlg alg, byte[] key, byte[] data);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 产生ECC密钥对并输出
|
* 产生ECC密钥对并输出
|
||||||
*
|
*
|
||||||
|
@ -2,14 +2,16 @@ package com.sunyard.chsm.sdf.adapter;
|
|||||||
|
|
||||||
import com.sunyard.chsm.sdf.model.DeviceInfo;
|
import com.sunyard.chsm.sdf.model.DeviceInfo;
|
||||||
import com.sunyard.chsm.sdf.model.EccKey;
|
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.util.LangUtils;
|
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.BCSM2Utils;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
import org.bouncycastle.crypto.InvalidCipherTextException;
|
||||||
|
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
||||||
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
|
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
|
||||||
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
|
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
|
||||||
import org.bouncycastle.math.ec.ECPoint;
|
import org.bouncycastle.math.ec.ECPoint;
|
||||||
|
import org.bouncycastle.util.Arrays;
|
||||||
import org.bouncycastle.util.BigIntegers;
|
import org.bouncycastle.util.BigIntegers;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
@ -29,7 +31,7 @@ public class BcSdfApiAdaptor implements SdfApiAdapter {
|
|||||||
deviceInfo = new DeviceInfo();
|
deviceInfo = new DeviceInfo();
|
||||||
deviceInfo.setIssuerName("BC");
|
deviceInfo.setIssuerName("BC");
|
||||||
deviceInfo.setDeviceName("BC-3000");
|
deviceInfo.setDeviceName("BC-3000");
|
||||||
deviceInfo.setDeviceSerial("BC00202411051037");
|
deviceInfo.setDeviceSerial("BC202411051037");
|
||||||
deviceInfo.setDeviceVersion(1);
|
deviceInfo.setDeviceVersion(1);
|
||||||
deviceInfo.setStandardVersion(1);
|
deviceInfo.setStandardVersion(1);
|
||||||
deviceInfo.setAsymAlgAbility(new long[]{7493065891348563935L, 3000543215027029126L});
|
deviceInfo.setAsymAlgAbility(new long[]{7493065891348563935L, 3000543215027029126L});
|
||||||
@ -70,10 +72,10 @@ public class BcSdfApiAdaptor implements SdfApiAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EccPubKey exportEncPublicKeyECC(String sessionHandle, int uiKeyIndex) {
|
public byte[] exportEncPublicKeyECC(String sessionHandle, int uiKeyIndex) {
|
||||||
BigInteger d = new BigInteger(1, getD());
|
BigInteger d = new BigInteger(1, getD());
|
||||||
ECPoint q = BCSM2Utils.G_POINT.multiply(d).normalize();
|
ECPoint q = BCSM2Utils.G_POINT.multiply(d).normalize();
|
||||||
return new EccPubKey(256, q.getXCoord().getEncoded(), q.getYCoord().getEncoded());
|
return LangUtils.merge(q.getXCoord().getEncoded(), q.getYCoord().getEncoded());
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getD() {
|
private byte[] getD() {
|
||||||
@ -93,7 +95,29 @@ public class BcSdfApiAdaptor implements SdfApiAdapter {
|
|||||||
byte[] x = pubKey.getQ().getXCoord().getEncoded();
|
byte[] x = pubKey.getQ().getXCoord().getEncoded();
|
||||||
byte[] y = pubKey.getQ().getYCoord().getEncoded();
|
byte[] y = pubKey.getQ().getYCoord().getEncoded();
|
||||||
byte[] d = BigIntegers.asUnsignedByteArray(32, priKey.getD());
|
byte[] d = BigIntegers.asUnsignedByteArray(32, priKey.getD());
|
||||||
return new EccKey(new EccPubKey(256, x, y), new EccPriKey(256, d));
|
return new EccKey(LangUtils.merge(x, y), d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] exchangeDigitEnvelopeBaseOnECC(String sessionHandle, int uiKeyIndex, byte[] pubKey, byte[] pucEncDateIn) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] externalEncryptECC(String sessionHandle, byte[] pubKey, byte[] pucData) {
|
||||||
|
if (pubKey[0] == 4) {
|
||||||
|
pubKey = Arrays.copyOfRange(pubKey, 1, 65);
|
||||||
|
}
|
||||||
|
ECPublicKeyParameters parameters = BCECUtils.createECPublicKeyParameters(
|
||||||
|
Arrays.copyOfRange(pubKey, 0, 32),
|
||||||
|
Arrays.copyOfRange(pubKey, 32, 64)
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
byte[] encrypt = BCSM2Utils.encrypt(parameters, pucData);
|
||||||
|
return Arrays.copyOfRange(encrypt, 1, encrypt.length);
|
||||||
|
} catch (InvalidCipherTextException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,11 +2,12 @@ package com.sunyard.chsm.sdf.adapter;
|
|||||||
|
|
||||||
import com.sun.jna.Pointer;
|
import com.sun.jna.Pointer;
|
||||||
import com.sun.jna.ptr.PointerByReference;
|
import com.sun.jna.ptr.PointerByReference;
|
||||||
|
import com.sunyard.chsm.sdf.context.AlgId;
|
||||||
import com.sunyard.chsm.sdf.lib.SdfLibrary;
|
import com.sunyard.chsm.sdf.lib.SdfLibrary;
|
||||||
import com.sunyard.chsm.sdf.model.DeviceInfo;
|
import com.sunyard.chsm.sdf.model.DeviceInfo;
|
||||||
import com.sunyard.chsm.sdf.model.EccKey;
|
import com.sunyard.chsm.sdf.model.EccKey;
|
||||||
import com.sunyard.chsm.sdf.model.EccPubKey;
|
|
||||||
import com.sunyard.chsm.sdf.model.SDF_DeviceInfo;
|
import com.sunyard.chsm.sdf.model.SDF_DeviceInfo;
|
||||||
|
import com.sunyard.chsm.sdf.util.LangUtils;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
@ -117,15 +118,28 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EccPubKey exportEncPublicKeyECC(String sessionHandle, int uiKeyIndex) {
|
public byte[] exportEncPublicKeyECC(String sessionHandle, int uiKeyIndex) {
|
||||||
byte[] pubKey = new byte[132];
|
byte[] pubKey = new byte[132];
|
||||||
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||||
sdfLibrary.SDF_ExportEncPublicKey_ECC(hSessionHandle, uiKeyIndex, pubKey);
|
sdfLibrary.SDF_ExportEncPublicKey_ECC(hSessionHandle, uiKeyIndex, pubKey);
|
||||||
return new EccPubKey(256, Arrays.copyOfRange(pubKey, 36, 68), Arrays.copyOfRange(pubKey, 100, 132));
|
return LangUtils.merge(Arrays.copyOfRange(pubKey, 36, 68), Arrays.copyOfRange(pubKey, 100, 132));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EccKey generateKeyPairECC(String sessionHandle, String alg, int uiKeyBits) {
|
public EccKey generateKeyPairECC(String sessionHandle, String alg, int uiKeyBits) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] exchangeDigitEnvelopeBaseOnECC(String sessionHandle, int uiKeyIndex, byte[] pubKey, byte[] pucEncDateIn) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] externalEncryptECC(String sessionHandle, byte[] pubKey, byte[] pucData) {
|
||||||
|
byte[] encData = new byte[128 + 32 + 4 + pucData.length];
|
||||||
|
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||||
|
sdfLibrary.SDF_ExternalEncrypt_ECC(hSessionHandle, getAlgId(AlgId.SGD_SM2_3), pubKey, pucData, pucData.length, encData);
|
||||||
|
return encData;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package com.sunyard.chsm.sdf.adapter;
|
|||||||
|
|
||||||
import com.sunyard.chsm.sdf.model.DeviceInfo;
|
import com.sunyard.chsm.sdf.model.DeviceInfo;
|
||||||
import com.sunyard.chsm.sdf.model.EccKey;
|
import com.sunyard.chsm.sdf.model.EccKey;
|
||||||
import com.sunyard.chsm.sdf.model.EccPubKey;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author liulu
|
* @author liulu
|
||||||
@ -54,9 +53,9 @@ public interface SdfApiAdapter {
|
|||||||
* 导出ECC加密公钥
|
* 导出ECC加密公钥
|
||||||
*
|
*
|
||||||
* @param uiKeyIndex 密码设备存储的ECC密钥对索引值
|
* @param uiKeyIndex 密码设备存储的ECC密钥对索引值
|
||||||
* @return pucPublicKeyEcc 返回ECC加密公钥
|
* @return pucPublicKeyEcc 返回ECC加密公钥x+y
|
||||||
*/
|
*/
|
||||||
EccPubKey exportEncPublicKeyECC(String sessionHandle, int uiKeyIndex);
|
byte[] exportEncPublicKeyECC(String sessionHandle, int uiKeyIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 产生ECC密钥对并输出
|
* 产生ECC密钥对并输出
|
||||||
@ -68,4 +67,10 @@ public interface SdfApiAdapter {
|
|||||||
EccKey generateKeyPairECC(String sessionHandle, String alg, int uiKeyBits);
|
EccKey generateKeyPairECC(String sessionHandle, String alg, int uiKeyBits);
|
||||||
|
|
||||||
|
|
||||||
|
byte[] exchangeDigitEnvelopeBaseOnECC(String sessionHandle, int uiKeyIndex, byte[] pubKey, byte[] pucEncDateIn);
|
||||||
|
|
||||||
|
|
||||||
|
byte[] externalEncryptECC(String sessionHandle, byte[] pubKey, byte[] pucData);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,10 @@ import lombok.NoArgsConstructor;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class EccKey {
|
public class EccKey {
|
||||||
|
|
||||||
private EccPubKey pubKey;
|
private byte[] pubKey;
|
||||||
private EccPriKey priKey;
|
private byte[] priKey;
|
||||||
|
|
||||||
public EccKey(EccPubKey pubKey, EccPriKey priKey) {
|
public EccKey(byte[] pubKey, byte[] priKey) {
|
||||||
this.pubKey = pubKey;
|
this.pubKey = pubKey;
|
||||||
this.priKey = priKey;
|
this.priKey = priKey;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.sunyard.chsm.service;
|
package com.sunyard.chsm.service;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.sunyard.chsm.dto.CertDTO;
|
import com.sunyard.chsm.model.dto.CertDTO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author liulu
|
* @author liulu
|
||||||
@ -12,4 +12,6 @@ public interface AppCertService {
|
|||||||
Page<CertDTO.ACView> selectPageList(CertDTO.Query query);
|
Page<CertDTO.ACView> selectPageList(CertDTO.Query query);
|
||||||
|
|
||||||
void importCert(CertDTO.ImportCert importCert);
|
void importCert(CertDTO.ImportCert importCert);
|
||||||
|
|
||||||
|
void delete(Long id);
|
||||||
}
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.sunyard.chsm.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.sunyard.chsm.model.dto.CertDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liulu
|
||||||
|
* @since 2024/11/11
|
||||||
|
*/
|
||||||
|
public interface CaCertService {
|
||||||
|
|
||||||
|
Page<CertDTO.CAView> selectPageList(CertDTO.CAQuery query);
|
||||||
|
|
||||||
|
Long save(CertDTO.CaInfo caInfo);
|
||||||
|
|
||||||
|
void update(CertDTO.CaInfo update);
|
||||||
|
|
||||||
|
void delete(Long id);
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
package com.sunyard.chsm.service;
|
package com.sunyard.chsm.service;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.sunyard.chsm.dto.KeyInfoDTO;
|
import com.sunyard.chsm.model.dto.KeyInfoDTO;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.sunyard.chsm.service;
|
||||||
|
|
||||||
|
import com.sunyard.chsm.model.entity.KeyRecord;
|
||||||
|
|
||||||
|
public interface KeyRecordService {
|
||||||
|
KeyRecord selectById(Long id);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 keyId 查找密钥
|
||||||
|
* @param keyId keyId
|
||||||
|
* @return 可用值或 null
|
||||||
|
*/
|
||||||
|
KeyRecord selectByKeyId(Long keyId);
|
||||||
|
}
|
@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.sunyard.chsm.dto.CertDTO;
|
|
||||||
import com.sunyard.chsm.enums.KeyCategory;
|
import com.sunyard.chsm.enums.KeyCategory;
|
||||||
import com.sunyard.chsm.enums.KeyStatus;
|
import com.sunyard.chsm.enums.KeyStatus;
|
||||||
import com.sunyard.chsm.enums.KeyUsage;
|
import com.sunyard.chsm.enums.KeyUsage;
|
||||||
@ -12,6 +11,7 @@ import com.sunyard.chsm.mapper.AppCertMapper;
|
|||||||
import com.sunyard.chsm.mapper.ApplicationMapper;
|
import com.sunyard.chsm.mapper.ApplicationMapper;
|
||||||
import com.sunyard.chsm.mapper.KeyInfoMapper;
|
import com.sunyard.chsm.mapper.KeyInfoMapper;
|
||||||
import com.sunyard.chsm.mapper.SpKeyRecordMapper;
|
import com.sunyard.chsm.mapper.SpKeyRecordMapper;
|
||||||
|
import com.sunyard.chsm.model.dto.CertDTO;
|
||||||
import com.sunyard.chsm.model.entity.AppCert;
|
import com.sunyard.chsm.model.entity.AppCert;
|
||||||
import com.sunyard.chsm.model.entity.Application;
|
import com.sunyard.chsm.model.entity.Application;
|
||||||
import com.sunyard.chsm.model.entity.KeyInfo;
|
import com.sunyard.chsm.model.entity.KeyInfo;
|
||||||
@ -23,6 +23,7 @@ import com.sunyard.chsm.utils.gm.BCSM2Utils;
|
|||||||
import com.sunyard.chsm.utils.gm.BCSM4Utils;
|
import com.sunyard.chsm.utils.gm.BCSM4Utils;
|
||||||
import com.sunyard.chsm.utils.gm.cert.BCSM2CertUtils;
|
import com.sunyard.chsm.utils.gm.cert.BCSM2CertUtils;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.bouncycastle.asn1.ASN1BitString;
|
import org.bouncycastle.asn1.ASN1BitString;
|
||||||
import org.bouncycastle.asn1.ASN1Integer;
|
import org.bouncycastle.asn1.ASN1Integer;
|
||||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
||||||
@ -36,7 +37,6 @@ import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
|
|||||||
import org.bouncycastle.util.BigIntegers;
|
import org.bouncycastle.util.BigIntegers;
|
||||||
import org.bouncycastle.util.encoders.Hex;
|
import org.bouncycastle.util.encoders.Hex;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.data.util.Pair;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
@ -173,6 +173,8 @@ public class AppCertServiceImpl implements AppCertService {
|
|||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new IllegalArgumentException("证书内容格式错误,无法解析");
|
throw new IllegalArgumentException("证书内容格式错误,无法解析");
|
||||||
}
|
}
|
||||||
|
Assert.isTrue(Objects.equals(signCert.getSubjectX500Principal().getName(), encCert.getSubjectX500Principal().getName()),
|
||||||
|
"证书主题不一致");
|
||||||
PublicKey signPk = signCert.getPublicKey();
|
PublicKey signPk = signCert.getPublicKey();
|
||||||
String signPkHex = BCECUtils.getHexPubKey((BCECPublicKey) signPk);
|
String signPkHex = BCECUtils.getHexPubKey((BCECPublicKey) signPk);
|
||||||
String encPkHex = BCECUtils.getHexPubKey((BCECPublicKey) encCert.getPublicKey());
|
String encPkHex = BCECUtils.getHexPubKey((BCECPublicKey) encCert.getPublicKey());
|
||||||
@ -192,7 +194,7 @@ public class AppCertServiceImpl implements AppCertService {
|
|||||||
log.error("解密加密密钥信封异常", ex);
|
log.error("解密加密密钥信封异常", ex);
|
||||||
throw new IllegalArgumentException("加密密钥信封格式错误,解密失败");
|
throw new IllegalArgumentException("加密密钥信封格式错误,解密失败");
|
||||||
}
|
}
|
||||||
Assert.isTrue(Objects.equals(encPkHex, keys.getFirst()), "加密证书和私钥不匹配");
|
Assert.isTrue(Objects.equals(encPkHex, keys.getLeft()), "加密证书和私钥不匹配");
|
||||||
|
|
||||||
AppCert exist = appCertMapper.selectBySN(signCert.getSerialNumber().toString());
|
AppCert exist = appCertMapper.selectBySN(signCert.getSerialNumber().toString());
|
||||||
Assert.isNull(exist, "签名证书已经存在");
|
Assert.isNull(exist, "签名证书已经存在");
|
||||||
@ -207,8 +209,8 @@ public class AppCertServiceImpl implements AppCertService {
|
|||||||
importCert.setCertType(KeyUsage.ENCRYPT_DECRYPT.getCode());
|
importCert.setCertType(KeyUsage.ENCRYPT_DECRYPT.getCode());
|
||||||
importCert.setCertText(importCert.getEncCertText());
|
importCert.setCertText(importCert.getEncCertText());
|
||||||
AppCert enc = genCert(encCert, keyInfo.getApplicationId(), record, importCert);
|
AppCert enc = genCert(encCert, keyInfo.getApplicationId(), record, importCert);
|
||||||
enc.setPubKey(keys.getFirst());
|
enc.setPubKey(keys.getLeft());
|
||||||
byte[] encPri = sdfApiService.encryptByTMK(keys.getSecond());
|
byte[] encPri = sdfApiService.encryptByTMK(keys.getRight());
|
||||||
enc.setEncPriKey(Hex.toHexString(encPri));
|
enc.setEncPriKey(Hex.toHexString(encPri));
|
||||||
appCertMapper.insert(enc);
|
appCertMapper.insert(enc);
|
||||||
|
|
||||||
@ -274,4 +276,25 @@ public class AppCertServiceImpl implements AppCertService {
|
|||||||
return Pair.of(Hex.toHexString(xy), pd);
|
return Pair.of(Hex.toHexString(xy), pd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(Long id) {
|
||||||
|
|
||||||
|
AppCert appCert = appCertMapper.selectById(id);
|
||||||
|
Assert.notNull(appCert, "证书不存在");
|
||||||
|
|
||||||
|
if (appCert.getSingle()) {
|
||||||
|
appCertMapper.deleteById(id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<AppCert> appCerts = appCertMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<AppCert>()
|
||||||
|
.eq(AppCert::getKeyId, appCert.getKeyId())
|
||||||
|
.eq(AppCert::getSubject, appCert.getSubject())
|
||||||
|
|
||||||
|
);
|
||||||
|
appCertMapper.deleteBatchIds(appCerts.stream().map(AppCert::getId).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,143 @@
|
|||||||
|
package com.sunyard.chsm.service.impl;
|
||||||
|
|
||||||
|
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.mapper.CaCertMapper;
|
||||||
|
import com.sunyard.chsm.model.dto.CertDTO;
|
||||||
|
import com.sunyard.chsm.model.entity.CaCert;
|
||||||
|
import com.sunyard.chsm.service.CaCertService;
|
||||||
|
import com.sunyard.chsm.utils.gm.BCECUtils;
|
||||||
|
import com.sunyard.chsm.utils.gm.cert.BCSM2CertUtils;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liulu
|
||||||
|
* @since 2024/11/11
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
public class CaCertServiceImpl implements CaCertService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CaCertMapper caCertMapper;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page<CertDTO.CAView> selectPageList(CertDTO.CAQuery query) {
|
||||||
|
IPage<CaCert> page = caCertMapper.selectPage(
|
||||||
|
new Page<>(query.getPageNumber(), query.getPageSize()),
|
||||||
|
new LambdaQueryWrapper<CaCert>()
|
||||||
|
.like(StringUtils.hasText(query.getCaName()), CaCert::getCaName, query.getCaName())
|
||||||
|
.orderByDesc(CaCert::getCreateTime)
|
||||||
|
);
|
||||||
|
List<CaCert> records = page.getRecords();
|
||||||
|
if (CollectionUtils.isEmpty(records)) {
|
||||||
|
return new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<CertDTO.CAView> viewList = records.stream()
|
||||||
|
.map(it -> {
|
||||||
|
CertDTO.CAView view = new CertDTO.CAView();
|
||||||
|
BeanUtils.copyProperties(it, view);
|
||||||
|
return view;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
return new Page<CertDTO.CAView>(page.getCurrent(), page.getSize(), page.getTotal()).setRecords(viewList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long save(CertDTO.CaInfo caInfo) {
|
||||||
|
checkName(caInfo.getCaName());
|
||||||
|
|
||||||
|
X509Certificate x509Cert;
|
||||||
|
try {
|
||||||
|
x509Cert = BCSM2CertUtils.getX509Cert(caInfo.getCertText());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new IllegalArgumentException("证书内容格式错误,无法解析");
|
||||||
|
}
|
||||||
|
|
||||||
|
CaCert cert = genCaCert(caInfo, x509Cert);
|
||||||
|
cert.setId(IdWorker.getId());
|
||||||
|
cert.setCreateTime(LocalDateTime.now());
|
||||||
|
caCertMapper.insert(cert);
|
||||||
|
|
||||||
|
return cert.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(CertDTO.CaInfo update) {
|
||||||
|
Assert.notNull(update.getId(), "id不能为空");
|
||||||
|
CaCert exist = caCertMapper.selectById(update.getId());
|
||||||
|
Assert.notNull(exist, "id对应的CA不存在");
|
||||||
|
|
||||||
|
if (!Objects.equals(exist.getCaName(), update.getCaName())) {
|
||||||
|
checkName(update.getCaName());
|
||||||
|
}
|
||||||
|
|
||||||
|
X509Certificate x509Cert;
|
||||||
|
try {
|
||||||
|
x509Cert = BCSM2CertUtils.getX509Cert(update.getCertText());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new IllegalArgumentException("证书内容格式错误,无法解析");
|
||||||
|
}
|
||||||
|
|
||||||
|
CaCert cert = genCaCert(update, x509Cert);
|
||||||
|
cert.setId(update.getId());
|
||||||
|
cert.setUpdateTime(LocalDateTime.now());
|
||||||
|
caCertMapper.updateById(cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static CaCert genCaCert(CertDTO.CaInfo caInfo, X509Certificate x509Cert) {
|
||||||
|
|
||||||
|
CaCert cert = new CaCert();
|
||||||
|
cert.setKeyAlg(caInfo.getKeyAlg());
|
||||||
|
cert.setCaName(caInfo.getCaName());
|
||||||
|
cert.setCaUrl(caInfo.getCaUrl());
|
||||||
|
cert.setCertText(caInfo.getCertText());
|
||||||
|
cert.setRemark(caInfo.getRemark());
|
||||||
|
|
||||||
|
cert.setSubject(x509Cert.getSubjectX500Principal().getName());
|
||||||
|
cert.setSerialNumber(x509Cert.getSerialNumber().toString());
|
||||||
|
cert.setIssuerDn(x509Cert.getIssuerX500Principal().getName());
|
||||||
|
cert.setNotBefore(x509Cert.getNotBefore());
|
||||||
|
cert.setNotAfter(x509Cert.getNotAfter());
|
||||||
|
|
||||||
|
PublicKey publicKey = x509Cert.getPublicKey();
|
||||||
|
String hexPubKey = BCECUtils.getHexPubKey((BCECPublicKey) publicKey);
|
||||||
|
cert.setPubKey(hexPubKey);
|
||||||
|
return cert;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkName(String name) {
|
||||||
|
|
||||||
|
CaCert exist = caCertMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<CaCert>().eq(CaCert::getCaName, name)
|
||||||
|
);
|
||||||
|
Assert.isNull(exist, "CA名称已经存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(Long id) {
|
||||||
|
caCertMapper.deleteById(id);
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,6 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.sunyard.chsm.dto.KeyInfoDTO;
|
|
||||||
import com.sunyard.chsm.enums.EnableStatus;
|
import com.sunyard.chsm.enums.EnableStatus;
|
||||||
import com.sunyard.chsm.enums.KeyCategory;
|
import com.sunyard.chsm.enums.KeyCategory;
|
||||||
import com.sunyard.chsm.enums.KeyStatus;
|
import com.sunyard.chsm.enums.KeyStatus;
|
||||||
@ -15,6 +14,7 @@ import com.sunyard.chsm.mapper.KeyCsrMapper;
|
|||||||
import com.sunyard.chsm.mapper.KeyInfoMapper;
|
import com.sunyard.chsm.mapper.KeyInfoMapper;
|
||||||
import com.sunyard.chsm.mapper.KeyTemplateMapper;
|
import com.sunyard.chsm.mapper.KeyTemplateMapper;
|
||||||
import com.sunyard.chsm.mapper.SpKeyRecordMapper;
|
import com.sunyard.chsm.mapper.SpKeyRecordMapper;
|
||||||
|
import com.sunyard.chsm.model.dto.KeyInfoDTO;
|
||||||
import com.sunyard.chsm.model.entity.Application;
|
import com.sunyard.chsm.model.entity.Application;
|
||||||
import com.sunyard.chsm.model.entity.KeyCsr;
|
import com.sunyard.chsm.model.entity.KeyCsr;
|
||||||
import com.sunyard.chsm.model.entity.KeyInfo;
|
import com.sunyard.chsm.model.entity.KeyInfo;
|
||||||
@ -26,7 +26,6 @@ import com.sunyard.chsm.service.KeyInfoService;
|
|||||||
import com.sunyard.chsm.utils.JsonUtils;
|
import com.sunyard.chsm.utils.JsonUtils;
|
||||||
import com.sunyard.chsm.utils.gm.BCECUtils;
|
import com.sunyard.chsm.utils.gm.BCECUtils;
|
||||||
import com.sunyard.chsm.utils.gm.cert.CommonCertUtils;
|
import com.sunyard.chsm.utils.gm.cert.CommonCertUtils;
|
||||||
import com.sunyard.ssp.common.exception.SspwebException;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.bouncycastle.asn1.x500.X500Name;
|
import org.bouncycastle.asn1.x500.X500Name;
|
||||||
import org.bouncycastle.crypto.params.ECDomainParameters;
|
import org.bouncycastle.crypto.params.ECDomainParameters;
|
||||||
@ -94,6 +93,7 @@ public class KeyInfoServiceImpl implements KeyInfoService {
|
|||||||
LocalDateTime now = LocalDateTime.now();
|
LocalDateTime now = LocalDateTime.now();
|
||||||
LambdaQueryWrapper<KeyInfo> wrapper = new LambdaQueryWrapper<KeyInfo>()
|
LambdaQueryWrapper<KeyInfo> wrapper = new LambdaQueryWrapper<KeyInfo>()
|
||||||
.eq(StringUtils.hasText(query.getKeyType()), KeyInfo::getKeyType, query.getKeyType())
|
.eq(StringUtils.hasText(query.getKeyType()), KeyInfo::getKeyType, query.getKeyType())
|
||||||
|
.eq(Objects.nonNull(query.getAppId()), KeyInfo::getApplicationId, query.getAppId())
|
||||||
// .eq(StringUtils.hasText(query.getStatus()), KeyInfo::getStatus, query.getStatus())
|
// .eq(StringUtils.hasText(query.getStatus()), KeyInfo::getStatus, query.getStatus())
|
||||||
// .eq(KeyInfo::getDeleted, false)
|
// .eq(KeyInfo::getDeleted, false)
|
||||||
.orderByDesc(KeyInfo::getCreateTime);
|
.orderByDesc(KeyInfo::getCreateTime);
|
||||||
@ -123,7 +123,7 @@ public class KeyInfoServiceImpl implements KeyInfoService {
|
|||||||
return new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
|
return new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Long> appIds = records.stream().map(KeyInfo::getId).collect(Collectors.toList());
|
List<Long> appIds = records.stream().map(KeyInfo::getApplicationId).collect(Collectors.toList());
|
||||||
Map<Long, String> appNameMap = applicationMapper.selectBatchIds(appIds)
|
Map<Long, String> appNameMap = applicationMapper.selectBatchIds(appIds)
|
||||||
.stream().collect(Collectors.toMap(Application::getId, Application::getName));
|
.stream().collect(Collectors.toMap(Application::getId, Application::getName));
|
||||||
|
|
||||||
@ -282,13 +282,13 @@ public class KeyInfoServiceImpl implements KeyInfoService {
|
|||||||
record.setCheckValue(checkHash);
|
record.setCheckValue(checkHash);
|
||||||
} else {
|
} else {
|
||||||
EccKey eccKey = sdfApiService.genKeyPairEcc();
|
EccKey eccKey = sdfApiService.genKeyPairEcc();
|
||||||
byte[] d = eccKey.getPriKey().getD();
|
byte[] d = eccKey.getPriKey();
|
||||||
byte[] encD = sdfApiService.encryptByTMK(d);
|
byte[] encD = sdfApiService.encryptByTMK(d);
|
||||||
record.setKeyData(Hex.toHexString(encD));
|
record.setKeyData(Hex.toHexString(encD));
|
||||||
String checkHash = Hex.toHexString(sdfApiService.hash(d));
|
String checkHash = Hex.toHexString(sdfApiService.hash(d));
|
||||||
record.setCheckValue(checkHash);
|
record.setCheckValue(checkHash);
|
||||||
|
|
||||||
byte[] pubKeyBytes = eccKey.getPubKey().getPubKeyBytes();
|
byte[] pubKeyBytes = eccKey.getPubKey();
|
||||||
record.setPubKey(Hex.toHexString(pubKeyBytes));
|
record.setPubKey(Hex.toHexString(pubKeyBytes));
|
||||||
record.setPubIdx(record.getPubKey().substring(0, 8));
|
record.setPubIdx(record.getPubKey().substring(0, 8));
|
||||||
}
|
}
|
||||||
@ -329,7 +329,7 @@ public class KeyInfoServiceImpl implements KeyInfoService {
|
|||||||
try {
|
try {
|
||||||
if ((line = reader.readLine()) == null) break;
|
if ((line = reader.readLine()) == null) break;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new SspwebException("文件读取异常");
|
throw new IllegalArgumentException("文件读取异常");
|
||||||
}
|
}
|
||||||
if (ObjectUtils.isEmpty(line)) {
|
if (ObjectUtils.isEmpty(line)) {
|
||||||
continue;
|
continue;
|
||||||
@ -357,7 +357,7 @@ public class KeyInfoServiceImpl implements KeyInfoService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new SspwebException(e.getMessage());
|
throw new IllegalArgumentException(e.getMessage());
|
||||||
}
|
}
|
||||||
return String.format("恢复完成,共%d条数据,跳过已经存在的密钥%d条,恢复成功%d条,解析失败%d条", count, exd, suc, err);
|
return String.format("恢复完成,共%d条数据,跳过已经存在的密钥%d条,恢复成功%d条,解析失败%d条", count, exd, suc, err);
|
||||||
}
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package com.sunyard.chsm.service.impl;
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.sunyard.chsm.mapper.KeyRecordMapper;
|
||||||
|
import com.sunyard.chsm.model.entity.KeyRecord;
|
||||||
|
import com.sunyard.chsm.service.KeyRecordService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Cheney
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@Transactional
|
||||||
|
public class KeyRecordServiceImpl implements KeyRecordService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private KeyRecordMapper keyRecordMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyRecord selectById(Long id) {
|
||||||
|
return keyRecordMapper.selectById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyRecord selectByKeyId(Long keyId) {
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
LambdaQueryWrapper<KeyRecord> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
// 添加 keyId 的条件
|
||||||
|
queryWrapper.eq(KeyRecord::getKeyId, keyId);
|
||||||
|
// 添加 effectiveTime 小于当前时间的条件
|
||||||
|
queryWrapper.lt(KeyRecord::getEffectiveTime, now);
|
||||||
|
// 添加 expiredTime 大于当前时间的条件
|
||||||
|
queryWrapper.gt(KeyRecord::getExpiredTime, now);
|
||||||
|
|
||||||
|
return keyRecordMapper.selectOne(queryWrapper);
|
||||||
|
}
|
||||||
|
}
|
@ -170,7 +170,7 @@ public class BCSM4Utils extends GMBaseUtil {
|
|||||||
return mac.doFinal();
|
return mac.doFinal();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Cipher generateECBCipher(String algorithmName, int mode, byte[] key)
|
public static Cipher generateECBCipher(String algorithmName, int mode, byte[] key)
|
||||||
throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
|
throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
|
||||||
InvalidKeyException {
|
InvalidKeyException {
|
||||||
Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
|
Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
|
||||||
@ -179,7 +179,7 @@ public class BCSM4Utils extends GMBaseUtil {
|
|||||||
return cipher;
|
return cipher;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Cipher generateCBCCipher(String algorithmName, int mode, byte[] key, byte[] iv)
|
public static Cipher generateCBCCipher(String algorithmName, int mode, byte[] key, byte[] iv)
|
||||||
throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException,
|
throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException,
|
||||||
NoSuchProviderException, NoSuchPaddingException {
|
NoSuchProviderException, NoSuchPaddingException {
|
||||||
Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
|
Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
|
||||||
|
@ -70,23 +70,12 @@
|
|||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-core</artifactId>
|
<artifactId>hutool-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-pool2</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-lang3</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-codec</groupId>
|
<groupId>commons-codec</groupId>
|
||||||
<artifactId>commons-codec</artifactId>
|
<artifactId>commons-codec</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!--动态库调用依赖-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.java.dev.jna</groupId>
|
|
||||||
<artifactId>jna</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.swagger</groupId>
|
<groupId>io.swagger</groupId>
|
||||||
<artifactId>swagger-annotations</artifactId>
|
<artifactId>swagger-annotations</artifactId>
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
package com.sunyard.chsm.controller;
|
package com.sunyard.chsm.controller;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.sunyard.chsm.dto.CertDTO;
|
import com.sunyard.chsm.constant.AuditLogConst;
|
||||||
import com.sunyard.chsm.model.R;
|
import com.sunyard.chsm.model.R;
|
||||||
|
import com.sunyard.chsm.model.dto.CertDTO;
|
||||||
import com.sunyard.chsm.service.AppCertService;
|
import com.sunyard.chsm.service.AppCertService;
|
||||||
|
import com.sunyard.ssp.common.annotation.AuditControllerLog;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
@ -53,5 +56,17 @@ public class AppCertController {
|
|||||||
appCertService.importCert(importCert);
|
appCertService.importCert(importCert);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除证书
|
||||||
|
*
|
||||||
|
* @param id id
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
@DeleteMapping
|
||||||
|
@AuditControllerLog(description = "删除证书", operateType = AuditLogConst.DELETE)
|
||||||
|
public R<Void> delete(Long id) {
|
||||||
|
appCertService.delete(id);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
package com.sunyard.chsm.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.sunyard.chsm.constant.AuditLogConst;
|
||||||
|
import com.sunyard.chsm.model.R;
|
||||||
|
import com.sunyard.chsm.model.dto.CertDTO;
|
||||||
|
import com.sunyard.chsm.service.CaCertService;
|
||||||
|
import com.sunyard.ssp.common.annotation.AuditControllerLog;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CA管理接口
|
||||||
|
*
|
||||||
|
* @author liulu
|
||||||
|
* @since 2024/11/11
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/ca/cert")
|
||||||
|
public class CaController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CaCertService caCertService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询CA列表
|
||||||
|
*
|
||||||
|
* @param query query
|
||||||
|
* @return 列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/pageList")
|
||||||
|
public R<Page<CertDTO.CAView>> queryPageList(CertDTO.CAQuery query) {
|
||||||
|
|
||||||
|
Page<CertDTO.CAView> page = caCertService.selectPageList(query);
|
||||||
|
|
||||||
|
return R.data(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增CA
|
||||||
|
*
|
||||||
|
* @param caInfo 证书
|
||||||
|
*/
|
||||||
|
@PostMapping
|
||||||
|
public R<Long> save(@Valid @RequestBody CertDTO.CaInfo caInfo) {
|
||||||
|
Long id = caCertService.save(caInfo);
|
||||||
|
return R.data(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改CA
|
||||||
|
*
|
||||||
|
* @param update 参数
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
@PutMapping
|
||||||
|
@AuditControllerLog(description = "修改CA", operateType = AuditLogConst.UPDATE)
|
||||||
|
public R<Void> update(@Valid @RequestBody CertDTO.CaInfo update) {
|
||||||
|
caCertService.update(update);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除CA
|
||||||
|
*
|
||||||
|
* @param id id
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
@DeleteMapping
|
||||||
|
@AuditControllerLog(description = "删除CA", operateType = AuditLogConst.DELETE)
|
||||||
|
public R<Void> delete(Long id) {
|
||||||
|
caCertService.delete(id);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
package com.sunyard.chsm.controller;
|
package com.sunyard.chsm.controller;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.sunyard.chsm.dto.KeyInfoDTO;
|
|
||||||
import com.sunyard.chsm.enums.KeyCategory;
|
import com.sunyard.chsm.enums.KeyCategory;
|
||||||
import com.sunyard.chsm.model.R;
|
import com.sunyard.chsm.model.R;
|
||||||
|
import com.sunyard.chsm.model.dto.KeyInfoDTO;
|
||||||
import com.sunyard.chsm.service.KeyInfoService;
|
import com.sunyard.chsm.service.KeyInfoService;
|
||||||
import com.sunyard.chsm.utils.DateFormat;
|
import com.sunyard.chsm.utils.DateFormat;
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package com.sunyard.chsm.controller;
|
package com.sunyard.chsm.controller;
|
||||||
|
|
||||||
import com.sunyard.chsm.constant.AuditLogConst;
|
import com.sunyard.chsm.constant.AuditLogConst;
|
||||||
import com.sunyard.chsm.dto.KeyInfoDTO;
|
|
||||||
import com.sunyard.chsm.enums.KeyStatus;
|
import com.sunyard.chsm.enums.KeyStatus;
|
||||||
import com.sunyard.chsm.model.Option;
|
import com.sunyard.chsm.model.Option;
|
||||||
import com.sunyard.chsm.model.R;
|
import com.sunyard.chsm.model.R;
|
||||||
|
import com.sunyard.chsm.model.dto.KeyInfoDTO;
|
||||||
import com.sunyard.chsm.service.KeyInfoService;
|
import com.sunyard.chsm.service.KeyInfoService;
|
||||||
import com.sunyard.ssp.common.annotation.AuditControllerLog;
|
import com.sunyard.ssp.common.annotation.AuditControllerLog;
|
||||||
import com.sunyard.ssp.common.exception.SspwebException;
|
import com.sunyard.ssp.common.exception.SspwebException;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package com.sunyard.chsm.controller;
|
package com.sunyard.chsm.controller;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.sunyard.chsm.dto.KeyInfoDTO;
|
|
||||||
import com.sunyard.chsm.enums.KeyCategory;
|
import com.sunyard.chsm.enums.KeyCategory;
|
||||||
import com.sunyard.chsm.model.R;
|
import com.sunyard.chsm.model.R;
|
||||||
|
import com.sunyard.chsm.model.dto.KeyInfoDTO;
|
||||||
import com.sunyard.chsm.service.KeyInfoService;
|
import com.sunyard.chsm.service.KeyInfoService;
|
||||||
import com.sunyard.chsm.utils.DateFormat;
|
import com.sunyard.chsm.utils.DateFormat;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
package com.sunyard.chsm.controller;
|
||||||
|
|
||||||
|
import com.sunyard.chsm.dto.TmkStatus;
|
||||||
|
import com.sunyard.chsm.model.R;
|
||||||
|
import com.sunyard.chsm.service.DeviceService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主密钥管理
|
||||||
|
*
|
||||||
|
* @author liulu
|
||||||
|
* @since 2024/11/8
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/tmk")
|
||||||
|
public class TmkController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DeviceService deviceService;
|
||||||
|
|
||||||
|
@GetMapping("/status")
|
||||||
|
public R<TmkStatus> getTMKStatus() {
|
||||||
|
TmkStatus status = deviceService.getTMKStatus();
|
||||||
|
return R.data(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化主密钥
|
||||||
|
*/
|
||||||
|
@PostMapping("/init")
|
||||||
|
public R<Void> initTmk() {
|
||||||
|
deviceService.initTmk();
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.sunyard.chsm.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liulu
|
||||||
|
* @since 2024/11/11
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TmkStatus {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否已经存在设备
|
||||||
|
*/
|
||||||
|
private boolean hasDevice;
|
||||||
|
/**
|
||||||
|
* 主密钥是否初始化
|
||||||
|
*/
|
||||||
|
private boolean tmkInit;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -2,6 +2,7 @@ package com.sunyard.chsm.service;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.sunyard.chsm.dto.DeviceDTO;
|
import com.sunyard.chsm.dto.DeviceDTO;
|
||||||
|
import com.sunyard.chsm.dto.TmkStatus;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -21,4 +22,8 @@ public interface DeviceService {
|
|||||||
void update(DeviceDTO.DeviceSave update);
|
void update(DeviceDTO.DeviceSave update);
|
||||||
|
|
||||||
void delete(Long id);
|
void delete(Long id);
|
||||||
|
|
||||||
|
TmkStatus getTMKStatus();
|
||||||
|
|
||||||
|
void initTmk();
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,19 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
|||||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.sunyard.chsm.dto.DeviceDTO;
|
import com.sunyard.chsm.dto.DeviceDTO;
|
||||||
|
import com.sunyard.chsm.dto.TmkStatus;
|
||||||
import com.sunyard.chsm.enums.ManufacturerEnum;
|
import com.sunyard.chsm.enums.ManufacturerEnum;
|
||||||
import com.sunyard.chsm.enums.ManufacturerModelEnum;
|
import com.sunyard.chsm.enums.ManufacturerModelEnum;
|
||||||
import com.sunyard.chsm.mapper.SpDeviceMapper;
|
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.Device;
|
||||||
|
import com.sunyard.chsm.model.entity.TmkInfo;
|
||||||
|
import com.sunyard.chsm.sdf.adapter.BcSdfApiAdaptor;
|
||||||
import com.sunyard.chsm.service.DeviceService;
|
import com.sunyard.chsm.service.DeviceService;
|
||||||
|
import com.sunyard.ssp.modules.sysconf.paramconf.entity.ParamConf;
|
||||||
|
import com.sunyard.ssp.modules.sysconf.paramconf.mapper.ParamConfMapper;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.bouncycastle.util.encoders.Hex;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@ -36,6 +43,10 @@ public class DeviceServiceImpl implements DeviceService {
|
|||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SpDeviceMapper spDeviceMapper;
|
private SpDeviceMapper spDeviceMapper;
|
||||||
|
@Resource
|
||||||
|
private ParamConfMapper paramConfMapper;
|
||||||
|
@Resource
|
||||||
|
private TmkInfoMapper tmkInfoMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Page<DeviceDTO.DeviceView> selectPageList(DeviceDTO.Query query) {
|
public Page<DeviceDTO.DeviceView> selectPageList(DeviceDTO.Query query) {
|
||||||
@ -171,6 +182,91 @@ public class DeviceServiceImpl implements DeviceService {
|
|||||||
spDeviceMapper.deleteById(id);
|
spDeviceMapper.deleteById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TmkStatus getTMKStatus() {
|
||||||
|
TmkStatus status = new TmkStatus();
|
||||||
|
ParamConf tmkInit = paramConfMapper.selectByKey("tmk_init");
|
||||||
|
if (tmkInit != null && "true".equals(tmkInit.getValue())) {
|
||||||
|
status.setHasDevice(true);
|
||||||
|
status.setTmkInit(false);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
status.setTmkInit(false);
|
||||||
|
Long c = spDeviceMapper.selectCount(new LambdaQueryWrapper<>());
|
||||||
|
status.setHasDevice(c > 0L);
|
||||||
|
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);
|
||||||
|
|
||||||
|
byte[] publicKey = sdfApi.exportEncPublicKeyECC("", 1);
|
||||||
|
byte[] encSk = sdfApi.externalEncryptECC("", publicKey, sk);
|
||||||
|
|
||||||
|
TmkInfo info = new TmkInfo();
|
||||||
|
info.setId(IdWorker.getId());
|
||||||
|
info.setCreateTime(now);
|
||||||
|
info.setDeviceSerial(sdfApi.getDeviceInfo("").getDeviceSerial());
|
||||||
|
info.setEncTmk(Hex.toHexString(encSk));
|
||||||
|
info.setPubKey(Hex.toHexString(publicKey));
|
||||||
|
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);
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
ParamConf conf = new ParamConf();
|
||||||
|
conf.setKey("tmk_init");
|
||||||
|
conf.setValue("true");
|
||||||
|
conf.setCreatTime(LocalDateTime.now());
|
||||||
|
paramConfMapper.insert(conf);
|
||||||
|
}
|
||||||
|
|
||||||
private void checkName(String name) {
|
private void checkName(String name) {
|
||||||
LambdaQueryWrapper<Device> wrapper = new LambdaQueryWrapper<Device>()
|
LambdaQueryWrapper<Device> wrapper = new LambdaQueryWrapper<Device>()
|
||||||
.eq(Device::getName, name);
|
.eq(Device::getName, name);
|
||||||
|
@ -9,7 +9,6 @@ import com.sunyard.chsm.sdf.adapter.SdfApiAdapter;
|
|||||||
import com.sunyard.chsm.sdf.adapter.SdfApiAdapterFactory;
|
import com.sunyard.chsm.sdf.adapter.SdfApiAdapterFactory;
|
||||||
import com.sunyard.chsm.sdf.context.DeviceContext;
|
import com.sunyard.chsm.sdf.context.DeviceContext;
|
||||||
import com.sunyard.chsm.sdf.model.DeviceInfo;
|
import com.sunyard.chsm.sdf.model.DeviceInfo;
|
||||||
import com.sunyard.chsm.sdf.model.EccPubKey;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.bouncycastle.util.encoders.Hex;
|
import org.bouncycastle.util.encoders.Hex;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
@ -65,8 +64,8 @@ public class DeviceTask implements InitializingBean {
|
|||||||
String sh = sdfApiAdapter.openSession(dh);
|
String sh = sdfApiAdapter.openSession(dh);
|
||||||
DeviceInfo info = sdfApiAdapter.getDeviceInfo(sh);
|
DeviceInfo info = sdfApiAdapter.getDeviceInfo(sh);
|
||||||
log.info("get DeviceInfo: {}", info);
|
log.info("get DeviceInfo: {}", info);
|
||||||
EccPubKey eccPubKey = sdfApiAdapter.exportEncPublicKeyECC(sh, 2);
|
byte[] eccPubKey = sdfApiAdapter.exportEncPublicKeyECC(sh, 2);
|
||||||
log.info("exportEncPublicKeyECC: {}", Hex.toHexString(eccPubKey.getPubKeyBytes()));
|
log.info("exportEncPublicKeyECC: {}", Hex.toHexString(eccPubKey));
|
||||||
sdfApiAdapter.closeSession(sh);
|
sdfApiAdapter.closeSession(sh);
|
||||||
sdfApiAdapter.closeDevice(dh);
|
sdfApiAdapter.closeDevice(dh);
|
||||||
connected = true;
|
connected = true;
|
||||||
|
@ -17,4 +17,39 @@
|
|||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- JUnit 5 API (仅单元测试使用)-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<version>5.8.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- Spring Boot Test (仅单元测试使用) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sunyard.chsm</groupId>
|
||||||
|
<artifactId>chsm-common</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sunyard.chsm</groupId>
|
||||||
|
<artifactId>chsm-params</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.dm</groupId>
|
||||||
|
<artifactId>DmJdbcDriver</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.sunyard.chsm;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liulu
|
||||||
|
* @since 2024/10/25
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@SpringBootApplication
|
||||||
|
public class WebServerApp {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SpringApplication.run(WebServerApp.class, args);
|
||||||
|
log.info("---------------------WebServerApp 启动完成-------------------");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.sunyard.chsm.config;
|
||||||
|
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liulu
|
||||||
|
* @since 2024/11/13
|
||||||
|
*/
|
||||||
|
public class AuthHandler implements HandlerInterceptor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.sunyard.chsm.controller;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用Token服务接口
|
||||||
|
*
|
||||||
|
* @author liulu
|
||||||
|
* @version V1.0
|
||||||
|
* @since 2023/8/4
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping
|
||||||
|
public class AppLoginController {
|
||||||
|
|
||||||
|
}
|
62
chsm-web-server/src/main/resources/application.yml
Normal file
62
chsm-web-server/src/main/resources/application.yml
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
server:
|
||||||
|
port: 89
|
||||||
|
tomcat:
|
||||||
|
uri-encoding: UTF-8
|
||||||
|
threads:
|
||||||
|
max: 1000
|
||||||
|
min-spare: 30
|
||||||
|
|
||||||
|
spring:
|
||||||
|
main:
|
||||||
|
allow-circular-references: true
|
||||||
|
# 数据源
|
||||||
|
datasource:
|
||||||
|
driverClassName: dm.jdbc.driver.DmDriver
|
||||||
|
url: jdbc:dm://172.16.17.236:5236?schema=SSP&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=true&characterEncoding=UTF-8
|
||||||
|
username: SUNYARD
|
||||||
|
# Jasypt加密 可到common-utils中找到JasyptUtil加解密工具类生成加密结果 格式为ENC(加密结果)
|
||||||
|
password: 123456
|
||||||
|
hikari:
|
||||||
|
minimum-idle: 5
|
||||||
|
maximum-pool-size: 100
|
||||||
|
idle-timeout: 600000 # 空闲连接的最大等待时间,单位为毫秒 (10 分钟)
|
||||||
|
max-lifetime: 1800000 # 连接池中连接的最大存活时间,单位为毫秒 (30 分钟)
|
||||||
|
connection-timeout: 30000 # 获取连接的超时时间,单位为毫秒 (30 秒)
|
||||||
|
leak-detection-threshold: 2000 # 连接泄漏检测阈值,单位为毫秒 (2 秒)
|
||||||
|
# 连接测试配置,确保连接有效性
|
||||||
|
connection-test-query: SELECT 1
|
||||||
|
validation-timeout: 5000 # 验证连接的超时时间,单位为毫秒 (5 秒)
|
||||||
|
jackson:
|
||||||
|
time-zone: GMT+8
|
||||||
|
date-format: yyyy-MM-dd HH:mm:ss
|
||||||
|
|
||||||
|
mybatis-plus:
|
||||||
|
mapper-locations: classpath*:mapper/**/*Mapper.xml
|
||||||
|
# 原生配置
|
||||||
|
configuration:
|
||||||
|
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
|
||||||
|
map-underscore-to-camel-case: true
|
||||||
|
cache-enabled: false
|
||||||
|
lazy-loading-enabled: false
|
||||||
|
global-config:
|
||||||
|
# 数据库相关配置
|
||||||
|
db-config:
|
||||||
|
#主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
|
||||||
|
id-type: AUTO
|
||||||
|
#驼峰下划线转换
|
||||||
|
table-underline: true
|
||||||
|
#是否开启大写命名,默认不开启
|
||||||
|
capital-mode: true
|
||||||
|
#逻辑删除配置
|
||||||
|
#logic-delete-value: 1
|
||||||
|
#logic-not-delete-value: 0
|
||||||
|
|
||||||
|
logging:
|
||||||
|
level:
|
||||||
|
root: info
|
||||||
|
com.sunyard.chsm.mapper: debug
|
||||||
|
# org.springframework.web: trace
|
||||||
|
# config: classpath:log4j2.xml
|
||||||
|
|
||||||
|
|
||||||
|
|
91
chsm-web-server/src/main/resources/logback.xml
Normal file
91
chsm-web-server/src/main/resources/logback.xml
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
|
||||||
|
<!--<include resource="org/springframework/boot/logging/logback/base.xml"/>-->
|
||||||
|
<!-- 定义log文件的目录 -->
|
||||||
|
<property name="LOG_HOME" value="logs"/>
|
||||||
|
<!-- 加载 Spring 配置文件信息 -->
|
||||||
|
<springProperty scope="context" name="applicationName" source="spring.application.name" defaultValue="localhost"/>
|
||||||
|
<!-- 日志输出格式 -->
|
||||||
|
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %X{tl} [%thread] %-5level [%logger{0}:%L]- %msg%n%ex{15}"/>
|
||||||
|
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<!--日志文件输出格式-->
|
||||||
|
<encoder>
|
||||||
|
<pattern>${LOG_PATTERN}</pattern>
|
||||||
|
<charset>UTF-8</charset> <!-- 设置字符集 -->
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${LOG_HOME}/info.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${LOG_HOME}/%d{yyyy-MM}/INFO-%d{yyyy-MM-dd}_%i.log</fileNamePattern>
|
||||||
|
<!--单个文件-->
|
||||||
|
<maxFileSize>10MB</maxFileSize>
|
||||||
|
<!--文件保存时间(天)-->
|
||||||
|
<maxHistory>30</maxHistory>
|
||||||
|
<!--总文件日志最大的大小-->
|
||||||
|
<totalSizeCap>20GB</totalSizeCap>
|
||||||
|
</rollingPolicy>
|
||||||
|
<!--日志文件输出格式-->
|
||||||
|
<encoder>
|
||||||
|
<pattern>${LOG_PATTERN}</pattern>
|
||||||
|
<charset>UTF-8</charset> <!-- 设置字符集 -->
|
||||||
|
</encoder>
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
|
<level>INFO</level>
|
||||||
|
</filter>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${LOG_HOME}/debug.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${LOG_HOME}/%d{yyyy-MM}/sspweb-DEBUG-%d{yyyy-MM-dd}_%i.log</fileNamePattern>
|
||||||
|
<!--单个文件-->
|
||||||
|
<maxFileSize>10MB</maxFileSize>
|
||||||
|
<!--文件保存时间(天)-->
|
||||||
|
<maxHistory>30</maxHistory>
|
||||||
|
<!--总文件日志最大的大小-->
|
||||||
|
<totalSizeCap>20GB</totalSizeCap>
|
||||||
|
</rollingPolicy>
|
||||||
|
<!--日志文件输出格式-->
|
||||||
|
<encoder>
|
||||||
|
<pattern>${LOG_PATTERN}</pattern>
|
||||||
|
<charset>UTF-8</charset> <!-- 设置字符集 -->
|
||||||
|
</encoder>
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
|
<level>DEBUG</level>
|
||||||
|
</filter>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${LOG_HOME}/error.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${LOG_HOME}/%d{yyyy-MM}/ERROR-%d{yyyy-MM-dd}_%i.log</fileNamePattern>
|
||||||
|
<!--单个文件-->
|
||||||
|
<maxFileSize>10MB</maxFileSize>
|
||||||
|
<!--文件保存时间(天)-->
|
||||||
|
<maxHistory>30</maxHistory>
|
||||||
|
<!--总文件日志最大的大小-->
|
||||||
|
<totalSizeCap>20GB</totalSizeCap>
|
||||||
|
</rollingPolicy>
|
||||||
|
<!--日志文件输出格式-->
|
||||||
|
<encoder>
|
||||||
|
<pattern>${LOG_PATTERN}</pattern>
|
||||||
|
<charset>UTF-8</charset> <!-- 设置字符集 -->
|
||||||
|
</encoder>
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
|
<level>ERROR</level>
|
||||||
|
</filter>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="INFO_FILE"/>
|
||||||
|
<appender-ref ref="DEBUG_FILE"/>
|
||||||
|
<appender-ref ref="ERROR_FILE"/>
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
</root>
|
||||||
|
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.sunyard.chsm.service;
|
||||||
|
|
||||||
|
import com.sunyard.chsm.WebServerApp;
|
||||||
|
import com.sunyard.chsm.model.dto.KeyInfoDTO;
|
||||||
|
import com.sunyard.chsm.model.entity.KeyRecord;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@SpringBootTest(classes = WebServerApp.class)
|
||||||
|
public class SYMEncryptControllerTest {
|
||||||
|
|
||||||
|
private static final long TEST_APP_ID = 1852232967292882946L;
|
||||||
|
private static final long TEST_KEY_ID = 1852232967292882945L;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private KeyRecordService keyRecordService;
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSelectKey() {
|
||||||
|
KeyRecord key = keyRecordService.selectByKeyId(TEST_KEY_ID);
|
||||||
|
System.out.println(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
34
chsm-web-server/src/test/java/sdf/BCSdfApiServiceTest.java
Normal file
34
chsm-web-server/src/test/java/sdf/BCSdfApiServiceTest.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package sdf;
|
||||||
|
import com.sunyard.chsm.WebServerApp;
|
||||||
|
import com.sunyard.chsm.enums.KeyAlg;
|
||||||
|
import com.sunyard.chsm.sdf.BCSdfApiService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@SpringBootTest(classes = WebServerApp.class)
|
||||||
|
public class BCSdfApiServiceTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BCSdfApiService bcSdfApiService;
|
||||||
|
|
||||||
|
// 对称加密解密测试
|
||||||
|
@Test
|
||||||
|
void testSym() {
|
||||||
|
byte[] data = new byte[128];
|
||||||
|
new Random().nextBytes( data );
|
||||||
|
|
||||||
|
byte[] key = bcSdfApiService.genSymKey( KeyAlg.SM4 );
|
||||||
|
byte[] enData = bcSdfApiService.symEncrypt( KeyAlg.SM4, key, data );
|
||||||
|
byte[] deData = bcSdfApiService.symDecrypt( KeyAlg.SM4, key, enData );
|
||||||
|
|
||||||
|
Assert.assertArrayEquals( data, deData );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
62
chsm-web-server/src/test/resources/application.yml
Normal file
62
chsm-web-server/src/test/resources/application.yml
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
server:
|
||||||
|
port: 89
|
||||||
|
tomcat:
|
||||||
|
uri-encoding: UTF-8
|
||||||
|
threads:
|
||||||
|
max: 1000
|
||||||
|
min-spare: 30
|
||||||
|
|
||||||
|
spring:
|
||||||
|
main:
|
||||||
|
allow-circular-references: true
|
||||||
|
# 数据源
|
||||||
|
datasource:
|
||||||
|
driverClassName: dm.jdbc.driver.DmDriver
|
||||||
|
url: jdbc:dm://172.16.17.236:5236?schema=SSP&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=true&characterEncoding=UTF-8
|
||||||
|
username: SUNYARD
|
||||||
|
# Jasypt加密 可到common-utils中找到JasyptUtil加解密工具类生成加密结果 格式为ENC(加密结果)
|
||||||
|
password: 123456
|
||||||
|
hikari:
|
||||||
|
minimum-idle: 5
|
||||||
|
maximum-pool-size: 100
|
||||||
|
idle-timeout: 600000 # 空闲连接的最大等待时间,单位为毫秒 (10 分钟)
|
||||||
|
max-lifetime: 1800000 # 连接池中连接的最大存活时间,单位为毫秒 (30 分钟)
|
||||||
|
connection-timeout: 30000 # 获取连接的超时时间,单位为毫秒 (30 秒)
|
||||||
|
leak-detection-threshold: 2000 # 连接泄漏检测阈值,单位为毫秒 (2 秒)
|
||||||
|
# 连接测试配置,确保连接有效性
|
||||||
|
connection-test-query: SELECT 1
|
||||||
|
validation-timeout: 5000 # 验证连接的超时时间,单位为毫秒 (5 秒)
|
||||||
|
jackson:
|
||||||
|
time-zone: GMT+8
|
||||||
|
date-format: yyyy-MM-dd HH:mm:ss
|
||||||
|
|
||||||
|
mybatis-plus:
|
||||||
|
mapper-locations: classpath*:mapper/**/*Mapper.xml
|
||||||
|
# 原生配置
|
||||||
|
configuration:
|
||||||
|
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
|
||||||
|
map-underscore-to-camel-case: true
|
||||||
|
cache-enabled: false
|
||||||
|
lazy-loading-enabled: false
|
||||||
|
global-config:
|
||||||
|
# 数据库相关配置
|
||||||
|
db-config:
|
||||||
|
#主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
|
||||||
|
id-type: AUTO
|
||||||
|
#驼峰下划线转换
|
||||||
|
table-underline: true
|
||||||
|
#是否开启大写命名,默认不开启
|
||||||
|
capital-mode: true
|
||||||
|
#逻辑删除配置
|
||||||
|
#logic-delete-value: 1
|
||||||
|
#logic-not-delete-value: 0
|
||||||
|
|
||||||
|
logging:
|
||||||
|
level:
|
||||||
|
root: info
|
||||||
|
com.sunyard.chsm.mapper: debug
|
||||||
|
# org.springframework.web: trace
|
||||||
|
# config: classpath:log4j2.xml
|
||||||
|
|
||||||
|
|
||||||
|
|
91
chsm-web-server/src/test/resources/logback.xml
Normal file
91
chsm-web-server/src/test/resources/logback.xml
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
|
||||||
|
<!--<include resource="org/springframework/boot/logging/logback/base.xml"/>-->
|
||||||
|
<!-- 定义log文件的目录 -->
|
||||||
|
<property name="LOG_HOME" value="logs"/>
|
||||||
|
<!-- 加载 Spring 配置文件信息 -->
|
||||||
|
<springProperty scope="context" name="applicationName" source="spring.application.name" defaultValue="localhost"/>
|
||||||
|
<!-- 日志输出格式 -->
|
||||||
|
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %X{tl} [%thread] %-5level [%logger{0}:%L]- %msg%n%ex{15}"/>
|
||||||
|
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<!--日志文件输出格式-->
|
||||||
|
<encoder>
|
||||||
|
<pattern>${LOG_PATTERN}</pattern>
|
||||||
|
<charset>UTF-8</charset> <!-- 设置字符集 -->
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${LOG_HOME}/info.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${LOG_HOME}/%d{yyyy-MM}/INFO-%d{yyyy-MM-dd}_%i.log</fileNamePattern>
|
||||||
|
<!--单个文件-->
|
||||||
|
<maxFileSize>10MB</maxFileSize>
|
||||||
|
<!--文件保存时间(天)-->
|
||||||
|
<maxHistory>30</maxHistory>
|
||||||
|
<!--总文件日志最大的大小-->
|
||||||
|
<totalSizeCap>20GB</totalSizeCap>
|
||||||
|
</rollingPolicy>
|
||||||
|
<!--日志文件输出格式-->
|
||||||
|
<encoder>
|
||||||
|
<pattern>${LOG_PATTERN}</pattern>
|
||||||
|
<charset>UTF-8</charset> <!-- 设置字符集 -->
|
||||||
|
</encoder>
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
|
<level>INFO</level>
|
||||||
|
</filter>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${LOG_HOME}/debug.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${LOG_HOME}/%d{yyyy-MM}/sspweb-DEBUG-%d{yyyy-MM-dd}_%i.log</fileNamePattern>
|
||||||
|
<!--单个文件-->
|
||||||
|
<maxFileSize>10MB</maxFileSize>
|
||||||
|
<!--文件保存时间(天)-->
|
||||||
|
<maxHistory>30</maxHistory>
|
||||||
|
<!--总文件日志最大的大小-->
|
||||||
|
<totalSizeCap>20GB</totalSizeCap>
|
||||||
|
</rollingPolicy>
|
||||||
|
<!--日志文件输出格式-->
|
||||||
|
<encoder>
|
||||||
|
<pattern>${LOG_PATTERN}</pattern>
|
||||||
|
<charset>UTF-8</charset> <!-- 设置字符集 -->
|
||||||
|
</encoder>
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
|
<level>DEBUG</level>
|
||||||
|
</filter>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${LOG_HOME}/error.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${LOG_HOME}/%d{yyyy-MM}/ERROR-%d{yyyy-MM-dd}_%i.log</fileNamePattern>
|
||||||
|
<!--单个文件-->
|
||||||
|
<maxFileSize>10MB</maxFileSize>
|
||||||
|
<!--文件保存时间(天)-->
|
||||||
|
<maxHistory>30</maxHistory>
|
||||||
|
<!--总文件日志最大的大小-->
|
||||||
|
<totalSizeCap>20GB</totalSizeCap>
|
||||||
|
</rollingPolicy>
|
||||||
|
<!--日志文件输出格式-->
|
||||||
|
<encoder>
|
||||||
|
<pattern>${LOG_PATTERN}</pattern>
|
||||||
|
<charset>UTF-8</charset> <!-- 设置字符集 -->
|
||||||
|
</encoder>
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
|
<level>ERROR</level>
|
||||||
|
</filter>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="INFO_FILE"/>
|
||||||
|
<appender-ref ref="DEBUG_FILE"/>
|
||||||
|
<appender-ref ref="ERROR_FILE"/>
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
</root>
|
||||||
|
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
|
@ -189,7 +189,7 @@ CREATE TABLE sp_key_csr (
|
|||||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
|
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
|
||||||
PRIMARY KEY (id)
|
PRIMARY KEY (id)
|
||||||
);
|
);
|
||||||
-- 证书
|
-- 应用证书
|
||||||
CREATE TABLE sp_app_cert (
|
CREATE TABLE sp_app_cert (
|
||||||
id BIGINT NOT NULL COMMENT 'id',
|
id BIGINT NOT NULL COMMENT 'id',
|
||||||
application_id BIGINT NOT NULL COMMENT '应用id',
|
application_id BIGINT NOT NULL COMMENT '应用id',
|
||||||
@ -213,4 +213,23 @@ CREATE TABLE sp_app_cert (
|
|||||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
|
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
|
||||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
|
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
|
||||||
PRIMARY KEY (id)
|
PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
-- CA证书
|
||||||
|
CREATE TABLE sp_ca_cert (
|
||||||
|
id BIGINT NOT NULL COMMENT 'id',
|
||||||
|
ca_name VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'ca name',
|
||||||
|
ca_url VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'url',
|
||||||
|
key_alg VARCHAR(30) NOT NULL DEFAULT '' COMMENT '密钥算法',
|
||||||
|
status VARCHAR(30) DEFAULT '' COMMENT '状态',
|
||||||
|
subject VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'DN',
|
||||||
|
serial_number VARCHAR(255) NOT NULL DEFAULT '' COMMENT '证书号',
|
||||||
|
issuer_dn VARCHAR(255) NOT NULL DEFAULT '' COMMENT '颁发者',
|
||||||
|
not_before TIMESTAMP NOT NULL COMMENT '开始时间',
|
||||||
|
not_after TIMESTAMP NOT NULL COMMENT '结束时间',
|
||||||
|
pub_key VARCHAR(255) NOT NULL DEFAULT '' COMMENT '公钥',
|
||||||
|
cert_text VARCHAR(4099) NOT NULL DEFAULT '' COMMENT '证书',
|
||||||
|
remark VARCHAR(500) NOT NULL DEFAULT '' COMMENT '备注',
|
||||||
|
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
|
||||||
|
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
|
||||||
|
PRIMARY KEY (id)
|
||||||
);
|
);
|
Loading…
Reference in New Issue
Block a user