在Java中结合使用AES(对称加密)和RSA(非对称加密)是一种常见的安全实践,既能利用AES的高效性处理大数据,又能通过RSA解决密钥分发问题。以下是混合加密的典型实现步骤和示例代码:
混合加密的核心思路
- 生成AES密钥:用于加密实际数据(速度快,适合大数据)。
- 用RSA加密AES密钥:将AES密钥通过RSA公钥加密后传输。
- 用AES加密数据:用AES密钥加密敏感数据。
- 解密时反向操作:先用RSA私钥解密得到AES密钥,再用AES解密数据。
Java实现步骤
1. 生成RSA密钥对
java
import java.security.*;
public class KeyPairGeneratorExample {
public static KeyPair generateRSAKeyPair(int keySize) throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(keySize); // 推荐2048位
return keyPairGen.generateKeyPair();
}
}
2. 生成AES密钥
java
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
public class AESKeyGenerator {
public static SecretKey generateAESKey(int keySize) throws NoSuchAlgorithmException {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(keySize); // 常用128/192/256位
return keyGen.generateKey();
}
}
3. RSA加密AES密钥
java
import javax.crypto.Cipher;
public class RSAEncryptor {
public static byte[] encryptAESKeyWithRSA(PublicKey publicKey, SecretKey aesKey)
throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(aesKey.getEncoded());
}
}
4. AES加密数据
java
public class AESEncryptor {
public static byte[] encryptDataWithAES(SecretKey aesKey, byte[] data)
throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
return cipher.doFinal(data);
}
}
5. 完整加密流程示例
java
public class HybridEncryption {
public static void main(String[] args) throws Exception {
// 1. 生成RSA密钥对
KeyPair rsaKeyPair = KeyPairGeneratorExample.generateRSAKeyPair(2048);
PublicKey publicKey = rsaKeyPair.getPublic();
PrivateKey privateKey = rsaKeyPair.getPrivate();
// 2. 生成AES密钥
SecretKey aesKey = AESKeyGenerator.generateAESKey(256);
// 3. 用RSA加密AES密钥
byte[] encryptedAESKey = RSAEncryptor.encryptAESKeyWithRSA(publicKey, aesKey);
// 4. 用AES加密数据
String originalData = "Sensitive information";
byte[] encryptedData = AESEncryptor.encryptDataWithAES(aesKey, originalData.getBytes());
// 5. 输出结果(实际场景需编码为Base64等格式)
System.out.println("Encrypted AES Key: " + bytesToHex(encryptedAESKey));
System.out.println("Encrypted Data: " + bytesToHex(encryptedData));
}
// 辅助方法:字节数组转十六进制字符串
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}
解密流程
- 用RSA私钥解密AES密钥:
java
public class RSADecryptor {
public static SecretKey decryptAESKeyWithRSA(PrivateKey privateKey, byte[] encryptedAESKey)
throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] aesKeyBytes = cipher.doFinal(encryptedAESKey);
return new SecretKeySpec(aesKeyBytes, "AES");
}
}
- 用AES解密数据:
java
public class AESDecryptor {
public static byte[] decryptDataWithAES(SecretKey aesKey, byte[] encryptedData)
throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, aesKey);
return cipher.doFinal(encryptedData);
}
}
关键注意事项
- 密钥长度匹配:
- RSA密钥长度需足够长(如2048位)以加密AES-256密钥。
- AES密钥长度需与算法匹配(128/192/256位)。
- 编码处理:
- 加密后的字节数组需通过Base64或Hex编码转换为字符串传输。
- 初始化向量(IV):
- 在CBC等模式中需随机生成IV,并与密文一起存储。
- 异常处理:
- 实际代码中需处理
NoSuchAlgorithmException
、InvalidKeyException
等异常。
混合加密的优势
- 安全性:通过RSA保护AES密钥,避免密钥直接传输。
- 效率:AES加密大数据速度远快于RSA。
- 灵活性:可动态生成AES密钥,每次会话使用不同密钥。
这种模式广泛应用于HTTPS、加密存储等场景,是平衡安全性和性能的经典方案。