.NET Framework 4.8中异常后CryptoStream释放的最佳实践
解决CryptoStream Dispose时重复抛异常的问题
问题根源
CryptoStream的Dispose()方法执行时,会自动调用FlushFinalBlock()完成剩余解密流程,其中包含PKCS7填充的校验步骤。当密钥错误时,填充校验失败,就会再次抛出CryptographicException: Padding is invalid and cannot be removed.异常,这就是你遇到的核心问题。
解决方案
既然已经明确解密失败,Dispose时抛出的异常属于预期的无效校验结果,我们只需要确保资源被清理,无需处理该异常。可以在调用Dispose()时单独包裹一层try-catch,避免异常扩散影响后续资源释放。
同时,遵循IDisposable规范管理所有流对象,确保资源被正确回收。
修改后的代码
using (Aes aes = Aes.Create()) { // 提取IV和加密数据 int IVsize = aes.IV.Length; int encDataSize = encByteArray.Length - IVsize; byte[] ivFromData = new byte[IVsize]; byte[] encData = new byte[encDataSize]; Buffer.BlockCopy(encByteArray, 0, ivFromData, 0, IVsize); Buffer.BlockCopy(encByteArray, IVsize, encData, 0, encDataSize); aes.IV = ivFromData; aes.Key = passwordBytes; MemoryStream bencr = new MemoryStream(encData); CryptoStream cr = new CryptoStream(bencr, aes.CreateDecryptor(), CryptoStreamMode.Read); byte[] buf = new byte[encDataSize + 1]; bool success = false; try { cr.Read(buf, 0, buf.Length); success = true; } catch (CryptographicException) { // 捕获解密失败的预期异常,仅标记失败状态 } finally { // 单独处理CryptoStream的Dispose异常,确保资源回收 try { cr.Dispose(); } catch (CryptographicException) { // 忽略Dispose时的填充校验异常,资源已完成核心清理 } // 确保MemoryStream被释放 bencr.Dispose(); } if (!success) throw new CryptographicException("Could not decrypt data."); // 反序列化逻辑用using块自动管理流资源 using (MemoryStream unenc = new MemoryStream(buf)) { unenc.Position = 0; IFormatter form = new BinaryFormatter(); object restored = form.Deserialize(unenc); return (T)Convert.ChangeType(restored, typeof(T)); } }
额外优化建议
- 不要捕获所有
Exception,明确捕获CryptographicException避免掩盖未知错误。 - 反序列化时的MemoryStream用using块管理,自动释放资源。
- 解密前可先验证加密数据长度是否符合AES要求(需为块大小整数倍+IV长度),提前过滤无效数据。
内容的提问来源于stack exchange,提问作者Himilou
相关产品推荐
相关产品推荐

