可以返回CryptoStream并且仍然可以正确处理所有内容吗?

时间:2014-06-12 15:47:29

标签: c# .net encryption stream dispose

如果我有CryptoStream我希望传回给用户,那么天真的做法就是

public Stream GetDecryptedFileStream(string inputFile, byte[] key, byte[] iv)
{
    var fsCrypt = new FileStream(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read);
    var rmCrypto = new RijndaelManaged();
    var transform = rmCrypto.CreateDecryptor(key, iv);
    var cs = new CryptoStream(fsCrypt, transform, CryptoStreamMode.Read);

    return cs;
}

我知道当我处理CryptoStream基础FileStream will also be disposed时。我遇到的问题是我如何处理rmCryptotransformRijndaelManagedICryptoTransform是一次性类,但处理流不会处理这两个对象。

处理这种情况的正确方法是什么?

2 个答案:

答案 0 :(得分:6)

我考虑创建自己的包装流的类,然后您可以管理这些的处理。沿着这些方向的事情(抱歉 - 不知道我头顶的变换对象的类型)。

public CryptoStreamWrapper : Stream, IDisposable
{
    public CryptoStreamWrapper(CryptoStream stream, RijndaelManaged rmCrypto, IDisposable transform)
    {
        this.transform = transform;
        this.rmCrypto = rmCrypto;
        this.stream = stream;
    }

    public void Dispose()
    {
        this.transform.Dispose();
        this.rmCrypto.Dispose();
        this.stream.Dispose();
    }
}

答案 1 :(得分:6)

Ian打败了我的基本概念(go upvote him),但CryptoStream本身并没有被密封,所以创建一个包含需要处理的东西的派生类是微不足道的。

/// <summary>
/// Creates a class that creates a <see cref="CryptoStream"/> and wraps the disposing action of all the associated objects 
/// </summary>
class ReturnableCryptoStream : CryptoStream
{
    private readonly ICryptoTransform _transform;
    private readonly IDisposable _algorithm;

    public ReturnableCryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode) 
        : this(stream, transform, mode, null)
    {
    }

    public ReturnableCryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode, IDisposable algorithm) 
        : base(stream, transform, mode)
    {
        _transform = transform;
        _algorithm = algorithm;
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        if (disposing)
        {
            if (_transform != null)
                _transform.Dispose();

            if (_algorithm != null)
                _algorithm.Dispose();
        }
    }
}

一样使用
public Stream GetDecryptedFileStream(string inputFile, byte[] key, byte[] iv)
{
    var fsCrypt = new FileStream(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read);
    var rmCrypto = new RijndaelManaged();
    var transform = rmCrypto.CreateDecryptor(key, iv);
    var cs = new ReturnableCryptoStream(fsCrypt, transform, CryptoStreamMode.Read, rmCrypto);

    return cs;
}