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

.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));
    }
}

额外优化建议

  1. 不要捕获所有Exception,明确捕获CryptographicException避免掩盖未知错误。
  2. 反序列化时的MemoryStream用using块管理,自动释放资源。
  3. 解密前可先验证加密数据长度是否符合AES要求(需为块大小整数倍+IV长度),提前过滤无效数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 16:12:21