|
@@ -0,0 +1,263 @@
|
|
|
+package cn.hanghui.outapi.platform.common.utils;
|
|
|
+
|
|
|
+import cn.anicert.module.encrypt.IKeyFactory;
|
|
|
+import cn.anicert.module.encrypt.ISM3;
|
|
|
+import cn.anicert.module.encrypt.bc.BcKeyFactory;
|
|
|
+import cn.anicert.module.encrypt.bc.BcSM3;
|
|
|
+import cn.anicert.module.encrypt.bc.BcSm2Cipher;
|
|
|
+import cn.anicert.module.encrypt.enums.CipherMode;
|
|
|
+import org.apache.commons.codec.DecoderException;
|
|
|
+import org.apache.commons.codec.binary.Hex;
|
|
|
+
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.security.PrivateKey;
|
|
|
+import java.security.PublicKey;
|
|
|
+import java.util.Base64;
|
|
|
+/**
|
|
|
+ * @author shisl
|
|
|
+ * @package cn.hanghui.outapi.platform.common.utils
|
|
|
+ * @class CipherUtil
|
|
|
+ * @date 2024/11/28 下午10:37
|
|
|
+ * @description
|
|
|
+ */
|
|
|
+public class CipherUtil {
|
|
|
+ private static final BcSm2Cipher SM2 = new BcSm2Cipher();
|
|
|
+ private static final ISM3 SM3 = new BcSM3();
|
|
|
+ private static final IKeyFactory bcKeyFactory = new BcKeyFactory();
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 用于向SIM卡内传输数据加密
|
|
|
+ * @author Gaoch
|
|
|
+ * @since 2023/01/03 09:50:04
|
|
|
+ * @param encKeyHex 1
|
|
|
+ * @param content 2
|
|
|
+ * @return java.lang.String
|
|
|
+ */
|
|
|
+ public static String encryptRaw(String encKeyHex, byte[] content) {
|
|
|
+ try {
|
|
|
+ byte[] bytes = SM2.encryptCipher(parsePublicKeyFromRaw("04"+encKeyHex), content,CipherMode.C1C3C2);
|
|
|
+ byte[] temp = new byte[bytes.length - 1];
|
|
|
+ System.arraycopy(bytes, 1, temp, 0, temp.length);
|
|
|
+ return encodeHex(temp);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("加密异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 用于SIM卡内读取数据解密
|
|
|
+ * @author Gaoch
|
|
|
+ * @since 2023/01/03 09:50:33
|
|
|
+ * @param decKeyHex 1
|
|
|
+ * @param encHexData 2
|
|
|
+ * @return java.lang.String
|
|
|
+ */
|
|
|
+ public static byte[] decryptRaw(String decKeyHex, String encHexData) {
|
|
|
+ try {
|
|
|
+ return SM2.decryptCipher(parsePrivateKeyFromRaw(decKeyHex), decodeHex("04"+encHexData),CipherMode.C1C3C2);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("解密异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 接口敏感数据数字信封加密
|
|
|
+ *
|
|
|
+ * @param encKey 1
|
|
|
+ * @param content 2
|
|
|
+ * @return java.lang.String
|
|
|
+ * @author Gaoch
|
|
|
+ * @since 2022/04/19 08:59:56
|
|
|
+ */
|
|
|
+ public static String encrypt(String encKey, byte[] content) {
|
|
|
+ try {
|
|
|
+ byte[] bytes = SM2.encryptEnvelope(parsePublicKey(encKey), content);
|
|
|
+ return encodeBase64(bytes);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("加密异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 接口敏感数据数字信封解密
|
|
|
+ *
|
|
|
+ * @param decKey 1
|
|
|
+ * @param encBase64Data 2
|
|
|
+ * @return java.lang.String
|
|
|
+ * @author Gaoch
|
|
|
+ * @since 2023/01/03 09:51:44
|
|
|
+ */
|
|
|
+ public static byte[] decrypt(String decKey, String encBase64Data) {
|
|
|
+ try {
|
|
|
+ return SM2.decryptEnvelope(parsePrivateKey(decKey), decodeBase64(encBase64Data));
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("解密异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 接口请求签名
|
|
|
+ *
|
|
|
+ * @param source 1
|
|
|
+ * @param signKey 2
|
|
|
+ * @return java.lang.String
|
|
|
+ * @author Gaoch
|
|
|
+ * @since 2022/04/19 09:00:06
|
|
|
+ */
|
|
|
+ public static String sign(String signKey, String source) {
|
|
|
+ try {
|
|
|
+ byte[] data = SM2.sign(parsePrivateKey(signKey), source.getBytes(StandardCharsets.UTF_8));
|
|
|
+ return encodeBase64(data);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("签名异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 接口响应验签
|
|
|
+ *
|
|
|
+ * @param content 1
|
|
|
+ * @param sign 2
|
|
|
+ * @return boolean
|
|
|
+ * @author Gaoch
|
|
|
+ * @since 2022/04/19 09:00:13
|
|
|
+ */
|
|
|
+ public static boolean verifySign(String verifySignKey, String content, String sign) {
|
|
|
+ try {
|
|
|
+ return SM2.verify(parsePublicKey(verifySignKey), content.getBytes(StandardCharsets.UTF_8), decodeBase64(sign));
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("验签异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * SM3哈希
|
|
|
+ * @author Gaoch
|
|
|
+ * @since 2023/01/03 09:52:19
|
|
|
+ * @param source 1
|
|
|
+ * @return java.lang.String
|
|
|
+ */
|
|
|
+ public static String hash(String source) {
|
|
|
+ try {
|
|
|
+ byte[] data = SM3.hash(source.getBytes(StandardCharsets.UTF_8));
|
|
|
+ return encodeHex(data);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("SM3摘要异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String hash(byte[] source) {
|
|
|
+ try {
|
|
|
+ byte[] data = SM3.hash(source);
|
|
|
+ return encodeHex(data);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("SM3摘要异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * BASE64编码
|
|
|
+ *
|
|
|
+ * @param data 1
|
|
|
+ * @return java.lang.String
|
|
|
+ * @author Gaoch
|
|
|
+ * @since 2022/04/19 09:00:22
|
|
|
+ */
|
|
|
+ public static String encodeBase64(byte[] data) {
|
|
|
+ return Base64.getEncoder().encodeToString(data);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * HEX编码
|
|
|
+ * @author Gaoch
|
|
|
+ * @since 2023/01/03 09:52:32
|
|
|
+ * @param data 1
|
|
|
+ * @return java.lang.String
|
|
|
+ */
|
|
|
+ public static String encodeHex(byte[] data) {
|
|
|
+ return Hex.encodeHexString(data, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * BASE64解码
|
|
|
+ *
|
|
|
+ * @param data 1
|
|
|
+ * @return byte[]
|
|
|
+ * @author Gaoch
|
|
|
+ * @since 2022/04/19 09:00:30
|
|
|
+ */
|
|
|
+ public static byte[] decodeBase64(String data) {
|
|
|
+ return Base64.getDecoder().decode(data);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * HEX解码
|
|
|
+ * @author Gaoch
|
|
|
+ * @since 2023/01/03 09:53:16
|
|
|
+ * @param hex 1
|
|
|
+ * @return byte[]
|
|
|
+ */
|
|
|
+ public static byte[] decodeHex(String hex) {
|
|
|
+ try {
|
|
|
+ return Hex.decodeHex(hex.toCharArray());
|
|
|
+ } catch (DecoderException e) {
|
|
|
+ throw new RuntimeException("HEX解码失败",e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static PublicKey parsePublicKeyFromRaw(String pubHex) {
|
|
|
+ //解析公钥
|
|
|
+ try {
|
|
|
+ return SM2KeyUtil.decodeWithPoint(pubHex);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * HEX 原始格式私钥转换
|
|
|
+ * @author Gaoch
|
|
|
+ * @since 2023/01/03 09:54:49
|
|
|
+ * @param privHex 1
|
|
|
+ * @return java.security.PrivateKey
|
|
|
+ */
|
|
|
+ private static PrivateKey parsePrivateKeyFromRaw(String privHex) {
|
|
|
+ //解析私钥
|
|
|
+ try {
|
|
|
+ return SM2KeyUtil.decodeWithBigInteger(privHex);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Base64 DER格式公钥转换
|
|
|
+ * @author Gaoch
|
|
|
+ * @since 2023/01/03 09:55:06
|
|
|
+ * @param pubStr 1
|
|
|
+ * @return java.security.PublicKey
|
|
|
+ */
|
|
|
+ private static PublicKey parsePublicKey(String pubStr) {
|
|
|
+ //解析公钥
|
|
|
+ byte[] pub = decodeBase64(pubStr);
|
|
|
+ return bcKeyFactory.parseSm2PublicKey(pub);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Base64 DER格式私钥转换
|
|
|
+ * @author Gaoch
|
|
|
+ * @since 2023/01/03 09:55:06
|
|
|
+ * @param privStr 1
|
|
|
+ * @return java.security.PublicKey
|
|
|
+ */
|
|
|
+ private static PrivateKey parsePrivateKey(String privStr) {
|
|
|
+ //解析私钥
|
|
|
+ byte[] pri = decodeBase64(privStr);
|
|
|
+ return bcKeyFactory.parseSm2PrivateKey(pri);
|
|
|
+ }
|
|
|
+}
|