package com.pj.api.pushfee.tools; import cn.hutool.core.codec.Base64; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.asymmetric.RSA; import cn.hutool.crypto.digest.DigestUtil; import cn.hutool.crypto.symmetric.AES; import cn.hutool.crypto.symmetric.SymmetricAlgorithm; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.pj.api.pushfee.tools.message.CuMessage; import com.pj.api.pushfee.tools.message.Header; import com.pj.api.pushfee.tools.message.Inter; import com.pj.api.pushfee.tools.message.MessageInter; public class EncryptTools { private String sysId; private String remotePublicKey; private String localPrivateKey; private RSA rsaInstance; private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create(); /** * 构造加密工具 * @param sysId 系统Id,由统一计费系统分配 * @param remotePublicKey 对方的公钥 */ public EncryptTools(String sysId, String remotePublicKey) { this.sysId = sysId; this.remotePublicKey = remotePublicKey; rsaInstance = SecureUtil.rsa(null, this.remotePublicKey); } /** * 构造解密工具 * @param localPrivateKey 己方的私钥 */ public EncryptTools(String localPrivateKey) { this.localPrivateKey = localPrivateKey; rsaInstance = SecureUtil.rsa(this.localPrivateKey, null); } /** * 生成RSA密钥对 */ public static void generateKeyPairs(){ RSA rsa = new RSA(); // 获取公钥 String pubKey = rsa.getPublicKeyBase64(); System.out.println("公钥:" + pubKey); // 获取私钥 String priKey = rsa.getPrivateKeyBase64(); System.out.println("私钥:" + priKey); } /** * md5签名 * @param text * @return */ private String md5(String text){ return DigestUtil.md5Hex(text); } /** * RSA私钥解密 * @return */ private String decryptStrByPrivateKey(String encrypt){ try { return this.rsaInstance.decryptStr(encrypt, KeyType.PrivateKey); } catch (Exception e) { throw new RuntimeException("RSA私钥解密失败"); } } /** * RSA公钥加密 * @param text * @return */ private String encryptByPublicKey(String text){ try { return this.rsaInstance.encryptBase64(StrUtil.bytes(text,CharsetUtil.CHARSET_UTF_8), KeyType.PublicKey); } catch (Exception e) { throw new RuntimeException("RSA公钥加密失败"); } } /** * 生成随机秘钥 */ private String getRandomKey(){ return Base64.encode(SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded()); } private String encodeByAES(String content, String randomKey){ try { AES aes = SecureUtil.aes(Base64.decode(randomKey)); return aes.encryptBase64(content); } catch (Exception e) { throw new RuntimeException("AES加密报文失败"); } } private String decodeByAES(String sourceText, String randomKey){ try { AES aes = SecureUtil.aes(Base64.decode(randomKey)); return aes.decryptStr(sourceText); } catch (Exception e) { throw new RuntimeException("AES解密报文失败"); } } private boolean verifySignature(CuMessage message){ String signature = message.getSignature(); return md5(gson.toJson(message.getHeader())).equals(signature); } /** * 加密报文 */ public String encryptMessage(MessageInter payLoad){ //生成随机秘钥 String randomKey = getRandomKey(); //加密报文payLoad String encrypted = encodeByAES(gson.toJson(payLoad), randomKey); //加密随机秘钥 String keyEncrypted = encryptByPublicKey(randomKey); Inter interAnnotation = payLoad.getClass().getAnnotation(Inter.class); String interId = interAnnotation.name(); Header header = new Header(this.sysId, encrypted, keyEncrypted, interId); //签名:md5提取摘要 String signature = md5(gson.toJson(header)); CuMessage cuMessage = new CuMessage(header, signature); String msg = gson.toJson(cuMessage); System.out.println("密文:" + msg); return msg; } /** * 解密报文 * @return */ public MessageInter decryptMessage(String text){ CuMessage cuMessage = gson.fromJson(text, CuMessage.class); return decryptMessage(cuMessage); } public MessageInter decryptMessage(CuMessage message){ //验签 if (!verifySignature(message)) { throw new RuntimeException("验签失败"); } //用公钥解密得到randomKey String key = decryptStrByPrivateKey(message.getHeader().getKeyEncrypted()); //用randomKey解密报文 String originText = decodeByAES(message.getHeader().getEncrypted(), key); MessageInter inter = gson.fromJson(originText, InterEnum.findClass(message.getHeader().getInterId())); System.out.println("解密:" + originText); return inter; } }