2016-12-04 114 views
1

有一种编码输入流的方法(版本1),并且存在成功解码编码数据的函数Decrypt()。但是,当输入数据很大时,可能会出现错误OutOfMemory(行“string textEncrypted = Convert.ToBase64String(ms.ToArray())”)。在C#中将CryptoStream编码为Base64字符串#

版本1

private static Stream EncryptRijndael1(byte[] key, byte[] iv, Stream plainText) 
    { 
     if (plainText == null) 
      return null; 

     byte[] bytesEncrypted; 

     RijndaelManaged rjndl = RijndaelManagedWithConfig(key, iv); 

     using (MemoryStream ms = new MemoryStream()) 
     { 
      using (CryptoStream cs = new CryptoStream(ms, rjndl.CreateEncryptor(key, iv), CryptoStreamMode.Write)) 
      { 
       byte[] buffer = new byte[16 * 1024]; 
       int readed; 
       while ((readed = (plainText.Read(buffer, 0, buffer.Length))) > 0) 
       { 
        cs.Write(buffer, 0, readed); 
       } 
      } 
      string textEncrypted = Convert.ToBase64String(ms.ToArray()); 
      bytesEncrypted = Encoding.ASCII.GetBytes(textEncrypted); 
     } 
     return new MemoryStream(bytesEncrypted); 
    } 

所以我修改以处理由部分(组块)的阵列部分中的方法。 这是版本2。它会导致错误“偏移量和长度必须引用行Convert.ToBase64String(ms.ToArray(),offset,read)中的字符串”“中的位置。

版本2

private static Stream EncryptRijndael2(byte[] key, byte[] iv, Stream plainText) 
    { 
     if (plainText == null) 
      return null; 

     byte[] bytesEncrypted; 

     RijndaelManaged rjndl = RijndaelManagedWithConfig(key, iv); 

     string textEncrypted = String.Empty; 

     using (MemoryStream ms = new MemoryStream()) 
     { 
      using (CryptoStream cs = new CryptoStream(ms, rjndl.CreateEncryptor(key, iv), CryptoStreamMode.Write)) 
      { 
       byte[] buffer = new byte[16 * 1024]; 
       int readed; 
       int offset = 0; 
       while ((readed = (plainText.Read(buffer, 0, buffer.Length))) > 0) 
       { 
        cs.Write(buffer, 0, readed); 
        textEncrypted += Convert.ToBase64String(ms.ToArray(), offset, readed); 
        offset += readed; 
       } 
      } 

      bytesEncrypted = Encoding.ASCII.GetBytes(textEncrypted); 

     } 

     return new MemoryStream(bytesEncrypted); 
    } 

然后,我做出版本3。它的工作原理没有错误,但输出数据长度现在大于具有相同输入数据的版本1。 Decryt()函数引发错误“输入不是有效的Base-64字符串,因为它包含非基本64字符,多于两个填充字符或填充字符中的非法字符。”

版本3

private static Stream EncryptRijndael3(byte[] key, byte[] iv, Stream plainText) 
    { 
     if (plainText == null) 
      return null; 

     byte[] bytesEncrypted; 

     RijndaelManaged rjndl = RijndaelManagedWithConfig(key, iv); 

     using (MemoryStream ms = new MemoryStream()) 
     { 
      string textEncrypted = String.Empty; 
      using (CryptoStream cs = new CryptoStream(ms, rjndl.CreateEncryptor(key, iv), CryptoStreamMode.Write)) 
      { 
       byte[] buffer = new byte[16*1024]; 
       int readed; 
       while ((readed = (plainText.Read(buffer, 0, buffer.Length))) > 0) 
       { 
        cs.Write(buffer, 0, readed); 
       } 
      } 


       byte[] buffer1 = new byte[16*1024]; 
       int readed1; 
       using (MemoryStream ms1 = new MemoryStream(ms.ToArray())) 
       { 
        while ((readed1 = (ms1.Read(buffer1, 0, buffer1.Length))) > 0) 
        { 
         if (readed1 < buffer1.Length) 
         { 
          var lastBuf = new List<Byte>(); 
          for (int i = 0; i < readed1; i++) 
          { 
           lastBuf.Add(buffer1[i]); 
          } 
          textEncrypted += Convert.ToBase64String(lastBuf.ToArray()); 
          continue; 
         } 
         textEncrypted += Convert.ToBase64String(buffer1); 
        } 
       } 

      bytesEncrypted = Encoding.ASCII.GetBytes(textEncrypted); 
     } 

     return new MemoryStream(bytesEncrypted); 
    } 

我RijndaelManaged的

private static RijndaelManaged RijndaelManagedWithConfig(byte[] key, byte[] iv) 
    { 
     RijndaelManaged rjndl = new RijndaelManaged(); 
     rjndl.KeySize = 256; 
     rjndl.BlockSize = 128; 

     rjndl.Key = key; 
     rjndl.IV = iv; 

     rjndl.Mode = CipherMode.CBC; 
     rjndl.Padding = PaddingMode.PKCS7; 

     return rjndl; 
    } 

请帮我摆脱错误的或者告诉我如何使版本1的过程Convert.ToBase64String数据部分

+0

多大你的数据的决定吗?大多数机器可以处理2Gb文件的加密。 –

+0

不,我尝试编码300 Mb输入数据 –

+0

300Mb对于现代机器(通常具有4-16Gb的RAM)毫无用处。 –

回答

0

我已经实现

  private static Stream EncryptRijndael(byte[] key, byte[] iv, Stream plainText) 
    { 
     if (plainText == null) 
      return null; 

     byte[] buffer = new byte[5120 * 1024]; 

     RijndaelManaged rjndl = RijndaelManagedWithConfig(key, iv); 

     using (var memoryStream = new MemoryStream()) 
     { 
      int readedBytes; 
      using (var cs = new CryptoStream(memoryStream, rjndl.CreateEncryptor(key, iv), CryptoStreamMode.Write)) 
      { 
       while ((readedBytes = (plainText.Read(buffer, 0, buffer.Length))) > 0) 
       { 
        cs.Write(buffer, 0, readedBytes); 
       } 
      } 


      using (var cryptoMemoryStream = new MemoryStream(memoryStream.ToArray())) 
      { 
       using (var base64MemoryStream = new MemoryStream()) 
       { 
        using (ICryptoTransform transform = new ToBase64Transform()) 
        { 
         using (var cryptStream = new CryptoStream(base64MemoryStream, transform, CryptoStreamMode.Write)) 
         { 
          while ((readedBytes = cryptoMemoryStream.Read(buffer, 0, buffer.Length)) > 0) 
          { 
           cryptStream.Write(buffer, 0, readedBytes); 
          } 
          cryptStream.FlushFinalBlock(); 
         } 

         return new MemoryStream(base64MemoryStream.ToArray()); 
        } 
       } 
      } 
     } 
    }