代码之家  ›  专栏  ›  技术社区  ›  Stzer

多层流读/写中的c#加密

  •  0
  • Stzer  · 技术社区  · 9 年前

    有从多个数据层创建的文件:

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

    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可以通过这种方式接收回来。有些数据会不同,写入的文件会比原始数据长,这让我认为问题在于加密流+二进制读取器从文件开始读取。 也许你会建议我使用 MemoryStream 我找到的唯一其他解决方案是 SubStream 但不幸的是,当我在“fs”和“cs”之间使用它时,它导致了错误的“somedata”,并且生成的文件也有错误的数据。

    也许有一种方法可以使用 Memory-Mapped Files ? 但我不太确定我需要如何以这种方式处理它。 或者我遗漏了一些其他的东西,因为使用BinaryWriter和CryptoStream编写“Wittendata的泛化”看起来效果不错。

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

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

    但不幸的是,这并没有解决这个问题,一些数据和写入文件的数据都与原始数据不一样。

    更新#2:

    所以这是一个愚蠢的问题——我创造了 CreateEncryptor() 而不是 CreateDecryptor()

    1 回复  |  直到 9 年前
        1
  •  0
  •   Kevin Ford    9 年前

    可能我有点胖,但你不能只寻找fs的适当位置,然后继续使用相同的二进制读取器吗?

    编辑:此外,您确定在解密时正确构建了加密转换吗?

    编辑: 当我使用以下代码时,您的代码与您提供的代码一样工作:

        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是我提供并解密的值。垃圾桶与普通垃圾桶相同。箱子

    这表明您提供给解密程序的密钥存在问题。

    更新1:

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

    结果是一样的,它仍然和你最初发布的一样有效。

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

    问题确实存在于密钥中,因此我的建议是在创建加密程序并转储密钥/iv后中断,然后在创建解密程序并检查它们是否完全相同后执行相同的操作。

    推荐文章