RSA加密Java怎么写?

wen python案例 3

RSA加密Java实现完全指南:从原理到代码实战

目录导读

  • RSA加密核心原理(必懂基础)

    RSA加密Java怎么写?

  • Java中RSA加密的两种常见场景

  • 完整代码实现:密钥生成、加密、解密

  • 常见问题与避坑指南(含问答)

  • 性能优化与安全建议


RSA加密核心原理(必懂基础)

RSA是一种非对称加密算法,由Ron Rivest、Adi Shamir和Leonard Adleman在1977年提出,其核心思想是:加密和解密使用不同的密钥——公钥用于加密,私钥用于解密,安全性基于大整数分解的数学难题。

关键参数:

  • 密钥长度:通常使用2048位(长度越长越安全,但性能越低)。
  • 填充方式:PKCS#1 v1.5(兼容性好)或OAEP(更安全,推荐)。

适用场景:

  • 数字签名(私钥签名,公钥验签)
  • 加密小数据(如对称密钥、密码等,不适合加密大文件)

问题1:RSA能加密任意大小的数据吗?
答:不能,RSA加密块大小受密钥长度限制,例如2048位密钥最多加密245字节(PKCS#1 v1.5)或190字节(OAEP),大文件建议先使用AES对称加密,再用RSA加密AES密钥。


Java中RSA加密的两种常见场景

在Java中实现RSA,主要分为标准JCE(Java Cryptography Extension)Bouncy Castle两种方式,JCE是JDK内置的,无需额外依赖;Bouncy Castle提供更多算法支持(如OAEP更灵活的哈希函数)。

对比维度 JCE(javax.crypto) Bouncy Castle
依赖 JDK自带 需引入bcprovjar包
填充方式 支持PKCS#1和OAEP 支持更多填充
密钥长度 无限制 无限制
推荐 常规项目使用 需要特殊算法时

优先使用JCE(除非必须用Bouncy Castle的特定功能)。


完整代码实现:密钥生成、加密、解密

以下代码演示了如何使用JCE生成2048位RSA密钥对,并用OAEP(SHA-256)加密/解密字符串。

1 生成密钥对并保存为Base64字符串

import javax.crypto.Cipher;
import java.security.*;
import java.util.Base64;
public class RSAUtil {
    // 生成密钥对
    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
        generator.initialize(2048); // 推荐2048位
        return generator.generateKeyPair();
    }
    // 密钥转Base64字符串
    public static String keyToBase64(Key key) {
        return Base64.getEncoder().encodeToString(key.getEncoded());
    }
    // 从Base64恢复密钥(示例:公钥)
    public static PublicKey base64ToPublicKey(String base64) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(base64);
        KeyFactory factory = KeyFactory.getInstance("RSA");
        return factory.generatePublic(new X509EncodedKeySpec(keyBytes));
    }
    // 私钥恢复同理,用PKCS8EncodedKeySpec
}

2 使用OAEP填充进行加密(推荐)

public static String encrypt(String plainText, PublicKey publicKey) throws Exception {
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
    return Base64.getEncoder().encodeToString(encryptedBytes);
}
public static String decrypt(String cipherText, PrivateKey privateKey) throws Exception {
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(cipherText));
    return new String(decryptedBytes, "UTF-8");
}

注意:OAEP填充默认使用SHA-1作为MGF1的哈希,显式指定SHA-256更安全,如果兼容性问题需用PKCS#1,则改为"RSA/ECB/PKCS1Padding"

3 完整测试示例

public static void main(String[] args) throws Exception {
    // 1. 生成密钥
    KeyPair keyPair = generateKeyPair();
    PublicKey pubKey = keyPair.getPublic();
    PrivateKey priKey = keyPair.getPrivate();
    // 2. 加密
    String original = "Hello, RSA! 这是一个测试。";
    String encrypted = encrypt(original, pubKey);
    System.out.println("加密后: " + encrypted);
    // 3. 解密
    String decrypted = decrypt(encrypted, priKey);
    System.out.println("解密后: " + decrypted);
}

输出示例:

加密后: Kd5m8y...(Base64字符串)
解密后: Hello, RSA! 这是一个测试。

常见问题与避坑指南(含问答)

问题2:RSA加密时出现IllegalBlockSizeException怎么办?
答:这表示明文数据超过最大加密长度,2048位密钥使用OAEP+SHA-256时最大加密190字节,解决方案:将数据分块加密,或改用混合加密(AES+RSA)。

问题3:公钥和私钥如何存储?
答:推荐使用Base64字符串保存到配置文件或数据库,生产环境中私钥必须加密存储(如使用Keystore或硬件安全模块)。

问题4:OAEP和PKCS#1 v1.5选哪个?
答:OAEP更安全,能抵抗选择密文攻击,PKCS#1 v1.5主要用于兼容旧系统,新系统首选OAEP。

问题5:为什么解密后中文乱码?
答:确保加密时使用UTF-8编码,解密时同样用UTF-8,示例中已正确处理。


性能优化与安全建议

  1. 避免频繁生成密钥对:密钥对生成耗时长,应复用,通常使用固定密钥对,定期轮换。
  2. 配合对称加密:RSA效率低,适合加密少量数据,大文件先通过AES加密(速度块),再用RSA加密AES密钥。
  3. 使用安全随机数:Java默认使用SecureRandom,无需额外配置。
  4. 禁用不安全的填充:不要使用"RSA/ECB/NoPadding"(无填充),不加密仅用于签名场景。
  5. 密钥长度选择:1024位已不安全,2048位是当前基线,4096位更安全但性能下降约2~3倍。

在Java中实现RSA加密,遵循以下步骤:

  1. 确定算法模式:RSA/ECB/OAEPWithSHA-256AndMGF1Padding
  2. 生成2048位密钥对
  3. 使用Cipher类完成加密/解密
  4. 注意数据大小限制,必要时采用混合加密

掌握这些,你就能在Java项目中安全地使用RSA加密了。实际开发中建议直接使用现成的JCE API,避免重复造轮子,但必须理解其原理才能应对异常场景。

抱歉,评论功能暂时关闭!