简体   繁体   English

填充无效,无法删除。 c#解密AES Rijndael,AES托管

[英]Padding is invalid and cannot be removed. c# decrypt AES Rijndael, AES Managed

I am trying to encrypt and decrypt the file. 我正在尝试加密和解密文件。 Using AES methods in a MVC web application. 在MVC Web应用程序中使用AES方法。 I am able to encrypt file and decrypt only once. 我能够加密文件,并且只能解密一次。 If I try for second time it gives me "Padding is invalid and cannot be removed error." 如果我第二次尝试,它将显示“填充无效且无法删除错误”。

  1. I have tried almost every combination with different properties of AES properties. 我尝试了几乎所有具有AES属性不同属性的组合。
  2. I have tried using statement for disposing the objects. 我尝试使用语句来处理对象。
  3. I have tried using FlushFinalBlock() after CryptoStream write. 我尝试在CryptoStream写入后使用FlushFinalBlock()。
  4. I have tried with using AES.Padding to Zero (gives me no error but the file doesnt decrypt ), AES.Padding to None gives me error('Length of the data to encrypt is invalid.'). 我尝试将AES.Padding设置为零(不会给我任何错误,但文件不会解密),而将AES.Padding设置为None会给我错误(“要加密的数据长度无效。”)。 AES.Padding to PKCS7 gives me error (padding is invalid.) AES.Padding到PKCS7给我错误(填充无效。)

Please find my code below. 请在下面找到我的代码。

public class EncryptionDecryption
{
    //  Call this function to remove the key from memory after use for security
    [DllImport("KERNEL32.DLL", EntryPoint = "RtlZeroMemory")]
    public static extern bool ZeroMemory(IntPtr Destination, int Length);

    /// <summary>
    /// Creates a random salt that will be used to encrypt your file. This method is required on FileEncrypt.
    /// </summary>
    /// <returns></returns>
    public static byte[] GenerateRandomSalt()
    {
        byte[] data = new byte[32];

        using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
        {
            // Ten iterations.
            for (int i = 0; i < 10; i++)
            {
                // Fill buffer.
                rng.GetBytes(data);
            }
        }
        return data;
    }


    /// <summary>
    /// Encrypts a file from its path and a plain password.
    /// </summary>
    /// <param name="inputFile"></param>
    /// <param name="password"></param>
    public static void FileEncrypt(string inputFile, string password)
    {

        //generate random salt
        byte[] salt = GenerateRandomSalt();

        //create output file name
        using (FileStream fsCrypt = new FileStream(inputFile + ".aes", FileMode.Create))
        {
            //convert password string to byte arrray
            byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes(password);

            //Set Rijndael symmetric encryption algorithm
            using (AesManaged AES = new  AesManaged())
            {
                AES.KeySize = 256;
                AES.BlockSize = 128;
                AES.Padding = PaddingMode.None;

                //http://stackoverflow.com/questions/2659214/why-do-i-need-to-use-the-rfc2898derivebytes-class-in-net-instead-of-directly
                //"What it does is repeatedly hash the user password along with the salt." High iteration counts.
                var key = new Rfc2898DeriveBytes(passwordBytes, salt, 50000);
                AES.Key = key.GetBytes(AES.KeySize / 8);
                AES.IV = key.GetBytes(AES.BlockSize / 8);

                //Cipher modes: http://security.stackexchange.com/questions/52665/which-is-the-best-cipher-mode-and-padding-mode-for-aes-encryption
                AES.Mode = CipherMode.CBC;

                // write salt to the begining of the output file, so in this case can be random every time
                fsCrypt.Write(salt, 0, salt.Length);

                using (CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write))
                {

                    using (FileStream fsIn = new FileStream(inputFile, FileMode.Open))
                    {

                        //create a buffer (1mb) so only this amount will allocate in the memory and not the whole file
                        byte[] buffer = new byte[1048576];
                        int read;

                        try
                        {
                            while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
                            {
                                // Application.DoEvents(); // -> for responsive GUI, using Task will be better!
                                cs.Write(buffer, 0, read);

                            }

                            // Close up
                            fsIn.Close();
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Error: " + ex.Message);
                        }
                        finally
                        {
                            if (!cs.HasFlushedFinalBlock)
                                cs.FlushFinalBlock();
                            cs.Close();
                            fsCrypt.Close();
                        }
                    }
                }
            }
        }
    }

    /// <summary>
    /// Decrypts an encrypted file with the FileEncrypt method through its path and the plain password.
    /// </summary>
    /// <param name="inputFile"></param>
    /// <param name="outputFile"></param>
    /// <param name="password"></param>
    public static void FileDecrypt(string inputFile, string outputFile, string password)
    {
        byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes(password);
        byte[] salt = new byte[32];

        using (FileStream fsCrypt = new FileStream(inputFile, FileMode.Open))
        {
            fsCrypt.Read(salt, 0, salt.Length);

            using (AesManaged AES = new AesManaged ())
            {
                AES.KeySize = 256;
                AES.BlockSize = 128;
                var key = new Rfc2898DeriveBytes(passwordBytes, salt, 50000);
                AES.Key = key.GetBytes(AES.KeySize / 8);
                AES.IV = key.GetBytes(AES.BlockSize / 8);
                AES.Padding = PaddingMode.PKCS7;
                AES.Mode = CipherMode.CBC;



                using (CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateDecryptor(), CryptoStreamMode.Read))
                {

                    using (FileStream fsOut = new FileStream(outputFile, FileMode.Create))
                    {
                        int read;
                        byte[] buffer = new byte[1048576];
                        try
                        {                            
                            while ((read = cs.Read(buffer, 0, buffer.Length)) > 0)
                            {
                                //Application.DoEvents();
                                fsOut.Write(buffer, 0, read);
                                //if (!cs.HasFlushedFinalBlock)
                                    cs.FlushFinalBlock();
                            }                          
                        }
                        catch (CryptographicException ex_CryptographicException)
                        {
                            Console.WriteLine("CryptographicException error: " + ex_CryptographicException.Message);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Error: " + ex.Message);
                        }
                        try
                        {
                            cs.Close();
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Error by closing CryptoStream: " + ex.Message);
                        }
                        finally
                        {
                            fsOut.Close();
                            fsCrypt.Close();
                        }
                    }
                }
            }
        }
    }

}

calling methods Encryption 调用方法加密

       string password = "ThePasswordToDecryptAndEncryptTheFile";

        // For additional security Pin the password of your files
        GCHandle gch = GCHandle.Alloc(password, GCHandleType.Pinned);

        // Encrypt the file
        EncryptionDecryption.FileEncrypt(inputFilePath, password);

        // To increase the security of the encryption, delete the given password from the memory !
        EncryptionDecryption.ZeroMemory(gch.AddrOfPinnedObject(), password.Length * 2);
        gch.Free();

Decryption 解密

GCHandle gch2 = GCHandle.Alloc(password, GCHandleType.Pinned);

        // Decrypt the file
        EncryptionDecryption.FileDecrypt(encryptedFilePath, outputPath, password);

        // To increase the security of the decryption, delete the used password from the memory !
        EncryptionDecryption.ZeroMemory(gch2.AddrOfPinnedObject(), password.Length * 2);
        gch2.Free();

I got it resolved by removing all the AES properties to default and just keeping few. 我通过将所有AES属性删除为默认值并仅保留其中几个来解决了该问题。 Find the code below. 查找下面的代码。 Specially the padding fields. 特别是填充字段。

public static void FileEncrypt(string inputFile, string outputFile, string password, byte[] salt)
    {
        try
        {
            using (RijndaelManaged AES = new RijndaelManaged())
            {
                byte[] passwordBytes = ASCIIEncoding.UTF8.GetBytes(password);

                AES.KeySize = 256;
                AES.BlockSize = 128;

                var key = new Rfc2898DeriveBytes(passwordBytes, salt, 50000);
                AES.Key = key.GetBytes(AES.KeySize / 8);
                AES.IV = key.GetBytes(AES.BlockSize / 8);



                /* This is for demostrating purposes only. 
                 * Ideally you will want the IV key to be different from your key and you should always generate a new one for each encryption in other to achieve maximum security*/
                //byte[] IV = ASCIIEncoding.UTF8.GetBytes(skey);

                using (FileStream fsCrypt = new FileStream(outputFile, FileMode.Create))
                {
                    using (ICryptoTransform encryptor = AES.CreateEncryptor(AES.Key, AES.IV))
                    {
                        using (CryptoStream cs = new CryptoStream(fsCrypt, encryptor, CryptoStreamMode.Write))
                        {
                            using (FileStream fsIn = new FileStream(inputFile, FileMode.Open))
                            {
                                int data;
                                while ((data = fsIn.ReadByte()) != -1)
                                {
                                    cs.WriteByte((byte)data);
                                }
                                if (!cs.HasFlushedFinalBlock)
                                    cs.FlushFinalBlock();
                            }
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }
    public static void FileDecrypt(string inputFile, string outputFile, string password, byte[] salt)
    {
        try
        {
            using (RijndaelManaged AES = new RijndaelManaged())
            {
                //byte[] key = ASCIIEncoding.UTF8.GetBytes(password);

                /* This is for demostrating purposes only. 
                 * Ideally you will want the IV key to be different from your key and you should always generate a new one for each encryption in other to achieve maximum security*/
                //byte[] IV = ASCIIEncoding.UTF8.GetBytes(password);

                byte[] passwordBytes = ASCIIEncoding.UTF8.GetBytes(password);

                AES.KeySize = 256;
                AES.BlockSize = 128;

                var key = new Rfc2898DeriveBytes(passwordBytes, salt, 50000);
                AES.Key = key.GetBytes(AES.KeySize / 8);
                AES.IV = key.GetBytes(AES.BlockSize / 8);

                using (FileStream fsCrypt = new FileStream(inputFile, FileMode.Open))
                {
                    using (FileStream fsOut = new FileStream(outputFile, FileMode.Create))
                    {
                        using (ICryptoTransform decryptor = AES.CreateDecryptor(AES.Key, AES.IV))
                        {
                            using (CryptoStream cs = new CryptoStream(fsCrypt, decryptor, CryptoStreamMode.Read))
                            {
                                int data;
                                while ((data = cs.ReadByte()) != -1)
                                {
                                    fsOut.WriteByte((byte)data);
                                }
                                if (!cs.HasFlushedFinalBlock)
                                    cs.FlushFinalBlock();
                            }
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            // failed to decrypt file
        }
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 c# AES 解密错误并显示“填充无效且无法删除”。 - c# AES decryption errors with “Padding is invalid and cannot be removed.” C#:AES错误:填充无效,无法删除。 相同的钥匙和一切,帮助 - C#: AES error: Padding is invalid and cannot be removed. Same key and everything, help 使用Crypto-JS和C#解密的AES加密-避免“填充无效且无法删除。” - AES encryption with Crypto-JS and C# Decryption - avoiding “Padding is invalid and cannot be removed.” TRIPLEDES 填充无效且无法删除。 c#解密 - TRIPLEDES padding is invalid and cannot be removed. c# decrypt 解密AES给我“填充无效,无法删除。”错误 - Decrypting AES gives me “Padding is invalid and cannot be removed.” error AES解密失败,并显示“填充无效且无法删除” - AES decrypt fails with “Padding is invalid and cannot be removed” AES Android加密C#解密填充无效,无法删除 - AES Android Encryption C# decryption Padding is invalid and cannot be removed 不断收到“CryptographicException: Padding is invalid and cannot be removed”。 即使有填充,AES CBC 加密也会出错 - Keep getting “CryptographicException : Padding is invalid and cannot be removed.” errors with AES CBC encryption even with padding 填充无效,无法使用 AES 删除 - Padding is invalid and cannot be removed with AES AES 填充无效且无法移除 - AES Padding is Invalid And Cannot Be Removed
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM