|
|
@@ -0,0 +1,131 @@
|
|
|
+package com.ygtx.common.utils;
|
|
|
+
|
|
|
+import cn.hutool.crypto.asymmetric.KeyType;
|
|
|
+import cn.hutool.crypto.asymmetric.RSA;
|
|
|
+import cn.hutool.crypto.symmetric.AES;
|
|
|
+import cn.hutool.core.codec.Base64;
|
|
|
+import cn.hutool.core.util.CharsetUtil;
|
|
|
+import cn.hutool.crypto.SecureUtil;
|
|
|
+
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.security.KeyPair;
|
|
|
+import java.security.PrivateKey;
|
|
|
+import java.security.PublicKey;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 加密工具类(RSA+AES)
|
|
|
+ * 严格适配你提供的 Hutool 5.8.0 M3 版本的 RSA 类反编译代码
|
|
|
+ */
|
|
|
+public class CryptoUtils {
|
|
|
+ // -------------------------- RSA 配置 --------------------------
|
|
|
+ // 全局单例的 RSA 工具对象
|
|
|
+ private static final RSA RSA_UTIL;
|
|
|
+
|
|
|
+ // 静态代码块初始化 RSA 密钥对(核心:基于反编译的 RSA 类 API)
|
|
|
+ static {
|
|
|
+ try {
|
|
|
+ // 1. 用 SecureUtil 生成 2048 位 RSA 密钥对(Hutool 通用工具类,兼容该版本)
|
|
|
+ KeyPair keyPair = SecureUtil.generateKeyPair("RSA", 2048);
|
|
|
+ // 2. 提取私钥和公钥
|
|
|
+ PrivateKey privateKey = keyPair.getPrivate();
|
|
|
+ PublicKey publicKey = keyPair.getPublic();
|
|
|
+ // 3. 用「私钥+公钥」初始化 RSA 对象(反编译的 RSA 类支持此构造方法)
|
|
|
+ RSA_UTIL = new RSA(privateKey, publicKey);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("RSA 密钥对初始化失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取 RSA 公钥(Base64 编码,供前端使用)
|
|
|
+ */
|
|
|
+ public static String getRsaPublicKey() {
|
|
|
+ try {
|
|
|
+ PublicKey publicKey = RSA_UTIL.getPublicKey();
|
|
|
+ // 将公钥字节数组编码为 Base64 字符串(便于网络传输)
|
|
|
+ return Base64.encode(publicKey.getEncoded());
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("获取 RSA 公钥失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * RSA 私钥解密(解密前端传来的 AES 密钥)
|
|
|
+ * @param encryptStr Base64 编码的加密字符串
|
|
|
+ * @return 解密后的明文
|
|
|
+ * 适配点:使用 KeyType.PRIVATE 枚举(反编译的 RSA 类的 decrypt 方法仅支持此参数)
|
|
|
+ */
|
|
|
+ public static String rsaDecrypt(String encryptStr) {
|
|
|
+ try {
|
|
|
+ // 1. 解码 Base64 加密字符串
|
|
|
+ byte[] encryptBytes = Base64.decode(encryptStr);
|
|
|
+ // 2. 私钥解密:严格使用 KeyType.PRIVATE 枚举(反编译的 RSA 类的方法签名要求)
|
|
|
+ byte[] decryptBytes = RSA_UTIL.decrypt(encryptBytes, KeyType.PrivateKey);
|
|
|
+ // 3. 转换为 UTF-8 明文
|
|
|
+ return new String(decryptBytes, StandardCharsets.UTF_8);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("RSA 解密失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // -------------------------- AES 配置 --------------------------
|
|
|
+ /**
|
|
|
+ * AES 加密(CBC 模式,PKCS7 填充,带 IV 向量)
|
|
|
+ * @param content 明文内容
|
|
|
+ * @param aesKey AES 密钥(Base64 编码,16 位/32 位)
|
|
|
+ * @return Base64 编码的密文
|
|
|
+ */
|
|
|
+ public static String aesEncrypt(String content, String aesKey) {
|
|
|
+ try {
|
|
|
+ // 解码 Base64 格式的 AES 密钥
|
|
|
+ byte[] keyBytes = Base64.decode(aesKey);
|
|
|
+ // 初始化 AES(CBC 模式,PKCS7 填充,密钥作为 IV 向量)
|
|
|
+ AES aes = new AES("CBC", "PKCS7Padding", keyBytes, keyBytes);
|
|
|
+ // 加密并编码为 Base64 字符串
|
|
|
+ return Base64.encode(aes.encrypt(content));
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("AES 加密失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * AES 解密(解密前端传来的业务数据)
|
|
|
+ * @param encryptStr Base64 编码的密文
|
|
|
+ * @param aesKey AES 密钥(Base64 编码)
|
|
|
+ * @return 解密后的明文
|
|
|
+ */
|
|
|
+ public static String aesDecrypt(String encryptStr, String aesKey) {
|
|
|
+ try {
|
|
|
+ // 解码 Base64 格式的 AES 密钥和密文
|
|
|
+ byte[] keyBytes = Base64.decode(aesKey);
|
|
|
+ byte[] encryptBytes = Base64.decode(encryptStr);
|
|
|
+ // 初始化 AES(与加密端一致的模式和填充方式)
|
|
|
+ AES aes = new AES("CBC", "PKCS7Padding", keyBytes, keyBytes);
|
|
|
+ // 解密并转换为 UTF-8 明文
|
|
|
+ byte[] decryptBytes = aes.decrypt(encryptBytes);
|
|
|
+ return new String(decryptBytes, StandardCharsets.UTF_8);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("AES 解密失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void main(String[] args) {
|
|
|
+ // 1. 获取公钥
|
|
|
+ String publicKey = CryptoUtils.getRsaPublicKey();
|
|
|
+ System.out.println("RSA 公钥:" + publicKey);
|
|
|
+
|
|
|
+ // 2. 模拟前端用公钥加密 AES 密钥
|
|
|
+ RSA rsa = new RSA(null, publicKey); // 仅传入公钥,用于加密
|
|
|
+ String originalAesKey = "testAesKey123456";
|
|
|
+ // 用公钥加密(使用 KeyType.PUBLIC 枚举,匹配 RSA 类方法签名)
|
|
|
+ String encryptAesKey = rsa.encryptBase64(originalAesKey, KeyType.PublicKey);
|
|
|
+ System.out.println("加密后的 AES 密钥:" + encryptAesKey);
|
|
|
+
|
|
|
+ // 3. 用工具类解密
|
|
|
+ String decryptAesKey = CryptoUtils.rsaDecrypt(encryptAesKey);
|
|
|
+ System.out.println("解密后的 AES 密钥:" + decryptAesKey);
|
|
|
+
|
|
|
+ // 验证解密结果
|
|
|
+ assert originalAesKey.equals(decryptAesKey);
|
|
|
+ }
|
|
|
+}
|