sanlin.shi 1 month ago
parent
commit
b17499114e

BIN
libs/anicert-encrypt-1.0.4.jar


BIN
libs/anicert-encrypt-bc-1.0.4.jar


+ 16 - 1
pom.xml

@@ -40,7 +40,7 @@
         <mybatis-plus.version>3.5.2</mybatis-plus.version>
         <fastjson.version>1.2.74</fastjson.version>
         <jjwt.version>0.9.1</jjwt.version>
-        <commons-codec.version>1.10</commons-codec.version>
+        <commons-codec.version>1.11</commons-codec.version>
         <hutool.version>5.7.7</hutool.version>
         <swagger-version>3.0.0</swagger-version>
     </properties>
@@ -185,6 +185,21 @@
             <version>4.0.2</version>
         </dependency>
 
+        <dependency>
+            <groupId>anicert.encrypt</groupId>
+            <artifactId>anicert-encrypt</artifactId>
+            <version>1.0.4</version>
+            <scope>system</scope>
+            <systemPath>${project.basedir}/libs/anicert-encrypt-1.0.4.jar</systemPath>
+        </dependency>
+        <dependency>
+            <groupId>anicert.encrypt.bc</groupId>
+            <artifactId>anicert-encrypt-bc</artifactId>
+            <version>1.0.4</version>
+            <scope>system</scope>
+            <systemPath>${project.basedir}/libs/anicert-encrypt-bc-1.0.4.jar</systemPath>
+        </dependency>
+
     </dependencies>
 
     <build>

+ 14 - 0
src/main/java/cn/hanghui/outapi/platform/alipay/controller/AlipayFaceAuthController.java

@@ -84,6 +84,20 @@ public class AlipayFaceAuthController {
     }
 
 
+    @ApiOperation("获取公安一所支付宝用户信息")
+    @PostMapping("/ga/user/info/query")
+    public Result<AlipayUserInfo> queryGaUserInfo(@RequestBody @Validated AlipayUserInfoReqDto alipayUserInfoReqDto) {
+        log.info("--->获取公安一所支付宝用户信息原始入参:{}", JSONObject.toJSONString(alipayUserInfoReqDto));
+        if (alipayUserInfoReqDto.getAuthCode() == null
+                && alipayUserInfoReqDto.getSn() == null
+                && alipayUserInfoReqDto.getFtoken() == null
+                && alipayUserInfoReqDto.getAlipayUid() == null) {
+            log.error("--->获取公安一所用户信息原始入参参数有误");
+            return Result.ok(new AlipayUserInfo());
+        }
+        return Result.ok(alipayFaceAuthService.queryGaUserInfo(alipayUserInfoReqDto));
+    }
+
 
     /**
      * 商家授权成功后,商家的页面跳转至服务商定义的回调地址(即 redirect_uri 参数对应的 URL),

+ 33 - 0
src/main/java/cn/hanghui/outapi/platform/alipay/entity/dto/GaAlipayUserInfoBizPackageReq.java

@@ -0,0 +1,33 @@
+package cn.hanghui.outapi.platform.alipay.entity.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author shisl
+ * @package cn.hanghui.outapi.platform.alipay.entity.dto
+ * @class GaAlipayUserInfoBizPackageReq
+ * @date 2024/11/28 下午9:59
+ * @description 获取公安一所支付宝用户信息入参
+ */
+@Data
+public class GaAlipayUserInfoBizPackageReq extends AlipayUserInfoReqDto implements Serializable {
+    /**
+     * 业务流水号(公安)
+     */
+    private String requestId;
+    /**
+     * 请求时间戳(公安)
+     */
+    private String requestTime;
+    /**
+     * 安全芯片id(公安)
+     */
+    private String seid;
+    /**
+     * 请求接口标识 固定值:11001(公安)
+     */
+    private String bizType;
+
+}

+ 27 - 0
src/main/java/cn/hanghui/outapi/platform/alipay/entity/dto/GaAlipayUserInfoReq.java

@@ -0,0 +1,27 @@
+package cn.hanghui.outapi.platform.alipay.entity.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author shisl
+ * @package cn.hanghui.outapi.platform.alipay.entity.dto
+ * @class GaAlipayUserInfoReq
+ * @date 2024/11/28 下午9:59
+ * @description 获取公安一所支付宝用户信息入参
+ */
+@Data
+public class GaAlipayUserInfoReq implements Serializable {
+
+    /**
+     * 签名
+     */
+    private String sign;
+    /**
+     * 加密数据
+     */
+    private String bizPackage;
+
+
+}

+ 33 - 0
src/main/java/cn/hanghui/outapi/platform/alipay/entity/dto/GaAlipayUserInfoResp.java

@@ -0,0 +1,33 @@
+package cn.hanghui.outapi.platform.alipay.entity.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author shisl
+ * @package cn.hanghui.outapi.platform.alipay.entity.dto
+ * @class GaAlipayUserInfoResp
+ * @date 2024/11/28 下午9:59
+ * @description 获取公安一所支付宝用户信息响应参数
+ */
+@Data
+public class GaAlipayUserInfoResp implements Serializable {
+
+    /**
+     * 状态码,“0”表示成功,其它失败
+     */
+    private String resultCode;
+    /**
+     * 错误信息描述(可为空)
+     */
+    private String resultDesc;
+
+    /**
+     * 业务数据 AlipayUserInfo
+     */
+    private Object bizData;
+
+
+
+}

+ 7 - 0
src/main/java/cn/hanghui/outapi/platform/alipay/service/AlipayFaceAuthService.java

@@ -39,4 +39,11 @@ public interface AlipayFaceAuthService {
     AlipayUserInfo queryCommonUserInfo(AlipayUserInfoReqDto alipayUserInfoReqDto);
 
 
+    /**
+     * 获取公安一所支付宝用户信息
+     *
+     * @param alipayUserInfoReqDto
+     * @return
+     */
+    AlipayUserInfo queryGaUserInfo(AlipayUserInfoReqDto alipayUserInfoReqDto);
 }

+ 76 - 1
src/main/java/cn/hanghui/outapi/platform/alipay/service/impl/AlipayFaceAuthServiceImpl.java

@@ -4,23 +4,36 @@ import cn.hanghui.outapi.platform.alipay.api.AlipayCommonApi;
 import cn.hanghui.outapi.platform.alipay.api.AlipayUserApi;
 import cn.hanghui.outapi.platform.alipay.entity.dto.AlipayUserInfoExtInfoReqDto;
 import cn.hanghui.outapi.platform.alipay.entity.dto.AlipayUserInfoReqDto;
+import cn.hanghui.outapi.platform.alipay.entity.dto.GaAlipayUserInfoBizPackageReq;
+import cn.hanghui.outapi.platform.alipay.entity.dto.GaAlipayUserInfoReq;
 import cn.hanghui.outapi.platform.alipay.entity.param.AlipayUserInfo;
 import cn.hanghui.outapi.platform.alipay.service.AlipayFaceAuthService;
 import cn.hanghui.outapi.platform.alipay.service.AlipayOpenApiService;
-import cn.hanghui.outapi.platform.common.entity.rest.RestResult;
 import cn.hanghui.outapi.platform.common.service.BaseService;
+import cn.hanghui.outapi.platform.common.utils.CipherUtil;
+import cn.hanghui.outapi.platform.common.utils.JSONUtil;
 import cn.hanghui.outapi.platform.common.utils.Preconditions;
+import cn.hanghui.outapi.platform.common.utils.SM2KeyUtil;
+import cn.hanghui.outapi.platform.common.utils.SnowflakeIdWorker;
 import cn.hanghui.outapi.platform.tenant.entity.dto.TenantVo;
 import cn.hanghui.outapi.platform.tenant.service.TenantService;
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.lang.UUID;
+import cn.hutool.crypto.digest.DigestUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.http.HttpUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.alipay.api.AlipayClient;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.Map;
 
 @Service
 @Slf4j
@@ -280,5 +293,67 @@ public class AlipayFaceAuthServiceImpl extends BaseService implements AlipayFace
         return userInfo;
     }
 
+    @Value("${ga.alipayUserInfoUrl}")
+    private String alipayUserInfoUrl;
+    @Value("${ga.seid}")
+    private String seid;
+    @Value("${ga.bizType}")
+    private String bizType;
+    @Value("${ga.signKey}")
+    private String signKey;
+    @Value("${ga.verifySignKey}")
+    private String verifySignKey;
+    @Value("${ga.signKey}")
+    private String encryptKey;
+
+
+    @Override
+    public AlipayUserInfo queryGaUserInfo(AlipayUserInfoReqDto alipayUserInfoReqDto) {
+        GaAlipayUserInfoReq alipayUserInfoReq = new GaAlipayUserInfoReq();
+        //bizPackage组装业务参数
+        GaAlipayUserInfoBizPackageReq bizPackage = BeanUtil.copyProperties(alipayUserInfoReqDto, GaAlipayUserInfoBizPackageReq.class);
+        bizPackage.setRequestId(DigestUtil.md5Hex(SnowflakeIdWorker.getSnowId() + UUID.randomUUID().toString().replace("-", "")));
+        bizPackage.setRequestTime(String.valueOf(System.currentTimeMillis()));
+        bizPackage.setSeid(seid);
+        bizPackage.setBizType(bizType);
+        alipayUserInfoReq.setBizPackage(JSONObject.toJSONString(bizPackage));
+        //签名
+        String body = JSONUtil.toJson(bizPackage);
+        String sign = doSignature(body);
+        alipayUserInfoReq.setSign(sign);
+
+        // 添加请求头信息
+        Map<String, String> heads = new HashMap<>();
+        // 使用json发送请求,下面的是必须的
+        heads.put("Content-Type", "application/json;charset=UTF-8");
+        heads.put("gp_sign", sign);
+        HttpResponse resp = HttpRequest.post(alipayUserInfoUrl)
+                .headerMap(heads, false)
+                .body(String.valueOf(body))
+                .timeout(5 * 60 * 1000)
+                .execute();
+        log.info("--->获取公安一所支付宝用户信息响应参数:{}", JSONObject.toJSONString(resp));
+        GaAlipayUserInfoReq userInfoResq = JSONObject.parseObject(resp.body(), GaAlipayUserInfoReq.class);
+        userInfoResq.getBizPackage();
+        CipherUtil.decrypt();
+
+
+        return null;
+    }
+
+    /**
+     * 接口请求数据签名
+     *
+     * @param params 1
+     * @return java.lang.String
+     * @author Gaoch
+     * @since 2022/04/20 10:48:13
+     */
+    private String doSignature(String... params) {
+        String content = String.join(";", params);
+        log.info("签名原文:" + content);
+        return CipherUtil.sign(signKey, content);
+    }
+
 
 }

+ 263 - 0
src/main/java/cn/hanghui/outapi/platform/common/utils/CipherUtil.java

@@ -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);
+    }
+}

+ 47 - 0
src/main/java/cn/hanghui/outapi/platform/common/utils/JSONUtil.java

@@ -0,0 +1,47 @@
+package cn.hanghui.outapi.platform.common.utils;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+/**
+ * @author shisl
+ * @package cn.hanghui.outapi.platform.common.utils
+ * @class JSONUtil
+ * @date 2024/11/28 下午11:02
+ * @description
+ */
+public class JSONUtil {
+    private static final ObjectMapper mapper;
+
+    static {
+        mapper = new ObjectMapper();
+        mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
+        //取消默认转换timestamps形式
+        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+        //忽略空Bean转json的错误
+        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+        //允许pojo中有在json串中不存在的字段
+        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        //允许有注释
+        mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
+    }
+
+    public static String toJson(Object obj) {
+        try {
+            return mapper.writeValueAsString(obj);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static <T> T parse(String content, Class<T> clazz) {
+        try {
+            return mapper.readValue(content, clazz);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}

+ 152 - 0
src/main/java/cn/hanghui/outapi/platform/common/utils/SM2KeyUtil.java

@@ -0,0 +1,152 @@
+package cn.hanghui.outapi.platform.common.utils;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+import org.bouncycastle.asn1.gm.GMNamedCurves;
+import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
+import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
+import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
+import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.jce.spec.ECNamedCurveSpec;
+import org.bouncycastle.math.ec.ECCurve;
+import java.util.Base64;
+
+import java.math.BigInteger;
+import java.security.*;
+import java.security.spec.*;
+
+/**
+ * @author Ivan
+ * @description
+ * @date 2020/5/27
+ */
+public class SM2KeyUtil {
+    public static final BouncyCastleProvider bcProvider = new BouncyCastleProvider();
+
+    private static final X9ECParameters ecParameters;
+
+    private static final ECNamedCurveSpec sm2Spec;
+
+    private static final KeyPairGenerator keyGenerator;
+    private static final KeyFactory keyFactory;
+    private static final ECCurve curve;
+
+
+    static {
+        try {
+            // 获取SM2 椭圆曲线推荐参数
+            ecParameters = GMNamedCurves.getByName("sm2p256v1");
+
+            // 构造EC 算法参数
+            sm2Spec = new ECNamedCurveSpec(
+                    // 设置SM2 算法的 OID
+                    GMObjectIdentifiers.sm2p256v1.toString()
+                    // 设置曲线方程
+                    , ecParameters.getCurve()
+                    // 椭圆曲线G点
+                    , ecParameters.getG()
+                    // 大整数N
+                    , ecParameters.getN());
+
+            // bouncycastle算法提供器
+
+
+            keyGenerator = KeyPairGenerator.getInstance("EC", bcProvider);
+            keyGenerator.initialize(sm2Spec, new SecureRandom());
+
+            keyFactory = KeyFactory.getInstance("EC", bcProvider);
+            curve = ecParameters.getCurve();
+        } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
+            throw new RuntimeException("无法提供SM2算法", e);
+        }
+    }
+
+    public static KeyPair genKeyPair() {
+        return keyGenerator.generateKeyPair();
+    }
+
+    public static byte[] encodeWithPoint(BCECPublicKey pub) {
+        return pub.getQ().getEncoded(false);
+    }
+
+    public static BCECPublicKey decodeWithPoint(byte[] data) throws InvalidKeySpecException {
+        ECPoint point = EC5Util.convertPoint(curve.decodePoint(data));
+        return (BCECPublicKey) keyFactory.generatePublic(new ECPublicKeySpec(point, sm2Spec));
+    }
+
+    public static String encodeStrWithPoint(BCECPublicKey pub) {
+        return Hex.encodeHexString(encodeWithPoint(pub),false);
+    }
+
+    public static BCECPublicKey decodeWithPoint(String hex) throws InvalidKeySpecException, DecoderException {
+        return decodeWithPoint(Hex.decodeHex(hex));
+    }
+
+    public static String getX64(BCECPublicKey pub) {
+        return Base64.getEncoder().encodeToString(pub.getQ().getXCoord().getEncoded());
+    }
+
+    public static String getY64(BCECPublicKey pub) {
+        return Base64.getEncoder().encodeToString(pub.getQ().getYCoord().getEncoded());
+    }
+
+    public static BCECPublicKey fromXY(String x64, String y64) throws InvalidKeySpecException {
+        return fromXY(Base64.getDecoder().decode(x64), Base64.getDecoder().decode(y64));
+    }
+
+    public static byte[] getX(BCECPublicKey pub) {
+        return pub.getQ().getXCoord().getEncoded();
+    }
+
+    public static byte[] getY(BCECPublicKey pub) {
+        return pub.getQ().getYCoord().getEncoded();
+    }
+
+    public static BCECPublicKey fromXY(byte[] x, byte[] y) throws InvalidKeySpecException {
+        ECPoint point = EC5Util.convertPoint(curve.createPoint(new BigInteger(1, x), new BigInteger(1, y)));
+        return (BCECPublicKey) keyFactory.generatePublic(new ECPublicKeySpec(point, sm2Spec));
+    }
+
+    public static byte[] encodeWithBigInteger(BCECPrivateKey pri) {
+        return pri.getD().toByteArray();
+    }
+
+    public static BCECPrivateKey decodeWithBigInteger(byte[] data) throws InvalidKeySpecException {
+        return (BCECPrivateKey) keyFactory.generatePrivate(new ECPrivateKeySpec(new BigInteger(1, data), sm2Spec));
+    }
+
+    public static String encodeStrWithBigInteger(BCECPrivateKey pri) {
+        return Hex.encodeHexString(encodeWithBigInteger(pri),false);
+    }
+
+    public static BCECPrivateKey decodeWithBigInteger(String hex) throws InvalidKeySpecException, DecoderException {
+        return decodeWithBigInteger(Hex.decodeHex(hex));
+    }
+
+    public static byte[] encodeWithKey(Key key) {
+        return key.getEncoded();
+    }
+
+    public static BCECPublicKey decodeWithX509(byte[] data) throws InvalidKeySpecException {
+        return (BCECPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(data));
+    }
+
+    public static BCECPrivateKey decodeWithPKCS8(byte[] data) throws InvalidKeySpecException {
+        return (BCECPrivateKey) keyFactory.generatePrivate(new PKCS8EncodedKeySpec(data));
+    }
+
+    public static String encodeStrWithKey(Key key) {
+        return Base64.getEncoder().encodeToString(encodeWithKey(key));
+    }
+
+    public static BCECPublicKey decodeWithX509(String base64) throws InvalidKeySpecException {
+        return decodeWithX509(Base64.getDecoder().decode(base64.replaceAll("-----.*-----", "")));
+    }
+
+    public static BCECPrivateKey decodeWithPKCS8(String base64) throws InvalidKeySpecException {
+        return decodeWithPKCS8(Base64.getDecoder().decode(base64.replaceAll("-----.*-----", "")));
+    }
+
+}

+ 15 - 2
src/main/resources/application-prod.yml

@@ -227,6 +227,19 @@ proof:
   privateKey: rgcfenyi4f73ooy5
 
 
-
-
+# 公安一所
+ga:
+  alipayUserInfoUrl: https://[ip]:[port]/alipayApi/faceAuth/getAlipayUserInfo
+  # 安全芯片id
+  seid:
+  # 请求接口标识 固定值:1100
+  bizType: 11001
+  # 签名密钥
+  signKey:
+  # 验签密钥
+  verifySignKey:
+  # 加密公钥
+  encryptKey: e51a1af31337b4fbeab817e8338aa2caf2ed31d361f41012696854195f3c4a3b85cb2dc5704808d300b80dc0ea68808bf9cfba06ebfc550f2eb0b6f6383f0ac5
+  # 解密私钥
+  decryptKey: a08d6b327501b9a6c14aa64b194bb4df338604945baecde8928b980e505080bb