在CryptoStream的开头添加IV [英] Add IV to beginning of CryptoStream

查看:85
本文介绍了在CryptoStream的开头添加IV的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在现有文件管理程序中实施本地加密。

I'm implementing local encryption within an existing file management program.

我可以找到很多示例代码,例如微软的,演示了如何直接写入文件,但是我需要做的是提供一个流,该流在程序的其他地方使用:

Much of the example code I can find, such as Microsoft's, demonstrates how to write directly to a file, but what I need to do is provide a stream that is consumed elsewhere in the program:

CryptoStream GetEncryptStream(string filename)
{
    var rjndl = new RijndaelManaged();
    rjndl.KeySize = 256;
    rjndl.BlockSize = 256;
    rjndl.Mode = CipherMode.CBC;
    rjndl.Padding = PaddingMode.PKCS7;

    // Open read stream of unencrypted source fileStream:
    var fileStream = new FileStream(filename, FileMode.Open); 

    /* Get key and iv */

    var transform = rjndl.CreateEncryptor(key, iv);

    // CryptoStream in *read* mode:
    var cryptoStream = new CryptoStream(fileStream, transform, CryptoStreamMode.Read); 

    /* What can I do here to insert the unencrypted IV at the start of the
       stream so that the first X bytes returned by cryptoStream.Read are
       the IV, before the bytes of the encrypted file are returned? */

    return cryptoStream; // Return CryptoStream to be consumed elsewhere
}

我的问题在评论中概述最后一行,但最后一行:我如何将IV添加到CryptoStream的开头,这样它将成为读取CryptoStream时返回的第一个X字节,并且可以控制何时开始实际读取流并写入文件不在我的代码范围之内?

My issue is outlined in the comment on the last line but one: how can I add the IV to the start of the CryptoStream such that it will be the first X bytes returned when the CryptoStream is read, given that control of when to actually start reading the stream and writing to a file is outside the scope of my code?

推荐答案

好...现在您的问题很清楚了,这很容易 ....遗憾的是,.NET不包含用于合并两个 Stream 的类,但是我们可以轻松地创建它。 MergedStream 是只读的,仅转发的多流合并。

Ok... now that your problem is clear, it is "quite" easy... Sadly .NET doesn't include a class to merge two Stream, but we can easily create it. The MergedStream is a read-only, forward-only multi-Stream merger.

您的用法如下:

var mergedStream = new MergedStream(new Stream 
{
    new MemoryStream(iv),
    cryptoStream,
}

现在...当有人试图从<$ c $中读取时c> MergedStream ,首先将使用包含IV的 MemoryStream ,然后使用 cryptoStream

Now... When someone tries to read from the MergedStream, first the MemoryStream containing the IV will be consumed, then the cryptoStream will be consumed.

public class MergedStream : Stream
{
    private Stream[] streams;

    private int position = 0;

    private int currentStream = 0;

    public MergedStream(Stream[] streams)
    {
        this.streams = streams;
    }

    public override bool CanRead => true;

    public override bool CanSeek => false;

    public override bool CanWrite => false;

    public override long Length => throw new NotImplementedException();

    public override long Position { get => position; set => throw new NotSupportedException(); }

    public override void Flush()
    {
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        if (streams == null)
        {
            throw new ObjectDisposedException(nameof(MergedStream));
        }

        if (currentStream >= streams.Length)
        {
            return 0;
        }

        int read;

        while (true)
        {
            read = streams[currentStream].Read(buffer, offset, count);
            position += read;

            if (read != 0)
            {
                break;
            }

            currentStream++;

            if (currentStream == streams.Length)
            {
                break;
            }
        }

        return read;
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        throw new NotSupportedException();
    }

    public override void SetLength(long value)
    {
        throw new NotSupportedException();
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        throw new NotSupportedException();
    }

    protected override void Dispose(bool disposing)
    {
        try
        {
            if (disposing && streams != null)
            {
                for (int i = 0; i < streams.Length; i++)
                {
                    streams[i].Close();
                }
            }
        }
        finally
        {
            streams = null;
        }
    }
}

这篇关于在CryptoStream的开头添加IV的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆