2015-03-13 4 views
1

Я следую за MSDN Example of Rijndael Encryption, только чтобы я хотел был зашифровать и вернуть поток.Использование StreamWriter для записи в потоке (для шифрования большого потока)

Следующие не работают.

Это не исключение, но после прохождения кода, возвращаемое значение не имеет данных.

 public static Stream EncryptStream(Stream plainStream, byte[] Key, byte[] IV) 
     { 

      var encrypted = new MemoryStream() 

      // Create an RijndaelManaged object 
      // with the specified key and IV. 
      using (RijndaelManaged rijAlg = new RijndaelManaged()) 
      { 
       rijAlg.Key = Key; 
       rijAlg.IV = IV; 

       // Create a decrytor to perform the stream transform. 
       ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV); 

       // Create the streams used for encryption. 
       using (MemoryStream msEncrypt = new MemoryStream()) 
       { 
        using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) 
        { 
         using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) 
         { 

          //Write all data to the stream. 
          swEncrypt.Write(plainStream); 
         } 
         msEncrypt.CopyTo(encrypted); 
        } 
       } 
      } 
      return encrypted; 


     } 

Я смотрел на documentation for the Stream.Writer class, думая, что это что-то делать с ним не поддерживает запись в поток.

Я заметил, что есть параметр типа «объект», поэтому я предполагаю, что это сработает ... Это правильно? Если нет, как мне это сделать?

Я передаю ему FileStream, кстати. Выполняя код, plainStream содержит данные.

+0

@AlexeiLevenkov Я не просил о «заходящего положении». Если это решение, я не мог знать, что это как-то связано с «установкой позиции» – user919426

+0

@AlexeiLevenkov, на самом деле это не решает проблему. Если вы проигнорируете вызов CopyTo() и посмотрите на msEncrypt (поток), он не содержит данных. Попробуй. – user919426

+0

@ user919426 Что делать, если вы выполняете 'msEncrypt.CopyTo (зашифрованный);' после удаления 'csEncrypt', все еще дает вам проблемы? – mishamosher

ответ

2

Вот некоторые пример функции для шифрования и дешифрования от и потоков (заменить Algo на тот, который вы предпочитаете):

public static void Decrypt(Stream input, Stream output, byte[] key, byte[] iv) 
{ 
    using (SymmetricAlgorithm algo = SymmetricAlgorithm.Create()) // Creates the default implementation, which is RijndaelManaged. 
    { 
     using (CryptoStream stream = new CryptoStream(input, algo.CreateDecryptor(key, iv), CryptoStreamMode.Read)) 
     { 
      byte[] bytes = new byte[16]; 
      int read; 
      do 
      { 
       read = stream.Read(bytes, 0, bytes.Length); 
       output.Write(bytes, 0, read); 
      } 
      while (read > 0); 
     } 
    } 
} 

public static void Encrypt(Stream input, Stream output, byte[] key, byte[] iv) 
{ 
    using (SymmetricAlgorithm algo = SymmetricAlgorithm.Create()) //Creates the default implementation, which is RijndaelManaged. 
    { 
     using (CryptoStream stream = new CryptoStream(output, algo.CreateEncryptor(key, iv), CryptoStreamMode.Write)) 
     { 
      byte[] bytes = new byte[16]; 
      int read; 
      do 
      { 
       read = input.Read(bytes, 0, bytes.Length); 
       stream.Write(bytes, 0, read); 
      } 
      while (read > 0); 
     } 
    } 
} 

Вы можете использовать их с любым выходным потоком. Если вы хотите записать в большой поток вывода, вы можете напрямую использовать этот выходной поток (например, FileStream или ASP.NET Response.OutputStream и т. Д.), Вы не должны использовать промежуточный MemoryStream, который будет потреблять память без реальной цели ,

Это, как говорится, если вы действительно хотите использовать MemoryStream, вы могли бы сделать это следующим образом:

MemoryStream output = new MemoryStream(); 
Encrypt(input, output, key, iv); 
output.Position = 0; // rewind the stream, so you can use it from the beginning 
+0

Спасибо Саймон. У меня есть один быстрый вопрос о том, почему вы выбрали то, что я предполагаю, это буфер (byte [] bytes = byte [16]) Есть ли какое-либо отношение этого к моей фактической длине буфера данных? – user919426

+0

О, это то, что я перенес из старой части кода.Фактически вы можете/должны поставить более высокое значение для повышения производительности (например, 65536, например, если ваш поток большой). Удостоверьтесь, что он не больше 85K (http://stackoverflow.com/questions/8951836/why-large-object-heap-and-why-do-we-care) –

+0

Исключено, когда оно попадает в удаляющуюся скобу из 'using (CryptoStream'. Он говорит: «Длина данных для шифрования недопустима». Попробует заставить его работать – user919426

1

Использовать копию уровня потока для копирования содержимого одного потока в другой или использовать соответствующую пару считывателей/писателей (например, TextReader/TextWriter) - если вы смешиваете, скорее всего, получите неправильный результат. То есть Уровень потока копия:

plainStream.CopyTo(csEncrypt); 

Кроме собственно записи данных в зашифрованном поток (вместо имени типа из plainStream, которые вы получаете из-за StreamWrite.Write(Object) вызова), вы должны использовать MemoryStream.ToArray скопировать полученный контент - в противном случае вы получаете " исключение объекта ».

Скопируйте код должен выглядеть так вместо msEncrypt.CopyTo(encrypted);

var bytes = msEncrypt.ToArray(); 
encrypted.Write(bytes, 0, bytes.Length); 
+0

Спасибо за подробное объяснение. Помеченный Саймон как ответ из-за детализации реализации, но ничего не отвлекающий от вашего хорошего объяснения. – user919426

Смежные вопросы