You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中RSA结合对称密钥加解密文件时InvalidKeyException问题求助

解决RSA解密对称密钥时的InvalidKeySpecException异常

问题根源分析

你的代码抛出invalid key format异常,核心原因和几个关键错误如下:

  • 私钥加载逻辑错误:在decryptSymmetricKey方法中,你读取的是publicKey.key文件,却用PKCS8EncodedKeySpec(私钥格式)来生成私钥。X509是公钥的标准格式,PKCS8是私钥的标准格式,两者不能混用。
  • 解密方法逻辑冗余:decryptSymmetricKey里调用encryptSymmetricKey(secKey)完全没必要,解密的前提是已有加密后的对称密钥,应该直接传入加密后的密钥字节数组,而非重新加密。
  • IV未持久化:AES/CBC模式依赖IV(初始化向量),你当前仅在内存生成IV,未保存到文件,实际场景中重启程序后无法正确解密。
  • 文件覆盖风险:main方法中直接将解密结果写回原输入文件,会覆盖原始数据,测试时需使用独立的输出文件。

修正后的代码

1. 修复私钥加载与解密方法

public static SecretKey decryptSymmetricKey(byte[] encryptedKey) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
    // 读取私钥文件(注意是privateKey.key,不是公钥文件)
    byte[] privateKeyBytes = Files.readAllBytes(Paths.get("privateKey.key"));
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
    PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
    
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    byte[] decryptedKey = cipher.doFinal(encryptedKey);
    return new SecretKeySpec(decryptedKey, 0, decryptedKey.length, "AES");
}

2. 添加IV的保存与加载方法

public static void saveIv(IvParameterSpec iv, File ivFile) throws IOException {
    Files.write(ivFile.toPath(), iv.getIV());
}

public static IvParameterSpec loadIv(File ivFile) throws IOException {
    byte[] ivBytes = Files.readAllBytes(ivFile.toPath());
    return new IvParameterSpec(ivBytes);
}

3. 修正main方法的流程逻辑

public static void main(String[] args) throws Exception {
    SecretKey secKey = generateKey(128);
    IvParameterSpec iv = generateIv();
    
    // 定义文件路径,避免覆盖原文件
    File inputFile = new File("C:/Users/nm-ca/IdeaProjects/RSA/src/inputFile.txt");
    File encryptedFile = new File("C:/Users/nm-ca/IdeaProjects/RSA/src/encryptedFile.txt");
    File decryptedFile = new File("C:/Users/nm-ca/IdeaProjects/RSA/src/decryptedFile.txt");
    File ivFile = new File("C:/Users/nm-ca/IdeaProjects/RSA/src/iv.dat");
    File encryptedSymKeyFile = new File("C:/Users/nm-ca/IdeaProjects/RSA/src/encryptedSymKey.dat");
    
    // 加密流程
    encryptFile("AES/CBC/PKCS5Padding", secKey, iv, inputFile, encryptedFile);
    saveIv(iv, ivFile);
    byte[] encryptedSymKey = encryptSymmetricKey(secKey);
    Files.write(encryptedSymKeyFile.toPath(), encryptedSymKey);
    
    // 解密流程
    byte[] loadedEncryptedSymKey = Files.readAllBytes(encryptedSymKeyFile.toPath());
    SecretKey decryptedSecKey = decryptSymmetricKey(loadedEncryptedSymKey);
    IvParameterSpec loadedIv = loadIv(ivFile);
    decryptFile("AES/CBC/PKCS5Padding", decryptedSecKey, loadedIv, encryptedFile, decryptedFile);
}

4. RSA密钥生成工具(需提前执行生成公/私钥文件)

public static void generateRSAKeys() throws NoSuchAlgorithmException, IOException {
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(2048); // 推荐使用2048位及以上长度
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    
    // 保存公钥(X509格式)
    Files.write(Paths.get("publicKey.key"), keyPair.getPublic().getEncoded());
    // 保存私钥(PKCS8格式)
    Files.write(Paths.get("privateKey.key"), keyPair.getPrivate().getEncoded());
}

关键注意事项

  • 公钥和私钥必须配对生成:公钥用于加密对称密钥,私钥用于解密对称密钥,不能交叉使用。
  • AES/CBC模式必须保存IV:解密时必须使用与加密时完全相同的IV,否则无法正确解密。
  • 避免文件覆盖:测试阶段使用独立的加密/解密文件,防止原始数据丢失。

内容的提问来源于stack exchange,提问作者darkman106

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 23:35:20