块进行的AES加密和解密导致错误的输出

时间:2018-12-16 07:45:20

标签: c# encryption aes

嗨,我正在使用C#代码并尝试加密和解密CSV文件 缺少记录和24列。

将其逐块加密4 mb,并随机生成盐。我该如何解决这个问题。

class Program
    {
        public static void Main()
        {
            Program p = new Program();
            string In_filePath = @"C:\Users\Selvakumar.Velusamy\Desktop\Test\Check.csv";
            string Enc_Out_filePath = @"C:\Users\Selvakumar.Velusamy\Desktop\Test\Check_Enc.csv";
            string Dec_Out_filePath = @"C:\Users\Selvakumar.Velusamy\Desktop\Test\Check_Dec.csv";
            byte[] password = Encoding.ASCII.GetBytes("Test");
            p.Encrypt(In_filePath,Enc_Out_filePath, password);
            p.Decrypt(password , Enc_Out_filePath, Dec_Out_filePath);
        }

        public static byte[] GenerateRandomSalt()
        {
            byte[] data = new byte[32];

            using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
            {
                for (int i = 0; i < 10; i++)
                {
                    rng.GetBytes(data);
                }
            }

            return data;
        }

        public void Encrypt(string inputFileName, string outputFileName, byte[] encryptionKey)
        {
            byte[] salt = GenerateRandomSalt();

            int chunkSizeInBytes = 4 * 1048576;
            byte[] chunk = new byte[chunkSizeInBytes];
            FileStream Infs = new FileStream(inputFileName, FileMode.Open);
            FileStream OutFs = new FileStream(outputFileName, FileMode.Create);

            using (var aesProvider = new RijndaelManaged())
            {
                aesProvider.KeySize = 256;
                aesProvider.BlockSize = 128;
                aesProvider.Padding = PaddingMode.PKCS7;
                aesProvider.Mode = CipherMode.CFB;

                using (var key = new Rfc2898DeriveBytes(encryptionKey, salt, 50000))
                {
                    aesProvider.Key = key.GetBytes(aesProvider.KeySize / 8);
                    aesProvider.IV = key.GetBytes(aesProvider.BlockSize / 8);
                    int bytesRead;
                    MemoryStream mstream = null;

                    try
                    {
                        mstream = new MemoryStream();
                        mstream.Write(salt, 0, salt.Length);

                        while ((bytesRead = Infs.Read(chunk, 0, chunkSizeInBytes)) > 0)
                        {
                            using (var cryptoStream = new CryptoStream(mstream, aesProvider.CreateEncryptor(), CryptoStreamMode.Write))
                            {
                                cryptoStream.Write(chunk, 0, bytesRead);
                                OutFs.Write(mstream.ToArray(), 0, mstream.ToArray().Length);
                            }

                            mstream = new MemoryStream();
                        }
                    }
                    catch (Exception)
                    {
                        throw;
                    }
                    finally
                    {
                        if (mstream != null)
                            mstream.Close();

                        if (Infs != null)
                            Infs.Dispose();

                        if (OutFs != null)
                            OutFs.Dispose();

                        Infs.Close();
                        OutFs.Close();
                    }
                }
            }
        }

        public void Decrypt(byte[] password, string inputfile, string outputfile)
        {
            byte[] salt = new byte[32];
            FileStream fsCrypt = new FileStream(inputfile, FileMode.Open);
            int readsize = fsCrypt.Read(salt, 0, salt.Length);

            RijndaelManaged AES = new RijndaelManaged();
            AES.KeySize = 256;
            AES.BlockSize = 128;
            var key = new Rfc2898DeriveBytes(password, salt, 50000);
            AES.Key = key.GetBytes(AES.KeySize / 8);
            AES.IV = key.GetBytes(AES.BlockSize / 8);
            AES.Padding = PaddingMode.None;
            AES.Mode = CipherMode.CFB;

            FileStream fsOut = new FileStream(outputfile, FileMode.Create);
            int read;
            byte[] buffer = new byte[1048576 * 4];

            MemoryStream ms;
            try
            {
                while ((read = fsCrypt.Read(buffer, 0, (buffer.Length))) > 0)
                {
                    ms = new MemoryStream(buffer);
                    using (CryptoStream cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Read))
                    {
                        int chunkCount = cs.Read(buffer, 0, read);
                        fsOut.Write(buffer, 0, buffer.Length);
                        fsCrypt.Read(salt, 0, salt.Length);
                    }
                    ms = new MemoryStream();
                }
            }
            catch (CryptographicException ex_CryptographicException)
            {
                Debug.WriteLine("CryptographicException error: " + ex_CryptographicException.Message);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Error: " + ex.Message);
            }

            finally
            {
                fsOut.Close();
                fsCrypt.Close();
            }
        }
    }

逐块加密csv文件并将其解密,我得到的结果是错误的csv。每个块后面都有一些垃圾字符。

谢谢。

1 个答案:

答案 0 :(得分:0)

您在流的开头编写了一次盐,但是对于每个块都读取了盐。

像这样更改您的加密方法:

....
MemoryStream mstream = null;

try {

    while ((bytesRead = Infs.Read(chunk, 0, chunkSizeInBytes)) > 0) {
        mstream = new MemoryStream();
        mstream.Write(salt, 0, salt.Length);
        using (var cryptoStream = new CryptoStream(mstream, aesProvider.CreateEncryptor(), CryptoStreamMode.Write)) {
....

或删除Decrypt方法的while循环内的fsCrypt.Read(salt, 0, salt.Length);