2
sunshine
2024-11-05 d1f9fb55a136e589a5ad588ed9a93ce9272917da
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package com.nova.sankuai.domain.api.yinsheng;
 
import cfca.sadk.algorithm.common.Mechanism;
import cfca.sadk.algorithm.sm2.SM2PublicKey;
import cfca.sadk.lib.crypto.JCrypto;
import cfca.sadk.lib.crypto.Session;
import cfca.sadk.util.EnvelopeUtil;
import cfca.sadk.util.KeyUtil;
import cfca.sadk.util.Signature;
import cfca.sadk.x509.certificate.X509Cert;
 
import java.security.PrivateKey;
 
 
/**
 * @类名称:GMSignUtil
 * @类描述:国密算法SM2签名工具类
 */
public class GMSignUtils {
 
    /**
     * 获取支付平台公钥证书
     * @param src
     * @return
     * @throws Exception
     */
    public static GMCertInfo getVerifyCertInfo(String src) throws Exception {
        GMCertInfo certInfo = new GMCertInfo();
        try{
            certInfo.ReadPublicKeyFromX509CertificateSM2(src);
        } catch (Exception e) {
            throw new Exception("银盛平台公钥证书加载失败");
        }
        return certInfo;
    }
 
 
    /**
     * 国密算法验证签名(报文)
     * @param certInfo
     * @param bcheck
     * @param xmlMsg
     * @throws Exception
     */
    public static boolean verifyMsgSignSM2(GMCertInfo certInfo, byte[] bcheck, byte[] xmlMsg){
        boolean bFlag;
        try{
            SM2PublicKey pubKey = certInfo.getPubKeySM2();
            final String deviceName = JCrypto.JSOFT_LIB;
            JCrypto.getInstance().initialize(deviceName, null);
            Session session = JCrypto.getInstance().openSession(deviceName);
            final Signature util = new Signature();
            final String signAlg = Mechanism.SM3_SM2;//SM3WithSM2
            // 校验,必须指定签名算法
            bFlag = util.p1VerifyMessage(signAlg,xmlMsg,bcheck,pubKey,session);
        } catch (Exception e) {
            bFlag = false;
            System.out.println("国密验签失败"+e);
        }
        return bFlag;
    }
 
    /**
     * 获取商户私钥证书
     * @param src
     * @return
     * @throws Exception
     */
    public synchronized static GMCertInfo getSignCertInfo(String src) throws Exception {
        //商户私钥证书
        String certfile = src;
        System.out.println("证书路经---"+certfile);
        GMCertInfo certInfo = new GMCertInfo();
        try {
            byte[] priKeySm2 = TextFileHelper.readFile(certfile);
            certInfo.setPriKey(priKeySm2);
        } catch (Exception e) {
            throw new Exception("商户签名证书加载失败");
        }
 
        return certInfo;
    }
 
    /**
     * 国密算法签名(报文)
     * @param sm2FilePath
     * @param msg
     * @return 返回 256长度base64编码
     * @throws Exception
     */
    public synchronized static String signMsgSM2(String sm2FilePath,String passWord, String msg) throws Exception {
        GMCertInfo certInfo = getSignCertInfo(sm2FilePath);
        // 返回的是256位
        byte[] signed;
        try {
            final String deviceName = JCrypto.JSOFT_LIB;
            JCrypto.getInstance().initialize(deviceName, null);
            Session session = JCrypto.getInstance().openSession(deviceName);
            PrivateKey priKey = KeyUtil.getPrivateKeyFromSM2(certInfo.getPriKey(),passWord);
//            PrivateKey priKey = KeyUtil.getPrivateKeyFromSM2(certInfo.getPriKey(),"ys123456");
            byte[] sourceData = msg.getBytes();
            Signature util = new Signature();
            String signAlg = Mechanism.SM3_SM2;//SM3WithSM2
            // 签名,必须指定签名算法,返回BASE64签名结果
            signed = util.p1SignMessage(signAlg, sourceData, priKey, session);
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("报文SM2签名失败");
        }
        String checkValue = new String(signed);
        return String.format("%-256s", checkValue);
    }
 
    /**
     * 国密算法数据加密(SM2公钥加密:长度通常限定为136字节内)
     * @param src
     * @param data
     * @throws Exception
     */
    public static String encryptData(String src,String data) throws Exception {
        String encryptMsg = null;
        GMCertInfo certInfo = getVerifyCertInfo(src);
        try {
            final String deviceName = JCrypto.JSOFT_LIB;
            JCrypto.getInstance().initialize(deviceName, null);
            final Session session = JCrypto.getInstance().openSession(deviceName);
            // 一个或者多个加密证书
            X509Cert[] recvcerts = new X509Cert[] { certInfo.getX509Cert() };
            byte[] base64Bytes = EnvelopeUtil.envelopeMessage(data.getBytes("UTF-8"), Mechanism.SM4_ECB, recvcerts, session);
            encryptMsg = new String(base64Bytes);
        } catch (Exception e) {
            throw new Exception("数据SM2加密失败");
        }
        return encryptMsg;
    }
 
}