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

Sco*_*ain 7 .net c# encryption dispose stream

如果我有一个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;
}
Run Code Online (Sandbox Code Playgroud)

我知道,当我处置时CryptoStream,底层FileStream 也会被处置掉.我到运行的问题是我该怎么办与rmCryptotransformRijndaelManaged并且ICryptoTransform是一次性类,但处理流不会处理这两个对象.

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

Ian*_*Ian 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 实际上,这与我在"问我的鸭子"之后提出问题后提出的解决方案非常相似.你可以派生出`CryptoStream`.我会发一个答案. (3认同)

Sco*_*ain 6

Ian打败了我的基本概念(向上投票),但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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用过像

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;
}
Run Code Online (Sandbox Code Playgroud)