Rijndael文件加密问题
本文关键字:问题 加密 文件 Rijndael | 更新日期: 2023-09-27 18:02:38
Rijndael文件加密问题
我想加密大文件使用Rijndael,但我得到内存异常错误。任何想法?这是我的代码
public void Rijndael_EncryptFile(string password, string filepath, int opt)
{
try
{
byte[] keyBytes;
keyBytes = Encoding.Unicode.GetBytes(password);
Rfc2898DeriveBytes derivedKey = new Rfc2898DeriveBytes(password, keyBytes);
RijndaelManaged rijndaelCSP = new RijndaelManaged();
rijndaelCSP.BlockSize = opt; //128 256
rijndaelCSP.KeySize = opt; //128 256
rijndaelCSP.Key = derivedKey.GetBytes(rijndaelCSP.KeySize / 8);
rijndaelCSP.IV = derivedKey.GetBytes(rijndaelCSP.BlockSize / 8);
rijndaelCSP.Mode = CipherMode.CFB;
rijndaelCSP.Padding = PaddingMode.Zeros;
ICryptoTransform encryptor = rijndaelCSP.CreateEncryptor();
FileStream inputFileStream = new FileStream(filepath, FileMode.Open, FileAccess.Read);
byte[] inputFileData = new byte[(int)inputFileStream.Length];
inputFileStream.Read(inputFileData, 0, (int)inputFileStream.Length);
FileStream outputFileStream = new FileStream(filepath + ".enc", FileMode.Create, FileAccess.Write);
CryptoStream encryptStream = new CryptoStream(outputFileStream, encryptor, CryptoStreamMode.Write);
encryptStream.Write(inputFileData, 0, (int)inputFileStream.Length);
encryptStream.FlushFinalBlock();
rijndaelCSP.Clear();
encryptStream.Close();
inputFileStream.Close();
outputFileStream.Close();
}
}
好吧,先说说你的实际问题。
将整个文件读入内存,加密,然后写入磁盘。大字节数组可能不适合内存(即使你有足够的"RAM")。
您应该一次读取一个数据块。这个块大小可能是16字节的倍数(AES块的大小),将其写入使用CryptoStream
,当您到达流的末尾时,关闭CryptoStream
,以便它应用任何填充。
好的,其他的
首先,不要使用RijndaelManaged
。使用AesManaged
。Rijndael是AES在被标准化为AES之前的名字。AES与Rijndael相同,除了AES不允许除128之外的块大小,所以不要更改块大小。唯一应该使用Rijndael的情况是,为了与现有系统兼容,您需要128位以外的块大小。
接下来,对于CFB模式,初始化向量应该是唯一的。IV不是秘密,您可以将其存储为纯文本和密文。不要从密码中导出它。最重要的是,静脉注射绝不能被重复使用。它也不需要是随机的。它可以是一个简单的递增计数器。请注意,对于其他AES模式,如CBC, IV应该是随机的。
您不需要将整个文件读入内存。最好的方法是每次从输入读取一个数据块,然后将该数据块写入输出。
类似于下面的内容,尽管我还没有测试下面的内容:
byte[] keyBytes;
keyBytes = Encoding.Unicode.GetBytes(password);
Rfc2898DeriveBytes derivedKey = new Rfc2898DeriveBytes(password, keyBytes);
RijndaelManaged rijndaelCSP = new RijndaelManaged();
// setup key parameters, i.e. IV, etc
ICryptoTransform encryptor = rijndaelCSP.CreateEncryptor();
using (FileStream inputFileStream = new FileStream(filepath, FileMode.Open, FileAccess.Read))
using (FileStream outputFileStream = new FileStream(filepath + ".enc", FileMode.Create, FileAccess.Write))
using (CryptoStream encryptStream = new CryptoStream(outputFileStream, encryptor, CryptoStreamMode.Write))
{
byte[] buffer = new byte[bufSize];
int readSize = 0;
while ((readSize = inputFileStream.Read(buffer, 0, buffer.Length)) > 0)
{
encryptStream.Write(buffer, 0, readSize);
}
encryptStream.FlushFinalBlock();
rijndaelCSP.Clear();
}
更新:删除初始化代码(从原始问题复制),因为它不安全