[英]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."
如果我第二次尝试,它将显示“填充无效且无法删除错误”。
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.