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; } }