在现代网络应用中,安全性是首要关注的问题之一,尤其是在数据传输过程中。为了保证数据的机密性和完整性,我们可以使用 RSA 和 AES 相结合的加密方案,借助 SpringBoot 实现传输加密并在服务器端自动解密。
本文将通过详细步骤,介绍如何使用 SpringBoot 实现这一功能。
什么是 RSA 和 AES?
- RSA (Rivest-Shamir-Adleman):一种非对称加密算法,使用公钥加密和私钥解密,适合加密小数据或传递加密密钥。
- AES (Advanced Encryption Standard):一种对称加密算法,密钥相同且高效,适合加密大数据。
将两者结合使用的优势:
- 使用 RSA 加密 AES 的密钥,确保密钥传输安全。
- 使用 AES 加密实际数据,保证加密速度快。
实现思路
- 客户端:生成 AES 密钥并使用 RSA 公钥加密,将加密后的 AES 密钥与加密数据一起发送到服务器。
- 服务器:使用 RSA 私钥解密 AES 密钥,再用解密后的 AES 密钥解密实际数据。
项目依赖
在 pom.xml
文件中引入以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
RSA 和 AES 工具类
RSA 工具类
import java.security.*;
import java.util.Base64;
import javax.crypto.Cipher;
public class RSAUtil {
private static final String RSA = "RSA";
// 生成密钥对
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);
keyPairGenerator.initialize(2048);
return keyPairGenerator.generateKeyPair();
}
// 公钥加密
public static String encrypt(String data, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes()));
}
// 私钥解密
public static String decrypt(String data, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(cipher.doFinal(Base64.getDecoder().decode(data)));
}
}
AES 工具类
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class AESUtil {
private static final String AES = "AES";
// 生成 AES 密钥
public static String generateKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
keyGenerator.init(128);
SecretKey secretKey = keyGenerator.generateKey();
return Base64.getEncoder().encodeToString(secretKey.getEncoded());
}
// 加密
public static String encrypt(String data, String key) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.getDecoder().decode(key), AES);
Cipher cipher = Cipher.getInstance(AES);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes()));
}
// 解密
public static String decrypt(String data, String key) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.getDecoder().decode(key), AES);
Cipher cipher = Cipher.getInstance(AES);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
return new String(cipher.doFinal(Base64.getDecoder().decode(data)));
}
}
控制器实现
创建一个控制器,用于接收加密数据并解密:
import org.springframework.web.bind.annotation.*;
import java.security.KeyPair;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/crypto")
public class CryptoController {
private final KeyPair keyPair;
public CryptoController() throws Exception {
// 初始化 RSA 密钥对
this.keyPair = RSAUtil.generateKeyPair();
}
@GetMapping("/publicKey")
public String getPublicKey() {
// 返回 Base64 编码的公钥
return Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
}
@PostMapping("/decrypt")
public Map<String, String> decrypt(@RequestBody Map<String, String> payload) throws Exception {
String encryptedKey = payload.get("encryptedKey");
String encryptedData = payload.get("encryptedData");
// 解密 AES 密钥
String aesKey = RSAUtil.decrypt(encryptedKey, keyPair.getPrivate());
// 解密数据
String data = AESUtil.decrypt(encryptedData, aesKey);
Map<String, String> response = new HashMap<>();
response.put("data", data);
return response;
}
}
测试加密解密流程
编写简单的测试代码模拟客户端操作:
public class ClientSimulation {
public static void main(String[] args) throws Exception {
// 模拟获取公钥
KeyPair keyPair = RSAUtil.generateKeyPair();
String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
// 生成 AES 密钥
String aesKey = AESUtil.generateKey();
// 加密数据
String data = "Hello, SpringBoot + RSA + AES!";
String encryptedData = AESUtil.encrypt(data, aesKey);
// 加密 AES 密钥
String encryptedKey = RSAUtil.encrypt(aesKey, keyPair.getPublic());
// 模拟发送到服务器
System.out.println("Encrypted Key: " + encryptedKey);
System.out.println("Encrypted Data: " + encryptedData);
// 模拟服务器解密
String decryptedKey = RSAUtil.decrypt(encryptedKey, keyPair.getPrivate());
String decryptedData = AESUtil.decrypt(encryptedData, decryptedKey);
System.out.println("Decrypted Data: " + decryptedData);
}
}
结论
通过以上方法,我们使用 SpringBoot 和 RSA、AES 实现了数据的加密传输和服务器端解密。这种方案既保证了密钥的安全传输,又能有效处理大数据的加密需求。
在实际生产中,可以通过更优化的密钥管理方案和安全策略,进一步提升系统的安全性和性能。