From e16420c2c51bc414673ac94d605a5e68f842a79c Mon Sep 17 00:00:00 2001 From: Cheney Date: Tue, 19 Nov 2024 20:34:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E5=9B=9E=E5=AE=B6=E5=81=9A?= =?UTF-8?q?=E5=AE=B6=E5=BA=AD=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chsm-common/pom.xml | 8 ++ .../sunyard/chsm/model/dto/KeyInfoDTO.java | 14 ++ .../chsm/sdf/AbstractSdfApiService.java | 14 +- .../com/sunyard/chsm/sdf/BCSdfApiService.java | 30 ++++- .../com/sunyard/chsm/sdf/SdfApiService.java | 7 +- .../sunyard/chsm/service/KeyInfoService.java | 7 + .../chsm/service/impl/KeyInfoServiceImpl.java | 10 ++ .../com/sunyard/chsm/utils/gm/BCSM4Utils.java | 10 +- chsm-web-server/pom.xml | 18 ++- .../com/sunyard/chsm/PerformanceTest.java | 70 ++++++++++ .../java/com/sunyard/chsm/WebServerApp.java | 7 +- .../com/sunyard/chsm/config/ResHandler.java | 28 ++++ .../chsm/controller/SYMEncryptController.java | 126 ++++++++++++++++++ .../chsm/service/SYMEncryptService.java | 48 +++++++ .../src/main/java/params/DTORes.java | 31 +++++ .../src/main/java/params/DTOSymReq.java | 29 ++++ .../src/main/java/params/DTOSymRes.java | 22 +++ .../sunyard/chsm/sdf/BCSdfApiServiceTest.java | 49 +++++++ .../test/java/sdf/BCSdfApiServiceTest.java | 34 ----- 19 files changed, 507 insertions(+), 55 deletions(-) create mode 100644 chsm-web-server/src/main/java/com/sunyard/chsm/PerformanceTest.java create mode 100644 chsm-web-server/src/main/java/com/sunyard/chsm/config/ResHandler.java create mode 100644 chsm-web-server/src/main/java/com/sunyard/chsm/controller/SYMEncryptController.java create mode 100644 chsm-web-server/src/main/java/com/sunyard/chsm/service/SYMEncryptService.java create mode 100644 chsm-web-server/src/main/java/params/DTORes.java create mode 100644 chsm-web-server/src/main/java/params/DTOSymReq.java create mode 100644 chsm-web-server/src/main/java/params/DTOSymRes.java create mode 100644 chsm-web-server/src/test/java/com/sunyard/chsm/sdf/BCSdfApiServiceTest.java delete mode 100644 chsm-web-server/src/test/java/sdf/BCSdfApiServiceTest.java diff --git a/chsm-common/pom.xml b/chsm-common/pom.xml index a92567f..0eca0ea 100644 --- a/chsm-common/pom.xml +++ b/chsm-common/pom.xml @@ -20,6 +20,14 @@ + + + cn.hutool + hutool-all + 5.8.33 + + + org.springframework.boot spring-boot-starter-web diff --git a/chsm-common/src/main/java/com/sunyard/chsm/model/dto/KeyInfoDTO.java b/chsm-common/src/main/java/com/sunyard/chsm/model/dto/KeyInfoDTO.java index f522bb5..8983e70 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/model/dto/KeyInfoDTO.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/model/dto/KeyInfoDTO.java @@ -2,6 +2,7 @@ package com.sunyard.chsm.model.dto; import com.sunyard.chsm.model.PageQuery; import com.sunyard.chsm.model.Subject; +import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; @@ -20,8 +21,10 @@ public abstract class KeyInfoDTO { @EqualsAndHashCode(callSuper = true) @Data + @Builder public static class Query extends PageQuery { private Long appId; + private Long keyId; private String status; private String keyType; } @@ -44,6 +47,10 @@ public abstract class KeyInfoDTO { private Integer genNumber; } + + + + @Data public static class KeyView { private Long id; @@ -80,6 +87,13 @@ public abstract class KeyInfoDTO { private LocalDateTime createTime; } + + @Data + @EqualsAndHashCode(callSuper = true) + public static class KeyValue extends KeyView { + private String keyData; + } + @Data public static class IDs { /** diff --git a/chsm-common/src/main/java/com/sunyard/chsm/sdf/AbstractSdfApiService.java b/chsm-common/src/main/java/com/sunyard/chsm/sdf/AbstractSdfApiService.java index cb4b764..27264ff 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/sdf/AbstractSdfApiService.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/sdf/AbstractSdfApiService.java @@ -16,7 +16,7 @@ import static com.sunyard.chsm.utils.gm.BCSM4Utils.DEFAULT_KEY_SIZE; */ public abstract class AbstractSdfApiService implements SdfApiService { - private static final Map algKeyLen = new HashMap<>(); + protected static final Map algKeyLen = new HashMap<>(); static { algKeyLen.put( KeyAlg.SM4, DEFAULT_KEY_SIZE ); } @@ -42,9 +42,13 @@ public abstract class AbstractSdfApiService implements SdfApiService { */ @Override public byte[] symEncrypt(KeyAlg alg, byte[] key, byte[] data){ - return symEncrypt( alg, AlgMode.ECB, Padding.PCKS5Padding, key, data ); + return symEncrypt( alg, AlgMode.ECB, Padding.PCKS5Padding, key, null, data ); } + @Override + public byte[] symEncrypt(KeyAlg alg, AlgMode mode, byte[] key, byte[] iv, byte[] data) { + return symEncrypt( alg, mode, Padding.PCKS5Padding, key, iv, data ); + } /** * 对称解密 @@ -55,7 +59,11 @@ public abstract class AbstractSdfApiService implements SdfApiService { */ @Override public byte[] symDecrypt(KeyAlg alg, byte[] key, byte[] data) { - return symDecrypt( alg, AlgMode.ECB, Padding.PCKS5Padding, key, data ); + return symDecrypt( alg, AlgMode.ECB, Padding.PCKS5Padding, key,null, data ); } + @Override + public byte[] symDecrypt(KeyAlg alg, AlgMode mode, byte[] key, byte[] iv, byte[] data) { + return symDecrypt( alg, mode, Padding.PCKS5Padding, key, iv, data ); + } } diff --git a/chsm-common/src/main/java/com/sunyard/chsm/sdf/BCSdfApiService.java b/chsm-common/src/main/java/com/sunyard/chsm/sdf/BCSdfApiService.java index efa11c2..4056254 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/sdf/BCSdfApiService.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/sdf/BCSdfApiService.java @@ -81,15 +81,16 @@ public class BCSdfApiService extends AbstractSdfApiService { } } + @Override - public byte[] symEncrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) { - return symCalc(Cipher.ENCRYPT_MODE, alg, mode, padding, key, data); + public byte[] symEncrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] iv, byte[] data) { + return symCalc(Cipher.ENCRYPT_MODE, alg, mode, padding, key, iv, 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); + public byte[] symDecrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] iv, byte[] data) { + return symCalc(Cipher.DECRYPT_MODE, alg, mode, padding, key, iv, data); } @@ -100,7 +101,8 @@ public class BCSdfApiService extends AbstractSdfApiService { * @param key 密钥值,明文 * @param data 加密时明文数据,解密时为密文数据 */ - private byte[] symCalc(int cipherMode, KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) { + private byte[] symCalc(int cipherMode, KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] iv, byte[] data) { + // 只支持对称算法 if (alg.getCategory() != KeyCategory.SYM_KEY) { throw new IllegalArgumentException("Must SYM_KEY, unsupported algorithm: " + alg); } @@ -122,13 +124,27 @@ public class BCSdfApiService extends AbstractSdfApiService { Cipher cipher = null; try { - cipher = BCSM4Utils.generateECBCipher(algName, cipherMode, key); + if ( mode == AlgMode.ECB ) { + cipher = BCSM4Utils.generateECBCipher(algName, cipherMode, key); + } else { + // iv 检查 + if ( null == iv ) { + throw new IllegalArgumentException("Current Mode "+ mode.getCode() + " Unsupported IV is null"); + } + if ( iv.length * 8 != algKeyLen.get(alg) ) { + throw new IllegalArgumentException("Current Alg "+ alg.getCode() + " Unsupported IV length: " + iv.length); + } + cipher = BCSM4Utils.generateCipher(algName, cipherMode, key, iv); + } + return cipher.doFinal(data); - } catch (IllegalBlockSizeException | BadPaddingException | NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException | InvalidKeyException e) { + } catch (IllegalBlockSizeException | BadPaddingException | NoSuchAlgorithmException | NoSuchProviderException | + NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e) { throw new RuntimeException("算法执行错误", e); } } + @SneakyThrows @Override public EccKey genKeyPairEcc() { diff --git a/chsm-common/src/main/java/com/sunyard/chsm/sdf/SdfApiService.java b/chsm-common/src/main/java/com/sunyard/chsm/sdf/SdfApiService.java index a7a4ad1..a016c45 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/sdf/SdfApiService.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/sdf/SdfApiService.java @@ -43,9 +43,11 @@ public interface SdfApiService { * @param key 密钥值,明文 * @param data 原始数据 */ - byte[] symEncrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data); + byte[] symEncrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] iv, byte[] data); + byte[] symEncrypt(KeyAlg alg, AlgMode mode, byte[] key, byte[] iv, byte[] data); byte[] symEncrypt(KeyAlg alg, byte[] key, byte[] data); + /** * 对称解密 * @param alg 算法,只支持对称算法 @@ -54,7 +56,8 @@ public interface SdfApiService { * @param padding 填充模式 * @param data 密文数据 */ - byte[] symDecrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data); + byte[] symDecrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] iv, byte[] data); + byte[] symDecrypt(KeyAlg alg, AlgMode mode, byte[] key, byte[] iv, byte[] data); byte[] symDecrypt(KeyAlg alg, byte[] key, byte[] data); diff --git a/chsm-common/src/main/java/com/sunyard/chsm/service/KeyInfoService.java b/chsm-common/src/main/java/com/sunyard/chsm/service/KeyInfoService.java index 9fcbd40..98029a7 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/service/KeyInfoService.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/service/KeyInfoService.java @@ -12,6 +12,13 @@ import java.util.List; */ public interface KeyInfoService { + /** + * 查询单个密钥 + * @param query + * @return + */ + KeyInfoDTO.KeyValue selectKeyInApp(KeyInfoDTO.Query query); + Page selectPageList(KeyInfoDTO.Query query); Long save(KeyInfoDTO.KeySave save); diff --git a/chsm-common/src/main/java/com/sunyard/chsm/service/impl/KeyInfoServiceImpl.java b/chsm-common/src/main/java/com/sunyard/chsm/service/impl/KeyInfoServiceImpl.java index 27675c3..92fc2ce 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/service/impl/KeyInfoServiceImpl.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/service/impl/KeyInfoServiceImpl.java @@ -88,6 +88,16 @@ public class KeyInfoServiceImpl implements KeyInfoService { private SdfApiService sdfApiService; + + @Override + public KeyInfoDTO.KeyValue selectKeyInApp(KeyInfoDTO.Query query) { + LocalDateTime now = LocalDateTime.now(); + + + return null; + } + + @Override public Page selectPageList(KeyInfoDTO.Query query) { LocalDateTime now = LocalDateTime.now(); diff --git a/chsm-common/src/main/java/com/sunyard/chsm/utils/gm/BCSM4Utils.java b/chsm-common/src/main/java/com/sunyard/chsm/utils/gm/BCSM4Utils.java index a8d57d2..6aeb83b 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/utils/gm/BCSM4Utils.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/utils/gm/BCSM4Utils.java @@ -80,7 +80,7 @@ public class BCSM4Utils extends GMBaseUtil { throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException { - Cipher cipher = generateCBCCipher(ALGORITHM_NAME_CBC_PADDING, Cipher.ENCRYPT_MODE, key, iv); + Cipher cipher = generateCipher(ALGORITHM_NAME_CBC_PADDING, Cipher.ENCRYPT_MODE, key, iv); return cipher.doFinal(data); } @@ -88,7 +88,7 @@ public class BCSM4Utils extends GMBaseUtil { throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidAlgorithmParameterException { - Cipher cipher = generateCBCCipher(ALGORITHM_NAME_CBC_PADDING, Cipher.DECRYPT_MODE, key, iv); + Cipher cipher = generateCipher(ALGORITHM_NAME_CBC_PADDING, Cipher.DECRYPT_MODE, key, iv); return cipher.doFinal(cipherText); } @@ -96,7 +96,7 @@ public class BCSM4Utils extends GMBaseUtil { throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException { - Cipher cipher = generateCBCCipher(ALGORITHM_NAME_CBC_NOPADDING, Cipher.ENCRYPT_MODE, key, iv); + Cipher cipher = generateCipher(ALGORITHM_NAME_CBC_NOPADDING, Cipher.ENCRYPT_MODE, key, iv); return cipher.doFinal(data); } @@ -104,7 +104,7 @@ public class BCSM4Utils extends GMBaseUtil { throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidAlgorithmParameterException { - Cipher cipher = generateCBCCipher(ALGORITHM_NAME_CBC_NOPADDING, Cipher.DECRYPT_MODE, key, iv); + Cipher cipher = generateCipher(ALGORITHM_NAME_CBC_NOPADDING, Cipher.DECRYPT_MODE, key, iv); return cipher.doFinal(cipherText); } @@ -179,7 +179,7 @@ public class BCSM4Utils extends GMBaseUtil { return cipher; } - public static Cipher generateCBCCipher(String algorithmName, int mode, byte[] key, byte[] iv) + public static Cipher generateCipher(String algorithmName, int mode, byte[] key, byte[] iv) throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException { Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME); diff --git a/chsm-web-server/pom.xml b/chsm-web-server/pom.xml index 5df15a7..dc118b8 100644 --- a/chsm-web-server/pom.xml +++ b/chsm-web-server/pom.xml @@ -34,11 +34,20 @@ test + com.sunyard.chsm chsm-common ${project.version} + + + + cn.hutool + hutool-all + 5.8.33 + + com.sunyard.chsm chsm-params @@ -51,5 +60,12 @@ - + + + + org.springframework.boot + spring-boot-maven-plugin + + + \ No newline at end of file diff --git a/chsm-web-server/src/main/java/com/sunyard/chsm/PerformanceTest.java b/chsm-web-server/src/main/java/com/sunyard/chsm/PerformanceTest.java new file mode 100644 index 0000000..b541e13 --- /dev/null +++ b/chsm-web-server/src/main/java/com/sunyard/chsm/PerformanceTest.java @@ -0,0 +1,70 @@ +package com.sunyard.chsm; + +import com.sunyard.chsm.enums.KeyAlg; +import com.sunyard.chsm.sdf.BCSdfApiService; +import com.sunyard.chsm.sdf.SdfApiService; +import com.sunyard.chsm.sdf.model.EccKey; +import lombok.SneakyThrows; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +public class PerformanceTest { + + private static final long max = 100_000L; + private static final SdfApiService service = new BCSdfApiService(); + private static final byte[] data = new byte[ 1024 ]; + + @SneakyThrows + public static void main(String[] args) { + + int numThreads = 16; // Number of threads to use + Thread[] threads = new Thread[numThreads]; + + long startTime = System.currentTimeMillis(); + for (int i = 0; i < numThreads; i++) { + threads[i] = new Thread(() -> { + testSM4(); + }); + threads[i].start(); + } + + + for ( int i =0 ; i < numThreads; i++ ) { + threads[i].join(); + } + + long endTime = System.currentTimeMillis(); + + double tps = numThreads * max * 1000.0 / (endTime - startTime); + System.out.println("SM4 TPS: " + String.format("%.02f", tps)); + + } + +// private static void testSM2() { +// long startTime = System.currentTimeMillis(); +// EccKey eccKey = service.genKeyPairEcc(); +// +// for (long i = 0; i < max; i++) { +// +// +// service.asym +// +// } +// +// long endTime = System.currentTimeMillis(); +// +// System.out.println("Addition result: " + sum + ", Time taken: " + (endTime - startTime) + " ns"); +// } + + private static void testSM4() { + + byte[] key = service.generateRandom(16); + for (long i = 0; i < max; i++) { + byte[] enData = service.symEncrypt(KeyAlg.SM4, key, data); + service.symDecrypt(KeyAlg.SM4, key, enData); + } + + } +} diff --git a/chsm-web-server/src/main/java/com/sunyard/chsm/WebServerApp.java b/chsm-web-server/src/main/java/com/sunyard/chsm/WebServerApp.java index 902c04b..38a1fe9 100644 --- a/chsm-web-server/src/main/java/com/sunyard/chsm/WebServerApp.java +++ b/chsm-web-server/src/main/java/com/sunyard/chsm/WebServerApp.java @@ -15,11 +15,12 @@ public class WebServerApp { public static void main(String[] args) { - - - + long startTime = System.currentTimeMillis(); SpringApplication.run(WebServerApp.class, args); + long endTime = System.currentTimeMillis(); log.info("---------------------WebServerApp 启动完成-------------------"); + log.info("启动耗时 " + (endTime - startTime) + " ms"); + PerformanceTest.main(args); } } diff --git a/chsm-web-server/src/main/java/com/sunyard/chsm/config/ResHandler.java b/chsm-web-server/src/main/java/com/sunyard/chsm/config/ResHandler.java new file mode 100644 index 0000000..e74af39 --- /dev/null +++ b/chsm-web-server/src/main/java/com/sunyard/chsm/config/ResHandler.java @@ -0,0 +1,28 @@ +package com.sunyard.chsm.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 拦截执行异常,返回错误码和提示信息 + * @author Cheney + * @since 2024/11/13 + */ +@Slf4j +public class ResHandler implements HandlerInterceptor { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + return true; + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + log.error("Error in call {}: {}", request.getRequestURI(), ex); + + HandlerInterceptor.super.afterCompletion(request, response, handler, ex); + } +} diff --git a/chsm-web-server/src/main/java/com/sunyard/chsm/controller/SYMEncryptController.java b/chsm-web-server/src/main/java/com/sunyard/chsm/controller/SYMEncryptController.java new file mode 100644 index 0000000..0b34f20 --- /dev/null +++ b/chsm-web-server/src/main/java/com/sunyard/chsm/controller/SYMEncryptController.java @@ -0,0 +1,126 @@ +/** + * 处理对称计算类请求 + */ + + +package com.sunyard.chsm.controller; +import cn.hutool.core.codec.Base64; +import com.sunyard.chsm.enums.AlgMode; +import com.sunyard.chsm.enums.KeyAlg; +import com.sunyard.chsm.enums.Padding; +import com.sunyard.chsm.service.KeyInfoService; +import com.sunyard.chsm.service.SYMEncryptService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import params.DTORes; +import params.DTOSymReq; + +import java.util.HashSet; +import java.util.Set; + +@RestController +@RequestMapping("/sym") +public class SYMEncryptController { + + @Autowired + private KeyInfoService keyInfoService; + + @Autowired + private SYMEncryptService symEncryptService; + + // 支持的算法 + private static final Set SUPPORTED_ALG = new HashSet<>(); + + // 支持的模式 + private static final Set SUPPORTED_MODE = new HashSet<>(); + + // 支持的填充方式 + private static final Set SUPPORTED_PADDING = new HashSet<>(); + + static { + SUPPORTED_ALG.add("SM4"); + } + + + @PostMapping("/encrypt") + @ResponseBody + public DTORes encrypt(@RequestBody DTOSymReq req) { + return doEnOrDe(true, req); + } + + @PostMapping("/decrypt") + @ResponseBody + public DTORes decrypt(@RequestBody DTOSymReq req) { + return doEnOrDe(false, req); + } + + /** + * 合并处理加密和解密逻辑 + * @param en true 为加密 false 为解密 + * @param req 请求数据 + * @return 返回数据 + */ + private DTORes doEnOrDe(boolean en, DTOSymReq req){ + // 参数检查 + // 填充默认参数 + if ( null == req.getAppId() ) { + throw new IllegalArgumentException("appId can't be null"); + } + + // 算法检查 + if ( ! SUPPORTED_ALG.contains(req.getAlg()) ) { + throw new IllegalArgumentException("alg must be SM4"); + } + + // 模式检查 + if ( ! SUPPORTED_MODE.contains(req.getMode()) ) { + throw new IllegalArgumentException("mode must be ECB/CBC"); + } + + // 填充检查 + if ( ! SUPPORTED_PADDING.contains( req.getPadding() ) ) { + throw new IllegalArgumentException("padding must be none or pkcs5"); + } + + + // iv + byte[] iv = null; + if ( ! "ECB".equals(req.getMode()) ) { + if ( null == req.getIv() ) { + throw new IllegalArgumentException("iv can't be null"); + } + iv = Base64.decode( req.getIv() ); + } + + // data + if ( null == req.getData() ) { + throw new IllegalArgumentException("data can't be null"); + } + byte[] data = Base64.decode( req.getData() ); + + // 功能执行 + if ( en ) { + data = symEncryptService.symEncrypt( + KeyAlg.of( req.getAlg() ), + AlgMode.of( req.getMode() ), + Padding.of( req.getPadding() ), + req.getAppId(), + req.getKeyId(), + iv, + data + ); + } else { + data = symEncryptService.symEncrypt( + KeyAlg.of( req.getAlg() ), + AlgMode.of( req.getMode() ), + Padding.of( req.getPadding() ), + req.getAppId(), + req.getKeyId(), + iv, + data + ); + } + + return DTORes.success(data); + } +} diff --git a/chsm-web-server/src/main/java/com/sunyard/chsm/service/SYMEncryptService.java b/chsm-web-server/src/main/java/com/sunyard/chsm/service/SYMEncryptService.java new file mode 100644 index 0000000..856cbe4 --- /dev/null +++ b/chsm-web-server/src/main/java/com/sunyard/chsm/service/SYMEncryptService.java @@ -0,0 +1,48 @@ +package com.sunyard.chsm.service; + + +import cn.hutool.core.util.HexUtil; +import com.sunyard.chsm.enums.AlgMode; +import com.sunyard.chsm.enums.KeyAlg; +import com.sunyard.chsm.enums.Padding; +import com.sunyard.chsm.model.dto.KeyInfoDTO; +import com.sunyard.chsm.model.entity.KeyRecord; +import com.sunyard.chsm.sdf.SdfApiService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + + +/** + * + */ +@Service +public class SYMEncryptService { + @Autowired + private SdfApiService sdf; + + @Autowired + private KeyInfoService keyInfoService; + + @Autowired + private KeyRecordService keyRecordService; + + + public byte[] symEncrypt(KeyAlg alg, AlgMode mode, Padding padding, Long appId , Long keyId, byte[] iv, byte[] data) { + // 查询 key 的值 + KeyRecord key = keyRecordService.selectByKeyId(keyId); + // TODO 没有检查 appId + + + // 验证 key + + + // 计算 + return sdf.symEncrypt( + alg, mode, padding, + HexUtil.decodeHex(key.getKeyData()), + iv, + data + ); + } + +} diff --git a/chsm-web-server/src/main/java/params/DTORes.java b/chsm-web-server/src/main/java/params/DTORes.java new file mode 100644 index 0000000..1066ac7 --- /dev/null +++ b/chsm-web-server/src/main/java/params/DTORes.java @@ -0,0 +1,31 @@ +package params; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@AllArgsConstructor +@Data +public class DTORes { + // 错误码,0 代表无错误 + private int code = 0; + // 提示信息 + private String msg = "执行成功"; + // 数据 + private Object data; + + + public static DTORes success(Object data){ + return success(data, "执行成功"); + } + + public static DTORes success(Object data, String msg){ + DTORes res = new DTORes(0, msg, data); + return res; + } + + public static DTORes fail(int code, String msg){ + DTORes res = new DTORes(code, msg,null); + return res; + } + +} diff --git a/chsm-web-server/src/main/java/params/DTOSymReq.java b/chsm-web-server/src/main/java/params/DTOSymReq.java new file mode 100644 index 0000000..735f65b --- /dev/null +++ b/chsm-web-server/src/main/java/params/DTOSymReq.java @@ -0,0 +1,29 @@ +package params; + +import com.sunyard.chsm.enums.Padding; +import lombok.Data; + +@Data +public class DTOSymReq { + + // 应用 Id + private Long appId; + + // 密钥 Id + private Long keyId; + + // 算法 + private String alg; + + // 模式 + private String mode = "ECB"; + + // padding + private String padding = Padding.NOPadding.getCode(); + + // iv 可以为 null,base64 编码 + private String iv; + + // 计算数据 base64 编码 + private String data; +} diff --git a/chsm-web-server/src/main/java/params/DTOSymRes.java b/chsm-web-server/src/main/java/params/DTOSymRes.java new file mode 100644 index 0000000..d8b3f84 --- /dev/null +++ b/chsm-web-server/src/main/java/params/DTOSymRes.java @@ -0,0 +1,22 @@ +package params; + +import lombok.Data; + +@Data +public class DTOSymRes { + + // 应用 Id + private String appId; + + // 密钥 Id + private String keyId; + + // 算法 + private String alg; + + // iv 可以为 null,base64 编码 + private String iv; + + // 计算数据 base64 编码 + private String data; +} diff --git a/chsm-web-server/src/test/java/com/sunyard/chsm/sdf/BCSdfApiServiceTest.java b/chsm-web-server/src/test/java/com/sunyard/chsm/sdf/BCSdfApiServiceTest.java new file mode 100644 index 0000000..58a7ecf --- /dev/null +++ b/chsm-web-server/src/test/java/com/sunyard/chsm/sdf/BCSdfApiServiceTest.java @@ -0,0 +1,49 @@ +package com.sunyard.chsm.sdf; + +import com.sunyard.chsm.WebServerApp; +import com.sunyard.chsm.enums.AlgMode; +import com.sunyard.chsm.enums.KeyAlg; +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; + + private byte[] data = new byte[1024]; + + // 对称加密解密测试 + @Test + void testSymECB() { + + 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); + } + + @Test + void testSymCBC() { + new Random().nextBytes(data); + + byte[] iv = new byte[16]; + + byte[] key = bcSdfApiService.genSymKey(KeyAlg.SM4); + byte[] enData = bcSdfApiService.symEncrypt(KeyAlg.SM4, AlgMode.CBC, key, iv, data); + byte[] deData = bcSdfApiService.symDecrypt(KeyAlg.SM4, AlgMode.CBC, key, iv, enData); + + Assert.assertArrayEquals(data, deData); + } +} diff --git a/chsm-web-server/src/test/java/sdf/BCSdfApiServiceTest.java b/chsm-web-server/src/test/java/sdf/BCSdfApiServiceTest.java deleted file mode 100644 index 40232e8..0000000 --- a/chsm-web-server/src/test/java/sdf/BCSdfApiServiceTest.java +++ /dev/null @@ -1,34 +0,0 @@ -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 ); - - } -}