首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rijndael文件加密问题

Rijndael文件加密问题
EN

Stack Overflow用户
提问于 2016-08-15 21:37:47
回答 2查看 235关注 0票数 0

Rijndael文件加密问题

我想使用Rijndael加密大文件,但出现内存不足异常错误。有什么想法吗?以下是我的代码

代码语言:javascript
复制
     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();
        }
    }
EN

回答 2

Stack Overflow用户

发布于 2016-08-15 21:49:37

好的,首先是你的实际问题。

您将整个文件读入内存,对其进行加密,然后将其写入磁盘。一个大的字节数组可能不适合内存(即使你有足够的"RAM")。

相反,您应该一次读取一块数据。此块大小可能是16字节( AES块的大小)的倍数,将其写入使用CryptoStream,当您到达流的末尾时,关闭CryptoStream,以便它应用任何填充。

好的,还有其他的事情。

首先,不要使用RijndaelManaged。使用AesManaged。Rijndael是AES被标准化为AES之前的名称。AES与Rijndael相同,不同之处在于AES不允许块大小超过128,因此不要更改块大小。只有当您需要与现有系统兼容的块大小不是128位时,才应该使用Rijndael。

接下来,您的初始化向量对于CFB模式应该是唯一的。IV不是秘密,您可以将其与密文一起存储在明文中。不要从密码派生它。至关重要的是,静脉注射绝不能重复使用。它也不需要是随机的。它可以是一个简单的递增计数器。请注意,对于AES的其他模式,如CBC,IV应该是随机的。

票数 2
EN

Stack Overflow用户

发布于 2016-08-15 21:49:53

您不需要将整个文件读取到内存中。最好的方法是一次从输入读取一块数据,并将该块写入输出。

类似于下面的代码,尽管我还没有测试下面的代码:

代码语言:javascript
复制
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();
}

更新:删除了初始化代码(从原始问题中复制),因为它不安全。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38956156

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档