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
相关产品推荐
相关产品推荐

