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

AES解密后CipherInputStream写入文本文件无内容问题求助

问题分析与解决方案

嘿,我一眼就发现你代码里的关键问题,这就是为啥解密后写入文件为空的原因:

核心问题1:输入流被提前读取到末尾

你在创建CipherInputStream之前,执行了这两行代码:

byte[] inputBytes = new byte[(int) decryptedData.length()];
inputStream.read(inputBytes);

首先,decryptedData是你要新建的文件,初始长度为0,所以inputBytes是一个长度为0的数组,这行read根本读不到任何数据。更致命的是,这行read操作会把inputStream的指针移动到流的末尾,后面CipherInputStream基于这个流创建后,再去读就没有任何数据可以读取了,自然写入文件就是空的。

解决方案:直接删掉这两行代码,让CipherInputStream直接从原始的inputStream读取数据就行。

核心问题2:不必要的SecureRandom参数

在解密模式下调用cipher.init时,不需要传入SecureRandom.getInstance("SHA1PRNG"),因为CBC模式的初始化向量(IV)已经提供了所需的随机性,额外传入随机源反而可能引发兼容性问题(比如不同Java版本的实现差异)。

额外优化:用try-with-resources自动管理流

你代码里手动调用close,还出现了未定义的bufin.close(),很容易因为异常导致流没有正确关闭。用Java的try-with-resources语法可以自动关闭所有实现了AutoCloseable的资源,更安全简洁。

修正后的完整代码

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.charset.StandardCharsets;

public class DecryptExample {
    public static void main(String[] args) throws Exception {
        // 假设你的key和iv已经和加密时完全一致
        SecretKeySpec newkey = new SecretKeySpec("your-valid-aes-key".getBytes(StandardCharsets.UTF_8), "AES");
        IvParameterSpec newiv = new IvParameterSpec("your-16-byte-iv".getBytes(StandardCharsets.UTF_8));

        File encryptedData = new File("C:\\Users\\Victoria\\Desktop\\encryptedData.txt");
        File decryptedData = new File("C:\\Users\\Victoria\\Desktop\\decryptedData.txt");

        // 使用try-with-resources自动关闭所有流
        try (FileInputStream inputStream = new FileInputStream(encryptedData);
             CipherInputStream cipherInputStream = new CipherInputStream(inputStream, getDecryptionCipher(newkey, newiv));
             FileOutputStream outputStream = new FileOutputStream(decryptedData)) {

            byte[] buff = new byte[1024 * 10];
            int length;
            while ((length = cipherInputStream.read(buff)) > 0) {
                outputStream.write(buff, 0, length);
                // 如果要把解密内容打印到控制台,加上这行(指定编码避免乱码)
                System.out.print(new String(buff, 0, length, StandardCharsets.UTF_8));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static Cipher getDecryptionCipher(SecretKeySpec key, IvParameterSpec iv) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        // 解密模式不需要传入SecureRandom
        cipher.init(Cipher.DECRYPT_MODE, key, iv);
        return cipher;
    }
}

最后几个注意事项

  • 必须确保加密和解密使用完全相同的key、IV、加密算法(包括模式和填充方式),否则解密会失败或得到乱码。
  • 打印控制台内容时,一定要指定正确的字符编码(比如UTF-8),避免出现乱码。
  • 如果加密时的IV不是硬编码的,要确保解密时能获取到正确的IV(通常IV会和加密数据一起存储,比如放在加密文件的开头)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:34:25