c# - 如何使用 AES256 算法从多页文件中提取单个解密页面
问题描述
我创建了一个 Winform 测试应用程序,用于检查AES256加密/解密是否适用于大文件。
我有一个包含多个页面的单个文本文件,它的大小为 7.32GB,总页数为 180 万。
我正在尝试使用 AES256 算法加密和解密这个多页文本文件。
目前加密需要 3 分钟,解密需要将近 3 分钟。但我有以下担忧,
“所以如果我们想从该文档中提取单个页面,我们是否需要完全解密它?或者有什么方法可以让我们访问文件的各个部分而不会产生开销? ”
我使用了以下代码:
加密:
public static void Encrypt(string password, string inputFile, string outputFile)
{
//http://stackoverflow.com/questions/27645527/aes-encryption-on-large-files
//generate random salt
byte[] salt = GenerateRandomSalt();
//create output file name
FileStream fsCrypt = new FileStream(inputFile + ".aes", FileMode.Create);
//convert password string to byte arrray
byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes(password);
//Set AES symmetric encryption algorithm
AesManaged AES = new AesManaged();
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Padding = PaddingMode.PKCS7;
//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.ECB;
// write salt to the begining of the output file, so in this case can be random every time
fsCrypt.Write(salt, 0, salt.Length);
CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write);
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
{
cs.Close();
fsCrypt.Close();
}
//using (FileStream infs = File.OpenRead(inputfile))
//using (FileStream outfs = File.Create(outputfile))
// Encrypt(password, infs, outfs);
}
解密:
public static void Decrypt(string password, string inputFile, string outputFile)
{
byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes(password);
byte[] salt = new byte[32];
FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
fsCrypt.Read(salt, 0, salt.Length);
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.ECB;
CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateDecryptor(), CryptoStreamMode.Read);
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);
}
}
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();
}
}
如果可能的话,请提出一种实现它的方法。
解决方案
推荐阅读
- google-cloud-platform - 使用 Google ML Engine 的预测时出现 ExpirationError
- java - 当 Marionette 通过 Selenium 3.12.0 变为 false 时,无法找到与 Firefox 匹配的一组功能
- session - Azure 服务总线 - 会话将消息复制到多个实例
- python - 使用 Pandas 和 SQLAlchemy 时出错
- angular - Angular 6 - HttpInterceptors - HttpResponse 正文没有被修改
- vue.js - 如何确认我使用的是 Vue 的“完整版本”?
- microsoft-graph-api - 使用 Microsoft Graph 登录的用户的图像 URL
- excel - Excel中具有搜索功能的多个IF语句
- php - 从 php 中的图像标签中过滤图像名称
- python - ImportError:没有名为“tensorflow.core”的模块