RSA 是非對稱加密基石,廣泛用於數據傳輸加密、數位簽名、HTTPS/TLS。本文提供開箱即用的完整示例,涵蓋金鑰對生成、持久化、加密、解密全流程。
public class RSADemo {
// 金鑰文件常量
private static final String PUB_KEY_FILE = "pubkey.dat";
private static final String PRI_KEY_FILE = "privatekey.dat";
private static final String ENCRYPT_FILE = "encrypt.dat";
private static final int KEY_SIZE = 1024; // 建議生產環境用 2048+
}
public static void generateKey() throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(KEY_SIZE);
KeyPair kp = kpg.genKeyPair();
// 序列化保存公鑰
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(PUB_KEY_FILE))) {
out.writeObject(kp.getPublic());
}
// 序列化保存私鑰
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(PRI_KEY_FILE))) {
out.writeObject(kp.getPrivate());
}
}
關鍵點:使用 ObjectOutputStream 序列化 PublicKey/PrivateKey,實現跨會話復用。
public static void encrypt() throws Exception {
String plainText = "Hello World!";
// 讀取公鑰
RSAPublicKey pubKey;
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(PUB_KEY_FILE))) {
pubKey = (RSAPublicKey) in.readObject();
}
// 核心加密:c = m^e mod n
BigInteger m = new BigInteger(plainText.getBytes("UTF-8"));
BigInteger c = m.modPow(pubKey.getPublicExponent(), pubKey.getModulus());
// 保存密文
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(ENCRYPT_FILE)))) {
writer.write(c.toString());
}
}
public static void decrypt() throws Exception {
// 讀取密文
String cText;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(ENCRYPT_FILE)))) {
cText = reader.readLine();
}
BigInteger c = new BigInteger(cText);
// 讀取私鑰
RSAPrivateKey priKey;
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(PRI_KEY_FILE))) {
priKey = (RSAPrivateKey) in.readObject();
}
// 核心解密:m = c^d mod n
BigInteger m = c.modPow(priKey.getPrivateExponent(), priKey.getModulus());
byte[] plainBytes = m.toByteArray();
System.out.print("解密結果: ");
for (byte b : plainBytes) System.out.print((char) b);
}
public static void main(String[] args) {
try {
generateKey();
encrypt();
decrypt();
} catch (Exception e) {
e.printStackTrace();
}
}
| 項目 | 建議 |
|---|---|
| 金鑰長度 | 最小 2048 位,推薦 3072/4096 |
| 填充模式 | 必須使用 OAEP:Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding") |
| 大數據加密 | RSA 僅加密 AES 金鑰,數據用 AES-GCM |
| 私鑰存儲 | PKCS#8 格式 + 加密存儲,或使用 Java KeyStore (JKS/PKCS12) |
| 異常處理 | 捕獲具體異常,避免吞噬 Exception |
// 使用 Cipher API 替代手動 BigInteger 運算
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
理解 RSA 數學原理固然重要,但生產代碼請優先使用成熟的 Cipher API 並遵循密碼學最佳實踐。