使用 AES 加密和解密文件会生成损坏的文件
本文关键字:文件 损坏 使用 加密 解密 AES | 更新日期: 2023-09-27 18:35:52
我正在尝试使用 AES 加密和解密文件。我遇到的问题是,当文件被解密时,它被破坏了,你无法打开它。原始文件的长度为 81.970 字节,解密文件的长度为 81.984 字节...所以由于某种原因增加了 14 个字节。问题可能在于文件的加密方式,但我不知道我做错了什么。
我在这里错过了什么?可能是我处理密码、iv 和填充的方式吗?
谢谢你的时间!
这是我用来加密的代码:
private AesManaged aesManaged;
private string filePathToEncrypt;
public Encrypt(AesManaged aesManaged, string filePathToEncrypt)
{
this.aesManaged = aesManaged;
this.filePathToEncrypt = filePathToEncrypt;
}
public void DoEncryption()
{
byte[] cipherTextBytes;
byte[] textBytes = File.ReadAllBytes(this.filePathToEncrypt);
using(ICryptoTransform encryptor = aesManaged.CreateEncryptor(aesManaged.Key, aesManaged.IV))
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cs.Write(textBytes, 0, textBytes.Length);
cs.FlushFinalBlock();
cipherTextBytes = ms.ToArray();
}
File.WriteAllBytes("EncryptedFile.aes", cipherTextBytes);
}
这是我用来解密的代码:
private AesManaged aesManaged;
private string filePathToDecrypt;
public Decrypt(AesManaged aesManaged, string filePathToDecrypt)
{
this.aesManaged = aesManaged;
this.filePathToDecrypt = filePathToDecrypt;
}
public void DoDecrypt()
{
byte[] cypherBytes = File.ReadAllBytes(this.filePathToDecrypt);
byte[] clearBytes = new byte[cypherBytes.Length];
ICryptoTransform encryptor = aesManaged.CreateDecryptor(aesManaged.Key, aesManaged.IV);
using (MemoryStream ms = new MemoryStream(cypherBytes))
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Read))
{
cs.Read(clearBytes, 0, clearBytes.Length);
clearBytes = ms.ToArray();
}
File.WriteAllBytes("DecryptedFile.gif", clearBytes);
}
以下是我调用函数的方式:
string filePathToEncrypt = "dilbert.gif";
string filePathToDecrypt = "EncryptedFile.aes";
string password = "Password";
string passwordSalt = "PasswordSalt";
Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(password, Encoding.ASCII.GetBytes(passwordSalt));
var aesManaged = new AesManaged
{
Key = deriveBytes.GetBytes(128 / 8),
IV = deriveBytes.GetBytes(16),
Padding = PaddingMode.PKCS7
};
Console.WriteLine("Encrypting File...");
var encryptor = new Encrypt(aesManaged, filePathToEncrypt);
encryptor.DoEncryption();
Thread.Sleep(300);
Console.WriteLine("Decrypting File...");
var decryptor = new Decrypt(aesManaged, filePathToDecrypt);
decryptor.DoDecrypt();
Thread.Sleep(300);
尝试:
public void DoEncryption()
{
byte[] cipherBytes;
byte[] textBytes = File.ReadAllBytes(this.filePathToEncrypt);
using (ICryptoTransform encryptor = aesManaged.CreateEncryptor(aesManaged.Key, aesManaged.IV))
using (MemoryStream input = new MemoryStream(textBytes))
using (MemoryStream output = new MemoryStream())
using (CryptoStream cs = new CryptoStream(output, encryptor, CryptoStreamMode.Write))
{
input.CopyTo(cs);
cs.FlushFinalBlock();
cipherBytes = output.ToArray();
}
File.WriteAllBytes("EncryptedFile.aes", cipherBytes);
}
和
public void DoDecrypt()
{
byte[] cypherBytes = File.ReadAllBytes(this.filePathToDecrypt);
byte[] textBytes;
using (ICryptoTransform decryptor = aesManaged.CreateDecryptor(aesManaged.Key, aesManaged.IV))
using (MemoryStream input = new MemoryStream(cypherBytes))
using (MemoryStream output = new MemoryStream())
using (CryptoStream cs = new CryptoStream(input, decryptor, CryptoStreamMode.Read))
{
cs.CopyTo(output);
textBytes = output.ToArray();
}
File.WriteAllBytes("DecryptedFile.gif", textBytes);
}
请注意,可以将代码修改为不使用临时byte[]
并直接读取/写入输入/输出流。
一般来说,你不能从密码文本的长度中分离出明文的长度,所以这一行:
new byte[cypherBytes.Length]
完全错了。
请不要在2016年使用Encoding.ASCII
。就像上个世纪一样。使用 Encoding.UTF8
支持非英语字符。
答案可能很简单。我不明白您尝试在哪里选择密码模式,因此默认情况下可能需要 CBC,因为 IV 已启动。然后,81.970 填充 14 个字节,可被 32 整除。因此,当它发生时,您分配的内存仅为 81.970,因此填充字节无法正确写入,导致某种内存泄漏,并且当启动解密时,取消填充无法正常工作。