1. 简介
RSA,全称 Rivest–Shamir–Adleman,是一种非对称加密算法。它与 DES 或 AES 这类对称加密算法不同的是,RSA 使用一对密钥:
- 公钥(Public Key):可以公开分享,用于加密数据
- 私钥(Private Key):必须严格保密,用于解密数据
本文将带你了解如何在 Java 中生成、存储并使用 RSA 密钥对进行加解密操作。
2. 生成 RSA 密钥对
在进行加密操作前,我们首先需要生成一对 RSA 密钥。Java 提供了 KeyPairGenerator
类来帮助我们快速生成密钥对:
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048);
KeyPair pair = generator.generateKeyPair();
✅ 这里我们初始化了密钥长度为 2048 位,这是目前比较安全且通用的长度。
接着,我们可以分别提取出私钥和公钥:
PrivateKey privateKey = pair.getPrivate();
PublicKey publicKey = pair.getPublic();
公钥用于加密,私钥用于解密。
3. 将密钥存储到文件中
密钥对如果只保存在内存中显然不靠谱,尤其在生产环境中,密钥通常需要长期保存。这时候,将密钥写入文件是更稳妥的做法。
保存密钥
我们可以使用 getEncoded()
方法获取密钥的字节内容,并写入文件:
try (FileOutputStream fos = new FileOutputStream("public.key")) {
fos.write(publicKey.getEncoded());
}
读取密钥
读取时,先将文件内容读为字节数组,再通过 KeyFactory
恢复成密钥对象:
File publicKeyFile = new File("public.key");
byte[] publicKeyBytes = Files.readAllBytes(publicKeyFile.toPath());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
⚠️ 注意:这里使用的是 X509EncodedKeySpec
,它是 getEncoded()
方法默认的编码格式。
私钥的读写流程与公钥一致,只需将 X509EncodedKeySpec
替换为 PKCS8EncodedKeySpec
。
🔒 安全提醒:私钥文件一定要妥善保管,权限控制要严格,避免泄露!
4. 字符串加解密操作
加密
假设我们有如下待加密的字符串:
String secretMessage = "Baeldung secret message";
我们使用 Cipher
类进行加密操作:
Cipher encryptCipher = Cipher.getInstance("RSA");
encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] secretMessageBytes = secretMessage.getBytes(StandardCharsets.UTF_8);
byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessageBytes);
为了便于存储或传输(比如通过 REST API),通常会对加密后的字节数组进行 Base64 编码:
String encodedMessage = Base64.getEncoder().encodeToString(encryptedMessageBytes);
解密
解密时,我们需要用私钥初始化 Cipher
并调用 doFinal
方法:
Cipher decryptCipher = Cipher.getInstance("RSA");
decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedMessageBytes = decryptCipher.doFinal(encryptedMessageBytes);
String decryptedMessage = new String(decryptedMessageBytes, StandardCharsets.UTF_8);
最后验证一下是否还原成功:
assertEquals(secretMessage, decryptedMessage);
5. 文件加解密操作
RSA 也可以用于对整个文件进行加密。
加密文件
比如我们创建一个临时文件:
Path tempFile = Files.createTempFile("temp", "txt");
Files.writeString(tempFile, "some secret message");
读取文件内容并加密:
byte[] fileBytes = Files.readAllBytes(tempFile);
Cipher encryptCipher = Cipher.getInstance("RSA");
encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedFileBytes = encryptCipher.doFinal(fileBytes);
将加密后的内容写回文件:
try (FileOutputStream stream = new FileOutputStream(tempFile.toFile())) {
stream.write(encryptedFileBytes);
}
解密文件
解密流程类似,只是 Cipher
初始化为解密模式并使用私钥:
byte[] encryptedFileBytes = Files.readAllBytes(tempFile);
Cipher decryptCipher = Cipher.getInstance("RSA");
decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedFileBytes = decryptCipher.doFinal(encryptedFileBytes);
try (FileOutputStream stream = new FileOutputStream(tempFile.toFile())) {
stream.write(decryptedFileBytes);
}
最后验证文件内容是否还原成功:
String fileContent = Files.readString(tempFile);
Assertions.assertEquals("some secret message", fileContent);
6. 总结
本文我们学习了如何在 Java 中:
- 生成 RSA 密钥对
- 将密钥保存到文件中
- 对字符串和文件进行加解密操作
RSA 是非对称加密的经典算法,虽然性能不如 AES,但在密钥交换、数字签名等场景下具有不可替代的优势。
🔐 小贴士:RSA 适合加密小量数据,大量数据建议使用混合加密(RSA + AES)。