SignatureUtils.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. package com.ydtech.modules.order.utils;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.ydtech.constants.InsuranceEnum;
  5. import lombok.extern.slf4j.Slf4j;
  6. import org.springframework.util.Base64Utils;
  7. import javax.crypto.Cipher;
  8. import java.io.ByteArrayOutputStream;
  9. import java.security.*;
  10. import java.security.spec.PKCS8EncodedKeySpec;
  11. import java.security.spec.X509EncodedKeySpec;
  12. import java.util.*;
  13. /**
  14. * 签名工具
  15. */
  16. @Slf4j
  17. public class SignatureUtils {
  18. private SignatureUtils(){
  19. throw new IllegalStateException("Utility class");
  20. }
  21. /**
  22. * 加密算法RSA
  23. */
  24. public static final String KEY_ALGORITHM = "RSA";
  25. /**
  26. * 签名算法
  27. */
  28. public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
  29. /**
  30. * RSA最大加密明文大小
  31. */
  32. private static final int MAX_ENCRYPT_BLOCK = 117;
  33. /**
  34. * RSA最大解密密文大小
  35. */
  36. private static final int MAX_DECRYPT_BLOCK = 128;
  37. /**
  38. * 验签并解密
  39. * <p>
  40. * 对于<b>银保信</b>,publicKey是指合作方的公钥,privateKey是指银保信的私钥<br>
  41. * 对于<b>合作方</b>,publicKey是指银保信的公钥,privateKey是指合作方的私钥<br>
  42. *
  43. * @param request 原始报文(JSON字符串)
  44. * @param publicKey 公钥
  45. * @param privateKey 私钥
  46. * @param isCheckSign 是否验签
  47. * @param isDecrypt 是否解密
  48. * @return 解密后的明文,验签失败则异常抛出
  49. */
  50. public static String checkSignAndDecrypt(String request, String sign, String publicKey, String privateKey, boolean isCheckSign,
  51. boolean isDecrypt) {
  52. boolean verifyResult = false;
  53. JSONObject requestJSONObject = JSONObject.parseObject(request);
  54. String bizContent = requestJSONObject.getString("bizContent");// 获取的业务数据密文
  55. String signContent = getSignContent(requestJSONObject);// 所有key排序后放入LingkedMap后map.toString()
  56. if (isCheckSign) {
  57. verifyResult = verify(signContent, sign, publicKey);
  58. }
  59. if (!isCheckSign) {
  60. verifyResult = true;
  61. }
  62. if (isDecrypt && verifyResult) {
  63. return decryptByPrivateKey(bizContent, privateKey);
  64. }
  65. return null;
  66. }
  67. public static String checkSignAndDecryptNew(String request, String sign, String publicKey, String privateKey, boolean isCheckSign,
  68. boolean isDecrypt) throws Exception {
  69. boolean verifyResult = false;
  70. JSONObject requestJSONObject = JSONObject.parseObject(request);
  71. String bizContent = requestJSONObject.getString("bizContent");// 获取的业务数据密文
  72. String insurerCode = requestJSONObject.getString("insurerCode");
  73. String sysSourceCode = requestJSONObject.getString("sysSourceCode");
  74. String signContent = getSignContent(requestJSONObject);// 所有key排序后放入LingkedMap后map.toString()
  75. if (isCheckSign) {
  76. verifyResult = verify(signContent, sign, publicKey);
  77. }
  78. if (!isCheckSign) {
  79. verifyResult = true;
  80. }
  81. if (isDecrypt && verifyResult) {
  82. String json = decryptByPrivateKey(bizContent, privateKey);
  83. String oldChar = "\\{";
  84. String newChar = "{\"sysSourceCode\": \"" + sysSourceCode + "\",\"insurerCode\": \"" + insurerCode + "\",";
  85. return json.replaceFirst(oldChar, newChar);
  86. }
  87. return null;
  88. }
  89. /**
  90. * 加密并签名
  91. * <p>
  92. * 对于<b>银保信</b>,publicKey是指合作方的公钥,privateKey是指银保信的私钥<br>
  93. * 对于<b>合作方</b>,publicKey是指银保信的公钥,privateKey是指合作方的私钥<br>
  94. *
  95. * @param publicKey 公钥
  96. * @param requestContent 报文原文
  97. * @param isCheckSign 是否签名
  98. * @param isEncrypt 是否加密
  99. * @return 加密加签后的返回报文
  100. * @throws Exception
  101. */
  102. public static Map<String, String> encryptAndSign(String privateKey, String publicKey, String requestContent, boolean isCheckSign,
  103. boolean isEncrypt) throws Exception {
  104. JSONObject requestJSONObject = JSONObject.parseObject(requestContent);
  105. String bizContent = requestJSONObject.getString("bizContent");
  106. Map<String, String> map = new HashMap<String, String>();
  107. if (isEncrypt) {
  108. //加密
  109. String encryptBizContent = encryptByPublicKey(bizContent, publicKey);//对业务数据进行加密
  110. requestJSONObject.put("bizContent", encryptBizContent);//将加密后的数据替换原有的明文
  111. map.put("content", requestJSONObject.toJSONString());
  112. if (isCheckSign) {
  113. //加签
  114. String signContent = getSignContent(requestJSONObject);// 所有key排序后放入LingkedMap后map.toString()
  115. String sign = sign(signContent, privateKey);
  116. map.put("signature", sign);
  117. }
  118. } else if (isCheckSign) {// 只加签、不加密
  119. String signContent = getSignContent(requestJSONObject);// 所有key排序后放入LingkedMap后map.toString()
  120. String sign = sign(signContent, privateKey);
  121. map.put("signature", sign);
  122. }
  123. return map;
  124. }
  125. /**
  126. * 封装待验签的内容
  127. *
  128. * @param sortedParam
  129. * @return
  130. */
  131. public static String getSignContent(Map<String, Object> sortedParam) {
  132. LinkedHashMap map = new LinkedHashMap();
  133. List<String> keys = new ArrayList<String>(sortedParam.keySet());
  134. Collections.sort(keys);
  135. for (int i = 0; i < keys.size(); i++) {
  136. String key = keys.get(i);
  137. String value = sortedParam.get(key).toString();
  138. map.put(key, value);
  139. }
  140. return map.toString();
  141. }
  142. /**
  143. * 验签
  144. *
  145. * @param request
  146. * @param sign
  147. * @param
  148. * @return
  149. */
  150. public static boolean verify(String request, String sign, String publicKey) {
  151. try {
  152. return SignatureUtils.verify(request.getBytes(), publicKey, sign);
  153. } catch (Exception e) {
  154. log.error("验签异常,inputParams: {} and publicKey: {} and sign: {} and errorMessage: {}", request, publicKey, sign,
  155. e.getMessage(), e);
  156. throw new RuntimeException(e);
  157. }
  158. }
  159. /**
  160. * <p>
  161. * 校验数字签名
  162. * </p>
  163. *
  164. * @param data 已加密数据
  165. * @param publicKey 公钥(BASE64编码)
  166. * @param sign 数字签名
  167. * @return
  168. * @throws Exception
  169. */
  170. public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
  171. byte[] keyBytes = Base64Utils.decode(publicKey.getBytes());
  172. X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
  173. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  174. PublicKey publicK = keyFactory.generatePublic(keySpec);
  175. Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
  176. signature.initVerify(publicK);
  177. signature.update(data);
  178. return signature.verify(Base64Utils.decode(sign.getBytes()));
  179. }
  180. /**
  181. * 私钥对数据进行解密
  182. *
  183. * @param bizContent
  184. * @param privateKey
  185. * @return
  186. */
  187. public static String decryptByPrivateKey(String bizContent, String privateKey) {
  188. try {
  189. return new String(SignatureUtils.decryptByPrivateKey(Base64Utils.decode(bizContent.getBytes()), privateKey));
  190. } catch (Exception e) {
  191. log.error("私钥解密异常,inputParams: {} and privateKey: {} and errorMessage: {}", bizContent, privateKey, e.getMessage(), e);
  192. throw new RuntimeException(e);
  193. }
  194. }
  195. /**
  196. * <P>
  197. * 私钥解密
  198. * </p>
  199. *
  200. * @param encryptedData 已加密数据
  201. * @param privateKey 私钥(BASE64编码)
  202. * @return
  203. * @throws Exception
  204. */
  205. public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception {
  206. byte[] keyBytes = Base64Utils.decode(privateKey.getBytes());
  207. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  208. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  209. Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
  210. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  211. cipher.init(Cipher.DECRYPT_MODE, privateK);
  212. int inputLen = encryptedData.length;
  213. ByteArrayOutputStream out = new ByteArrayOutputStream();
  214. int offSet = 0;
  215. byte[] cache;
  216. int i = 0;
  217. // 对数据分段解密
  218. while (inputLen - offSet > 0) {
  219. if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
  220. cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
  221. } else {
  222. cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
  223. }
  224. out.write(cache, 0, cache.length);
  225. i++;
  226. offSet = i * MAX_DECRYPT_BLOCK;
  227. }
  228. byte[] decryptedData = out.toByteArray();
  229. out.close();
  230. return decryptedData;
  231. }
  232. /**
  233. * 公钥加密
  234. *
  235. * @param request
  236. * @param publicKey
  237. * @return
  238. */
  239. public static String encryptByPublicKey(String request, String publicKey) throws Exception {
  240. return new String(Base64Utils.encode(SignatureUtils.encryptByPublicKey(request.getBytes(), publicKey)));
  241. }
  242. /**
  243. * <p>
  244. * 公钥加密
  245. * </p>
  246. *
  247. * @param data 源数据
  248. * @param publicKey 公钥(BASE64编码)
  249. * @return
  250. * @throws Exception
  251. */
  252. public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
  253. byte[] keyBytes = Base64Utils.decode(publicKey.getBytes());
  254. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  255. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  256. Key publicK = keyFactory.generatePublic(x509KeySpec);
  257. // 对数据加密
  258. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  259. cipher.init(Cipher.ENCRYPT_MODE, publicK);
  260. int inputLen = data.length;
  261. ByteArrayOutputStream out = new ByteArrayOutputStream();
  262. int offSet = 0;
  263. byte[] cache;
  264. int i = 0;
  265. // 对数据分段加密
  266. while (inputLen - offSet > 0) {
  267. if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
  268. cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
  269. } else {
  270. cache = cipher.doFinal(data, offSet, inputLen - offSet);
  271. }
  272. out.write(cache, 0, cache.length);
  273. i++;
  274. offSet = i * MAX_ENCRYPT_BLOCK;
  275. }
  276. byte[] encryptedData = out.toByteArray();
  277. out.close();
  278. return encryptedData;
  279. }
  280. /**
  281. * 加签
  282. *
  283. * @param
  284. * @param privateKey
  285. * @return
  286. */
  287. public static String sign(String request, String privateKey) {
  288. try {
  289. return SignatureUtils.sign(request.getBytes(), privateKey);
  290. } catch (Exception e) {
  291. log.error("加签异常,inputParams: {} and privateKey: {} and errorMessage: {}", request, privateKey, e.getMessage(), e);
  292. throw new RuntimeException(e);
  293. }
  294. }
  295. /**
  296. * <p>
  297. * 用私钥对信息生成数字签名
  298. * </p>
  299. *
  300. * @param data 已加密数据
  301. * @param privateKey 私钥(BASE64编码)
  302. * @return
  303. * @throws Exception
  304. */
  305. public static String sign(byte[] data, String privateKey) throws Exception {
  306. byte[] keyBytes = Base64Utils.decode(privateKey.getBytes());
  307. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  308. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  309. PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
  310. Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
  311. signature.initSign(privateK);
  312. signature.update(data);
  313. return new String(Base64Utils.encode(signature.sign()));
  314. }
  315. public static <T> T decryptMessage(String s, Class<T> c, String message, String sessionKey) {
  316. InsuranceLog.infoLog(InsuranceEnum.ZMBX.getPinyin(), "\n\t---------> 解密前的参数:{}", s);
  317. // 解密
  318. String text = decryptByPrivateKey(s.replace("\n", ""), sessionKey);
  319. InsuranceLog.infoLog(InsuranceEnum.ZMBX.getPinyin(), "\n\t---------> {}:{}", message, text);
  320. return JSON.parseObject(text, c);
  321. }
  322. }