使用CryptoStream解密返回空文件问题排查
解密后文件为空的问题排查与解决
我帮你找出解密后文件为空的核心原因了——加密阶段的FileStream位置没有重置到开头,导致你实际加密的是空内容,解密自然也只能得到空文件。下面一步步分析问题并给出修正方案:
问题根源分析
在你的tempEncrypt方法中,创建test.txt并写入"Test String"后,FileStream的指针已经移动到了文件末尾。此时直接把这个流传给Encrypt方法调用source.CopyTo(cryptoStream),因为流的位置在末尾,没有任何数据可以复制,最终加密的encrypted.tmp是空文件,替换原文件后,解密当然只能得到空内容。
另外还有两个小细节会影响加密解密的正确性:
- 加密时没有调用
CryptoStream.FlushFinalBlock(),AES是块加密算法,最后一块数据需要填充,这个方法会确保所有加密数据都写入目标流。 - 手动调用
Stream.Close()容易导致资源泄漏,应该用using语句自动管理流的生命周期。
修正后的代码
加密部分代码调整
tempEncrypt方法
重新打开文件流(确保指针在开头),或者写入后重置流位置:
private void tempEncrypt() { // Creates file with "Test String" inside byte[] test = Encoding.ASCII.GetBytes("Test String"); using (var file = File.Create("test.txt")) { file.Write(test, 0, test.Length); } // 重新打开文件流,此时指针默认在文件开头 using (var file = File.OpenRead("test.txt")) { // Saves key and IV for decryption var temp = new AesCryptoServiceProvider(); Console.WriteLine(System.Convert.ToBase64String(temp.Key)); Console.WriteLine(System.Convert.ToBase64String(temp.IV)); Encryptor.Encrypt(file, temp.Key, temp.IV); } }
Encrypt方法
用using管理所有流资源,添加FlushFinalBlock()确保加密数据完整写入:
public static void Encrypt(FileStream source, byte[] key, byte[] IV) { string path = source.Name; // 用using自动管理目标流资源 using (var destination = File.Create("encrypted.tmp")) using (var provider = new AesCryptoServiceProvider()) using (var transform = provider.CreateEncryptor(key, IV)) using (var cryptoStream = new CryptoStream(destination, transform, CryptoStreamMode.Write)) { // 双重保险:确保源流指针在开头 source.Seek(0, SeekOrigin.Begin); // 复制数据进行加密 source.CopyTo(cryptoStream); // 确保所有加密数据(包括最后一块填充数据)写入目标流 cryptoStream.FlushFinalBlock(); } // 替换原文件 File.Delete(path); File.Move("encrypted.tmp", path); }
解密部分代码调整
Decrypt方法
同样用using管理流资源,确保源流指针在开头:
public static void Decrypt(FileStream source, byte[] key, byte[] IV) { string path = source.Name; using (var destination = File.Create("decrypted.tmp")) using (var provider = new AesCryptoServiceProvider()) using (var transform = provider.CreateDecryptor(key, IV)) using (var cryptoStream = new CryptoStream(source, transform, CryptoStreamMode.Read)) { // 确保源流指针在开头 source.Seek(0, SeekOrigin.Begin); // 解密并写入目标文件 cryptoStream.CopyTo(destination); } // 替换原文件 source.Close(); File.Delete(path); File.Move("decrypted.tmp", path); }
额外注意事项
- 保存的Key和IV必须完全匹配,解密时不能写错,否则会解密失败或得到乱码。
AesCryptoServiceProvider在.NET Core/.NET 5+中已被标记为过时,建议改用Aes.Create()来创建AES实例,兼容性更好。
内容的提问来源于stack exchange,提问作者Dylan
相关产品推荐
相关产品推荐

