有这样的加密和覆盖文件的方法
private static byte[] Encrypt(byte[] fileData, byte[] key, byte[] salt)
{
using (Aes aes = Aes.Create())
{
using (Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(key, salt, 10000))
{
aes.Key = rfc2898.GetBytes(aes.KeySize / 8);
}
aes.GenerateIV();
byte[] iv = aes.IV;
using (MemoryStream encryptedStream = new MemoryStream())
{
encryptedStream.Write(salt, 0, salt.Length);
encryptedStream.Write(iv, 0, iv.Length);
using (CryptoStream cryptoStream = new CryptoStream(encryptedStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cryptoStream.Write(fileData, 0, fileData.Length);
cryptoStream.FlushFinalBlock();
}
byte[] encryptedData = encryptedStream.ToArray();
return encryptedData;
}
}
}
public void EncryptFile(string filePath, byte[] key, byte[] salt)
{
byte[] data = File.ReadAllBytes(filePath);
byte[] encryptedData = Encrypt(data, key, salt);
using (FileStream encryptedFileStream = new FileStream(filePath, FileMode.Create))
{
encryptedFileStream.Write(encryptedData, 0, encryptedData.Length);
}
Console.WriteLine($"Файл {filePath} был успешно зашифрован.");
data = null;
encryptedData = null;
GC.Collect();
}
以及解密和覆盖文件的方法
private static byte[] Decrypt(byte[] encryptedData, byte[] key, byte[] salt)
{
using (Aes aes = Aes.Create())
{
using (Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(key, salt, 10000))
{
aes.Key = rfc2898.GetBytes(aes.KeySize / 8);
}
byte[] iv = new byte[aes.IV.Length];
Buffer.BlockCopy(encryptedData, salt.Length, iv, 0, iv.Length);
aes.IV = iv;
using (MemoryStream encryptedStream = new MemoryStream(encryptedData, salt.Length + iv.Length, encryptedData.Length - salt.Length - iv.Length))
using (MemoryStream decryptedStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(encryptedStream, aes.CreateDecryptor(), CryptoStreamMode.Read))
{
cryptoStream.CopyTo(decryptedStream);
}
byte[] decryptedData = decryptedStream.ToArray();
return decryptedData;
}
}
}
public void DecryptFile(string filePath, byte[] key, byte[] salt)
{
byte[] encryptedData = File.ReadAllBytes(filePath);
byte[] decryptedData = Decrypt(encryptedData, key, salt);
using (MemoryStream decryptedStream = new MemoryStream(decryptedData))
{
using (FileStream fs = new FileStream(filePath, FileMode.Create))
{
decryptedStream.CopyTo(fs);
}
}
Console.WriteLine($"Файл {filePath} был успешно расшифрован.");
encryptedData = null;
decryptedData = null;
GC.Collect();
}
而我的问题是,当你开始加密一个200mb的目录过程时,使用了大约700mb的RAM,但在后续操作过程中,使用的内存没有增加或减少,这是否正常。也就是说,好像有一块保留内存是在第一次操作时分配的,之后用于所有后续操作,这是正常的,还是我的代码存在内存泄漏?
您只需要停止将所有数据完全加载到内存中即可。
这段代码不会吃掉一千字节的额外内存,因为原则上它不会将文件的内容完全读入内存。
在图像和相似性上更进一步。
扔掉多余的。准备好。您至少可以加密 40 GB 重量的电影,而不会增加内存消耗。
盐不用大惊小怪,随便放一个就很适合她的角色
IV。这不会以任何方式降低加密的安全性,恰恰相反,您不必在任何地方存储或硬编码这种盐。像这样尝试垃圾收集:
如果我没理解错的话,默认
GC是不压缩LOB堆的,因为这需要相当长的时间。它只是将大对象占用的空间标记为可重用,然后这个空间实际用于新对象。如果你不走运,首先创建了一个较小的对象,然后创建了一个较大的对象,那么运行时环境将保留这两个对象的空间,就好像被占用一样。但是,如果新对象适合这个总空间,则已经占用的空间将不会增长。一般来说,建议不要从事业余活动,不要
GC手动调用。除非您有一些时间紧迫的操作,并且您希望确保GC在这些操作之前开始工作,而不是在一些随机的、不方便的时间进行。好吧,或者如果你需要在不需要的时候尽量不要用内存占用程序。那些。当程序一直挂在内存中,而这些函数并不是一直起作用,而是间隔很长时间时,那么如果你需要为其他程序释放内存就有意义了。