package com.ydtech.modules.order.utils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.ydtech.constants.InsuranceEnum; import lombok.extern.slf4j.Slf4j; import org.springframework.util.Base64Utils; import javax.crypto.Cipher; import java.io.ByteArrayOutputStream; import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.*; /** * 签名工具 */ @Slf4j public class SignatureUtils { private SignatureUtils(){ throw new IllegalStateException("Utility class"); } /** * 加密算法RSA */ public static final String KEY_ALGORITHM = "RSA"; /** * 签名算法 */ public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; /** * RSA最大加密明文大小 */ private static final int MAX_ENCRYPT_BLOCK = 117; /** * RSA最大解密密文大小 */ private static final int MAX_DECRYPT_BLOCK = 128; /** * 验签并解密 *

* 对于银保信,publicKey是指合作方的公钥,privateKey是指银保信的私钥
* 对于合作方,publicKey是指银保信的公钥,privateKey是指合作方的私钥
* * @param request 原始报文(JSON字符串) * @param publicKey 公钥 * @param privateKey 私钥 * @param isCheckSign 是否验签 * @param isDecrypt 是否解密 * @return 解密后的明文,验签失败则异常抛出 */ public static String checkSignAndDecrypt(String request, String sign, String publicKey, String privateKey, boolean isCheckSign, boolean isDecrypt) { boolean verifyResult = false; JSONObject requestJSONObject = JSONObject.parseObject(request); String bizContent = requestJSONObject.getString("bizContent");// 获取的业务数据密文 String signContent = getSignContent(requestJSONObject);// 所有key排序后放入LingkedMap后map.toString() if (isCheckSign) { verifyResult = verify(signContent, sign, publicKey); } if (!isCheckSign) { verifyResult = true; } if (isDecrypt && verifyResult) { return decryptByPrivateKey(bizContent, privateKey); } return null; } public static String checkSignAndDecryptNew(String request, String sign, String publicKey, String privateKey, boolean isCheckSign, boolean isDecrypt) throws Exception { boolean verifyResult = false; JSONObject requestJSONObject = JSONObject.parseObject(request); String bizContent = requestJSONObject.getString("bizContent");// 获取的业务数据密文 String insurerCode = requestJSONObject.getString("insurerCode"); String sysSourceCode = requestJSONObject.getString("sysSourceCode"); String signContent = getSignContent(requestJSONObject);// 所有key排序后放入LingkedMap后map.toString() if (isCheckSign) { verifyResult = verify(signContent, sign, publicKey); } if (!isCheckSign) { verifyResult = true; } if (isDecrypt && verifyResult) { String json = decryptByPrivateKey(bizContent, privateKey); String oldChar = "\\{"; String newChar = "{\"sysSourceCode\": \"" + sysSourceCode + "\",\"insurerCode\": \"" + insurerCode + "\","; return json.replaceFirst(oldChar, newChar); } return null; } /** * 加密并签名 *

* 对于银保信,publicKey是指合作方的公钥,privateKey是指银保信的私钥
* 对于合作方,publicKey是指银保信的公钥,privateKey是指合作方的私钥
* * @param publicKey 公钥 * @param requestContent 报文原文 * @param isCheckSign 是否签名 * @param isEncrypt 是否加密 * @return 加密加签后的返回报文 * @throws Exception */ public static Map encryptAndSign(String privateKey, String publicKey, String requestContent, boolean isCheckSign, boolean isEncrypt) throws Exception { JSONObject requestJSONObject = JSONObject.parseObject(requestContent); String bizContent = requestJSONObject.getString("bizContent"); Map map = new HashMap(); if (isEncrypt) { //加密 String encryptBizContent = encryptByPublicKey(bizContent, publicKey);//对业务数据进行加密 requestJSONObject.put("bizContent", encryptBizContent);//将加密后的数据替换原有的明文 map.put("content", requestJSONObject.toJSONString()); if (isCheckSign) { //加签 String signContent = getSignContent(requestJSONObject);// 所有key排序后放入LingkedMap后map.toString() String sign = sign(signContent, privateKey); map.put("signature", sign); } } else if (isCheckSign) {// 只加签、不加密 String signContent = getSignContent(requestJSONObject);// 所有key排序后放入LingkedMap后map.toString() String sign = sign(signContent, privateKey); map.put("signature", sign); } return map; } /** * 封装待验签的内容 * * @param sortedParam * @return */ public static String getSignContent(Map sortedParam) { LinkedHashMap map = new LinkedHashMap(); List keys = new ArrayList(sortedParam.keySet()); Collections.sort(keys); for (int i = 0; i < keys.size(); i++) { String key = keys.get(i); String value = sortedParam.get(key).toString(); map.put(key, value); } return map.toString(); } /** * 验签 * * @param request * @param sign * @param * @return */ public static boolean verify(String request, String sign, String publicKey) { try { return SignatureUtils.verify(request.getBytes(), publicKey, sign); } catch (Exception e) { log.error("验签异常,inputParams: {} and publicKey: {} and sign: {} and errorMessage: {}", request, publicKey, sign, e.getMessage(), e); throw new RuntimeException(e); } } /** *

* 校验数字签名 *

* * @param data 已加密数据 * @param publicKey 公钥(BASE64编码) * @param sign 数字签名 * @return * @throws Exception */ public static boolean verify(byte[] data, String publicKey, String sign) throws Exception { byte[] keyBytes = Base64Utils.decode(publicKey.getBytes()); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PublicKey publicK = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(publicK); signature.update(data); return signature.verify(Base64Utils.decode(sign.getBytes())); } /** * 私钥对数据进行解密 * * @param bizContent * @param privateKey * @return */ public static String decryptByPrivateKey(String bizContent, String privateKey) { try { return new String(SignatureUtils.decryptByPrivateKey(Base64Utils.decode(bizContent.getBytes()), privateKey)); } catch (Exception e) { log.error("私钥解密异常,inputParams: {} and privateKey: {} and errorMessage: {}", bizContent, privateKey, e.getMessage(), e); throw new RuntimeException(e); } } /** *

* 私钥解密 *

* * @param encryptedData 已加密数据 * @param privateKey 私钥(BASE64编码) * @return * @throws Exception */ public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decode(privateKey.getBytes()); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateK); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } /** * 公钥加密 * * @param request * @param publicKey * @return */ public static String encryptByPublicKey(String request, String publicKey) throws Exception { return new String(Base64Utils.encode(SignatureUtils.encryptByPublicKey(request.getBytes(), publicKey))); } /** *

* 公钥加密 *

* * @param data 源数据 * @param publicKey 公钥(BASE64编码) * @return * @throws Exception */ public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception { byte[] keyBytes = Base64Utils.decode(publicKey.getBytes()); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePublic(x509KeySpec); // 对数据加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段加密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } /** * 加签 * * @param * @param privateKey * @return */ public static String sign(String request, String privateKey) { try { return SignatureUtils.sign(request.getBytes(), privateKey); } catch (Exception e) { log.error("加签异常,inputParams: {} and privateKey: {} and errorMessage: {}", request, privateKey, e.getMessage(), e); throw new RuntimeException(e); } } /** *

* 用私钥对信息生成数字签名 *

* * @param data 已加密数据 * @param privateKey 私钥(BASE64编码) * @return * @throws Exception */ public static String sign(byte[] data, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decode(privateKey.getBytes()); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(privateK); signature.update(data); return new String(Base64Utils.encode(signature.sign())); } public static T decryptMessage(String s, Class c, String message, String sessionKey) { InsuranceLog.infoLog(InsuranceEnum.ZMBX.getPinyin(), "\n\t---------> 解密前的参数:{}", s); // 解密 String text = decryptByPrivateKey(s.replace("\n", ""), sessionKey); InsuranceLog.infoLog(InsuranceEnum.ZMBX.getPinyin(), "\n\t---------> {}:{}", message, text); return JSON.parseObject(text, c); } }