ca管理
This commit is contained in:
parent
c18cfda28b
commit
a9b35329ce
@ -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,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;
|
||||
|
||||
|
||||
|
||||
}
|
@ -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.dto.CertDTO;
|
||||
import com.sunyard.chsm.model.R;
|
||||
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,8 +1,10 @@
|
||||
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;
|
||||
@ -23,6 +25,12 @@ public class TmkController {
|
||||
@Resource
|
||||
private DeviceService deviceService;
|
||||
|
||||
@GetMapping("/status")
|
||||
public R<TmkStatus> getTMKStatus() {
|
||||
TmkStatus status = deviceService.getTMKStatus();
|
||||
return R.data(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化主密钥
|
||||
*/
|
||||
|
@ -95,8 +95,53 @@ public abstract class CertDTO {
|
||||
* 加密密钥信封
|
||||
*/
|
||||
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 remark;
|
||||
private LocalDateTime createTime;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.sunyard.chsm.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.sunyard.chsm.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);
|
||||
}
|
@ -2,6 +2,7 @@ package com.sunyard.chsm.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.sunyard.chsm.dto.DeviceDTO;
|
||||
import com.sunyard.chsm.dto.TmkStatus;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -22,6 +23,7 @@ public interface DeviceService {
|
||||
|
||||
void delete(Long id);
|
||||
|
||||
void initTmk();
|
||||
TmkStatus getTMKStatus();
|
||||
|
||||
void initTmk();
|
||||
}
|
||||
|
@ -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.dto.CertDTO;
|
||||
import com.sunyard.chsm.mapper.CaCertMapper;
|
||||
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,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.sunyard.chsm.dto.DeviceDTO;
|
||||
import com.sunyard.chsm.dto.TmkStatus;
|
||||
import com.sunyard.chsm.enums.ManufacturerEnum;
|
||||
import com.sunyard.chsm.enums.ManufacturerModelEnum;
|
||||
import com.sunyard.chsm.mapper.SpDeviceMapper;
|
||||
@ -181,6 +182,21 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
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");
|
||||
@ -189,20 +205,20 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
//
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
// if (CollectionUtils.isEmpty(conned)) {
|
||||
//
|
||||
BcSdfApiAdaptor sdfApi = new BcSdfApiAdaptor();
|
||||
byte[] sk = sdfApi.generateRandom("", 16);
|
||||
//
|
||||
BcSdfApiAdaptor sdfApi = new BcSdfApiAdaptor();
|
||||
byte[] sk = sdfApi.generateRandom("", 16);
|
||||
|
||||
byte[] publicKey = sdfApi.exportEncPublicKeyECC("", 1);
|
||||
byte[] encSk = sdfApi.externalEncryptECC("", publicKey, sk);
|
||||
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);
|
||||
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();
|
||||
|
@ -189,7 +189,7 @@ CREATE TABLE sp_key_csr (
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
-- 证书
|
||||
-- 应用证书
|
||||
CREATE TABLE sp_app_cert (
|
||||
id BIGINT NOT NULL COMMENT 'id',
|
||||
application_id BIGINT NOT NULL COMMENT '应用id',
|
||||
@ -214,3 +214,22 @@ CREATE TABLE sp_app_cert (
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
|
||||
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