Can a CryptoStream be returned and still have everything dispose correctly?

陌路散爱 提交于 2019-12-09 03:11:21

问题


If I have a CryptoStream that I want to pass back to the user, the naïve approach would be

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

I know that when I dispose the CryptoStream the underlying FileStream will also be disposed. The issue I am running in to is what do I do with rmCrypto and transform? RijndaelManaged and ICryptoTransform are disposable classes, but disposing of the stream does not dispose those two objects.

What is the correct way to handle this situation?


回答1:


I'd consider creating your own class that wraps the stream and then you can manage the disposal of these. Somethings along these lines (sorry - don't know the type of the transform object off top of my head).

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



回答2:


Ian beat me to the basic concept (go upvote him), but CryptoStream itself is not sealed so it is trivial to make a derived class that wraps the things that need to be disposed.

/// <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();
        }
    }
}

Used like

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


来源:https://stackoverflow.com/questions/24188644/can-a-cryptostream-be-returned-and-still-have-everything-dispose-correctly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!