多层流中的c#加密读/写 [英] c# Encryption in a multi-layered Streams read/write

查看:107
本文介绍了多层流中的c#加密读/写的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有些文件是根据多层数据创建的:

There are files created from multiple layers of data:

    //input is not always the same, but the structure is, so for example there might be h4 and h5, but I will know that, so that is not the problem
    private void generalizationofwrittendata(string filename, int someint, int chunks, string outputfilename, ICryptoTransform crypt, byte[] somedata, int h1, int h2, int h3)
    {
        using (FileStream fs = new FileStream(outputfilename, FileMode.Create, FileAccess.Write))
        {
            using (BinaryWriter w = new BinaryWriter(fs, Encoding.ASCII))
            {
                //writing some data with binary writer
                w.Write(h1);
                w.Write(h2);
                w.Write(h3);
                using (FileStream fsIn = File.OpenRead(filename))
                {
                    using (CryptoStream cs = new CryptoStream(fs, crypt, CryptoStreamMode.Write))
                    {
                        //writing the rest of data with crypto stream
                        cs.Write(somedata, 0, somedata.Length);
                        byte[] chunk = new byte[chunks];
                        int bytesRead = 0;
                        while ((bytesRead = fsIn.Read(chunk, 0, chunks)) > 0)
                        {
                            cs.Write(chunk, 0, bytesRead);
                        }
                    }
                }
            }
        }
    }

通用化的书面数据"可以按预期的方式很好地工作.

"generalizationofwrittendata" works perfectly fine in an intended way.

现在的问题是从文件中分离出所有数据:

Now the problem is in separating all of that data from the file:

private void test(string filename, int someint, int chunks, string outputfilename, ICryptoTransform crypt)
    {
        using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
        {
            using (BinaryReader br = new BinaryReader(fs, Encoding.ASCII))
            {
                //reading some not encrypted data
                int h1 = br.ReadInt32();
                int h2 = br.ReadInt32();
                int h3 = br.ReadInt32();
                using (CryptoStream cs = new CryptoStream(fs, crypt, CryptoStreamMode.Read))
                {
                    using (BinaryReader br2 = new BinaryReader(cs, Encoding.ASCII))
                    {
                        //reading some encrypted data
                        byte[] somedata = br2.ReadBytes(someint);
                        //writing the rest of the data to file
                        using (FileStream fsOut = new FileStream(outputfilename, FileMode.Create))
                        {
                            byte[] chunk = new byte[chunks];
                            int bytesRead = 0;
                            while ((bytesRead = cs.Read(chunk, 0, chunks)) > 0)
                            {
                                fsOut.Write(chunk, 0, bytesRead);
                            }
                        }
                    }
                }
            }
        }
    }

这种方法根本行不通.这样只能接收回h1,h2,h3. somedata将有所不同,并且写入的文件将比原始数据更长,这使我想到问题在于CryptoStream + BinaryReader从文件的开头读取. 可能您会建议我使用MemoryStream,但这仅对小文件有效,因此将导致内存超出范围异常. 我发现的唯一其他解决方案是 SubStream 实现,但是不幸的是,当我在"fs"和"cs"之间使用它时,导致错误的"somedata"和生成的文件也包含错误的数据.

This approach simply doesn't work. Only h1,h2,h3 can be received back in this way. somedata will be different and the written file will be longer than the original data, which lead me to thinking that the problem is with CryptoStream+BinaryReader reading from the beginning of the file. Probably you will suggest me to use MemoryStream, but this will be valid only for small files, thus will lead to memory out of range exception. The only other solution I found was SubStream implementation, but unfortunately when I used it between "fs" and "cs" it resulted in wrong "somedata" and the resulted file had wrong data as well.

也许有一种方法可以使用内存映射文件?但是我不确定我将如何以这种方式进行处理. 也许我还缺少其他东西,因为先使用BinaryWriter编写"generalizationofwritingdata",然后CryptoStream确实可以正常工作.

Maybe there is a way to do this using Memory-Mapped Files? But I'm not quite sure how would I need to approach it in that way. Or maybe I'm missing something else, since writing in "generalizationofwrittendata" using BinaryWriter and then CryptoStream does seem to work just fine.

更新#1:

因此,在收到答复后,我重新检查了所有代码,尤其是与ICryptoTransform相关的代码. ICryptoTransform绝对不是问题,这两种方法完全相同.

So after receiving replies I've rechecked all of the code, especially related to ICryptoTransform. The ICryptoTransform is definitely not the problem, it is exactly the same for both methods.

我注意到的另一件事是我没有明显原因使用"BinaryReader br2",因此我将其删除:

The other thing that I noticed was that I used "BinaryReader br2" for no apparent reason, so I have removed that:

private void test(string filename, int someint, int chunks, string outputfilename, ICryptoTransform crypt)
    {
        using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
        {
            using (BinaryReader br = new BinaryReader(fs, Encoding.ASCII))
            {
                //reading some not encrypted data
                int h1 = br.ReadInt32();
                int h2 = br.ReadInt32();
                int h3 = br.ReadInt32();
                using (CryptoStream cs = new CryptoStream(fs, crypt, CryptoStreamMode.Read))
                {
                    //reading some encrypted data
                    byte[] somedata = new byte[someint];
                    cs.Read(somedata, 0, someint);
                    //writing the rest of the data to file
                    using (FileStream fsOut = new FileStream(outputfilename, FileMode.Create))
                    {
                        byte[] chunk = new byte[chunks];
                        int bytesRead = 0;
                        while ((bytesRead = cs.Read(chunk, 0, chunks)) > 0)
                        {
                            fsOut.Write(chunk, 0, bytesRead);
                        }
                    }
                }
            }
        }
    }

但是不幸的是,这并不能解决问题,某些数据和写入文件的数据都与原始数据不同.

But unfortunately that hasn't solved the issue, both somedata and the data written to file aren't the same as original.

更新#2:

这是一个愚蠢的问题-我创建了CreateEncryptor()而不是CreateDecryptor()进行解密.

So that was a stupid problem - I've created CreateEncryptor() instead of CreateDecryptor() for decryption.

推荐答案

可能我很胖,但是您难道不只是寻求fs的适当位置并继续使用相同的二进制读取器吗?

Possibly I am being thick, but couldn't you just seek to the appropriate position of fs and continue to use the same binary reader?

我会尝试一下,但是设置一个加密密钥将需要一些时间.

I will try this but setting up a crypto key will take some time.

另外,您确定在解密时正确构建了CryptoTransform吗?

Also, are you certain that you are building the CryptoTransform correctly when you decrypt?

当我使用以下代码时,您的代码将按您提供的方式工作:

Your code works as you supplied it when I use the following code:

    byte[] testdata = new byte[] { 0x12, 0x34, 0x56 };
    byte[] key;
    byte[] iv;

    String encryptedFile = "encrypted.bin";
    private void buttonCrypt_Click(object sender, EventArgs e)
    {
        ICryptoTransform transform;
        RijndaelManaged rjndl = new RijndaelManaged();
        rjndl.KeySize = 256;
        rjndl.BlockSize = 256;
        rjndl.Mode = CipherMode.CBC;
        transform = rjndl.CreateEncryptor();
        key = (byte[])rjndl.Key.Clone();
        iv = (byte[])rjndl.IV.Clone();
        generalizationofwrittendata("plain.bin",testdata.Length,1,encryptedFile,transform,testdata,0x0abbccdd,0x01223344,0x09887766);
    }

    private void buttonDecrypt_Click(object sender, EventArgs e)
    {
        RijndaelManaged rjndl = new RijndaelManaged();
        rjndl.KeySize = 256;
        rjndl.BlockSize = 256;
        rjndl.Mode = CipherMode.CBC;
        var transform = rjndl.CreateDecryptor(key, iv);
        test(encryptedFile, testdata.Length, 1, "decrypted.bin", transform);
    }

其他数据读取为{0x12,0x34,0x56},h1至h3是我提供并解密的值.bin与plain.bin相同.

The other data is read as {0x12,0x34,0x56}, h1 to h3 are the values I supplied and decrypted.bin is the same as plain.bin.

这表明您提供给解密器的密钥有问题.

This points to a problem with the key you are supplying to the decryptor.

更新1:

我已经修改了测试工具以使用Aes:

I have modded my test harness to use Aes:

    private void buttonCrypt_Click(object sender, EventArgs e)
    {
        ICryptoTransform transform;
        AesManaged Aes = new AesManaged();
        Aes.KeySize = 256;
        Aes.BlockSize = 128;
        Aes.Mode = CipherMode.CBC;
        Aes.Padding = PaddingMode.PKCS7;
        transform = Aes.CreateEncryptor();
        key = (byte[])Aes.Key.Clone();
        iv = (byte[])Aes.IV.Clone();
        generalizationofwrittendata("plain.bin",testdata.Length,1,encryptedFile,transform,testdata,0x0abbccdd,0x01223344,0x09887766);
    }

    private void buttonDecrypt_Click(object sender, EventArgs e)
    {
        AesManaged Aes = new AesManaged();
        Aes.KeySize = 256;
        Aes.BlockSize = 128;
        Aes.Mode = CipherMode.CBC;
        Aes.Padding = PaddingMode.PKCS7;
        var transform = Aes.CreateDecryptor(key, iv);
        test(encryptedFile, testdata.Length, 1, "decrypted.bin", transform);
    }

结果相同,它仍然可以像您最初发布时一样工作.

The results are identical, it still works as you originally posted it.

我正在让Aes创建一个保存的密钥和初始化向量,您需要检查加密和解密是否都使用完全相同的值来调用您的Aes生成器.另外,请确保使用Aes.CreateEncyptor()进行加密,并使用Aes.CreateDecryptor()进行解密.

I am getting Aes to create a key and initialisation vector which I save, you need to check that the encryption and decryption both call your Aes generator with exactly the same values. Also, ensure that you are using Aes.CreateEncyptor() to encrypt and Aes.CreateDecryptor() to decrypt.

问题确实必须存在于密钥中,因此我的建议是在创建加密器并转储密钥/iv之后中断,然后在创建解密器并检查它们是否字节对字节相同后再执行相同操作.

The problem really does have to be in the keys so my suggestion is to break after you create the encryptor and dump the key/iv, then do the same after you create the decryptor and check that they are byte for byte identical.

这篇关于多层流中的c#加密读/写的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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