AES256+RSA网络数据加密
为什么这么搭配?
- AES:加密速度快,适合大数据量业务报文
- RSA/ECC:只用来传 AES 密钥,不适合加密大文本
说明:Java 网络传输通用加解密工具类(AES+RSA 混合加密)
方案说明
AES:AES-128-CBC 加密业务报文(速度快、适合网络传输)
RSA:RSA-2048 加密 AES 随机密钥
流程:
- 客户端生成随机 AES 密钥 + 偏移量 IV
- AES 加密业务明文
- RSA 用服务端公钥加密 AES 密钥 + IV
- 传给后端:RSA 密文 + AES 业务密文
- 后端用私钥RSA 解密出 AES 密钥和 IV,再 AES 解业务数据
依赖(无需额外引入,JDK 原生)
JDK8+ 自带,不用导任何第三方包,直接能用。
java
package com.pansoft.lcdp.util;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
/**
* 网络传输 AES+RSA 混合加解密工具
* 适用:前后端接口、微服务敏感数据传输
*/
public class NetEncryptUtil {
// ==================== AES 常量 ====================
private static final String AES_ALGORITHM = "AES";
private static final String AES_CIPHER_MODE = "AES/CBC/PKCS5Padding";
// AES 128位 密钥长度
private static final int AES_KEY_SIZE = 16;
// CBC 模式偏移量 IV 长度
private static final int AES_IV_SIZE = 16;
// ==================== RSA 常量 ====================
private static final String RSA_ALGORITHM = "RSA";
private static final int RSA_KEY_SIZE = 2048;
// ------------------------------ 生成RSA公私钥对 ------------------------------
/**
* 生成RSA 公钥、私钥 Base64 字符串
*/
public static KeyPair generateRsaKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM);
keyPairGenerator.initialize(RSA_KEY_SIZE);
return keyPairGenerator.generateKeyPair();
}
/**
* 公钥转Base64
*/
public static String getPublicKeyBase64(PublicKey publicKey) {
return Base64.getEncoder().encodeToString(publicKey.getEncoded());
}
/**
* 私钥转Base64
*/
public static String getPrivateKeyBase64(PrivateKey privateKey) {
return Base64.getEncoder().encodeToString(privateKey.getEncoded());
}
// ------------------------------ RSA 加解密 ------------------------------
/**
* RSA 公钥加密
*/
public static String rsaEncrypt(String data, String publicKeyBase64) throws Exception {
byte[] keyBytes = Base64.getDecoder().decode(publicKeyBase64);
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
PublicKey publicKey = keyFactory.generatePublic(spec);
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encryptBytes);
}
/**
* RSA 私钥解密
*/
public static String rsaDecrypt(String encryptData, String privateKeyBase64) throws Exception {
byte[] keyBytes = Base64.getDecoder().decode(privateKeyBase64);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
PrivateKey privateKey = keyFactory.generatePrivate(spec);
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptBytes = cipher.doFinal(Base64.getDecoder().decode(encryptData));
return new String(decryptBytes, StandardCharsets.UTF_8);
}
// ------------------------------ AES 随机生成密钥和IV ------------------------------
/**
* 生成随机16位AES密钥
*/
public static String generateAesKey() {
return getRandomStr(AES_KEY_SIZE);
}
/**
* 生成随机16位IV
*/
public static String generateAesIv() {
return getRandomStr(AES_IV_SIZE);
}
/**
* 生成指定长度随机字符串
*/
private static String getRandomStr(int length) {
String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
StringBuilder sb = new StringBuilder();
SecureRandom random = new SecureRandom();
for (int i = 0; i < length; i++) {
int idx = random.nextInt(chars.length());
sb.append(chars.charAt(idx));
}
return sb.toString();
}
// ------------------------------ AES 加解密 ------------------------------
/**
* AES CBC 加密
*/
public static String aesEncrypt(String content, String aesKey, String iv) throws Exception {
SecretKeySpec keySpec = new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), AES_ALGORITHM);
IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
Cipher cipher = Cipher.getInstance(AES_CIPHER_MODE);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] encryptBytes = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encryptBytes);
}
/**
* AES CBC 解密
*/
public static String aesDecrypt(String encryptContent, String aesKey, String iv) throws Exception {
SecretKeySpec keySpec = new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), AES_ALGORITHM);
IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
Cipher cipher = Cipher.getInstance(AES_CIPHER_MODE);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] decryptBytes = cipher.doFinal(Base64.getDecoder().decode(encryptContent));
return new String(decryptBytes, StandardCharsets.UTF_8);
}
// ------------------------------ 测试入口 ------------------------------
public static void main(String[] args) throws Exception {
// 1. 生成RSA公私钥对(服务端保存私钥,客户端下发公钥)
KeyPair keyPair = generateRsaKeyPair();
String pubKey = getPublicKeyBase64(keyPair.getPublic());
String priKey = getPrivateKeyBase64(keyPair.getPrivate());
System.out.println("RSA公钥:" + pubKey);
System.out.println("RSA私钥:" + priKey);
// 2. 客户端:生成随机AES密钥、IV
String aesKey = generateAesKey();
String aesIv = generateAesIv();
String secret = aesKey + "|" + aesIv;
// 3. 业务明文
String plainText = "userId=10086&phone=13800138000&idCard=310101199001011234";
// 4. AES加密业务数据
String aesEncryptStr = aesEncrypt(plainText, aesKey, aesIv);
// 5. RSA加密AES密钥+IV
String rsaEncryptStr = rsaEncrypt(secret, pubKey);
System.out.println("\nAES业务密文:" + aesEncryptStr);
System.out.println("RSA密钥密文:" + rsaEncryptStr);
// ========== 服务端解密流程 ==========
// 1. RSA私钥解密 拿到AESKey和IV
String decryptSecret = rsaDecrypt(rsaEncryptStr, priKey);
String[] split = decryptSecret.split("\\|");
String realAesKey = split[0];
String realAesIv = split[1];
// 2. AES解密业务数据
String realPlain = aesDecrypt(aesEncryptStr, realAesKey, realAesIv);
System.out.println("\n解密原文:" + realPlain);
}
}