2013-05-08 3 views
2

Вот фрагмент моего кода, который должен шифровать файл и писать криптограф в новый файл. Код аналогичен примеру, найденному на веб-странице Microsoft MSDN.AES C# File Encryption - поток записывает только 16 байтов

byte[] inputBuffer = new byte[InputFileStream.Length]; 
byte[] outputBuffer = new byte[InputFileStream.Length]; 

InputFileStream.Read(inputBuffer, 0, (int)InputFileStream.Length); 

ICryptoTransform encryptor = AesInstance.CreateEncryptor(AesInstance.Key, AesInstance.IV); 


      using (MemoryStream memoryStream = new MemoryStream()) 
      { 

       using (CryptoStream stream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) 
       { 
        using (StreamWriter encrypted = new StreamWriter(stream)) 
        { 

         encrypted.Write(inputBuffer); 

        } 

        outputBuffer = memoryStream.ToArray(); 

        OutputFileStream.Write(outputBuffer, 0, (int)outputBuffer.Length); 


       } 

      } 

OutputFileStream.Close(); 
InputFileStream.Close();` 

Проблема заключается в том, что входной буфер считывает байты из файла, но выходной буфер, по-видимому, содержит только 16 байт данных. В результате выходной файл имеет только 16 байт, даже если входной файл был большим. Где ошибка? Проблема существует в различных режимах, ECB, CBC и т.д.

+0

Не беспокойтесь о том, что обеспечивается в логике программы. –

ответ

0

Я верю, что когда вы используете

encrypted.Write(inputBuffer); 

вы не даете писатель размера буфера для записи.

+0

inputBuffer является байтовым [] типом, поэтому я думаю, что не нужно указывать размер буфера, не так ли? –

+1

Основная проблема заключается в том, что 'StreamWriter' является подклассом' TextStream', и вы не можете записать в него 'byte []' buffer. Вместо этого используйте «MemoryStream» и укажите размер буфера для функции «Write», и вам должно быть хорошо идти! –

0

Многие потоки выполняют буферизацию, особенно криптографические и сжатые потоки. Не вызывайте ToArray на MemoryStream до тех пор, пока вы не закроете/не удалите криптовый поток.

  using (CryptoStream stream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) 
      { 
       using (StreamWriter encrypted = new StreamWriter(stream)) 
       { 
        encrypted.Write(inputBuffer); 
       } 
      } 
      OutputFileStream.Write(memoryStream.GetBuffer(), 
       0, (int)memoryStream.Length); 
     } 

Чтобы быть еще более ясным, полностью теряют MemoryStream и просто создать криптографический поток поверх OutputFileStream - это будет работать хорошо, даже с огромными данными.

+0

Спасибо за ваш ответ. К сожалению, у меня есть необработанное исключение «Невозможно получить доступ к закрытому потоку» в строке с memoryStream.Lenght. Кроме того, когда я отменил memoryStream и использовал только CryptoStream, я все равно получаю только 16bytes на выходе –

+0

@Anna hmm .... Имеет ли конструктор криптопотока собственный/не собственный внутренний поток? –

+0

Конструктор cryptoStream AFAIK получает только один поток в качестве параметра, «поток, на котором выполняется криптографическое преобразование». Я думаю, что может быть проблема с потоками очистки, но IDK, как это исправить, при использовании файлов ... –

0

Хорошо, теперь исправлено. Благодаря ответу Марка, я понял, как он должен работать. Вот рабочий код, если кто-нибудь понадобится позже:

  InputFileStream.Read(inputBuffer, 0, (int)InputFileStream.Length); 
      InputFileStream.Flush(); 
      InputFileStream.Close(); 

      using (MemoryStream msEncrypt = new MemoryStream(outputBuffer)) 
      { 
       using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) 
       { 
        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) 
        { 
         swEncrypt.Write(inputBuffer); 
         swEncrypt.Flush(); 
         swEncrypt.Close(); 
        } 
        csEncrypt.Flush(); 
        csEncrypt.Close(); 
       } 
       OutputFileStream.Write(outputBuffer, 0, (int)outputBuffer.Length); 
       OutputFileStream.Flush(); 
       OutputFileStream.Close(); 
      } 

Может быть, это не идеальный код (я знаю, что это может быть излишним), но он отлично работает даже для больших файлов.

0

Этот вопрос довольно старый, но он заслуживает лучшего объяснения. Проблема скрыта в самом StreamWriter. Этот класс следует использовать для записи текста в поток. Однако inputBuffer не является текстом. Это байтовый массив!

encrypted.Write(inputBuffer);

равно

encrypted.Write(inputBuffer.ToString());

Согласно MSDN StreamWriter.Write(object):

Записывает текстовое представление объекта в текстовой строке или потока путем вызова ToString метод на этом объекте.

Правильное решение записать входной буфер непосредственно в CryptoStream:

using (MemoryStream msEncrypt = new MemoryStream(outputBuffer)) 
{ 
    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) 
    { 
     csEncrypt.Write(inputBuffer, 0, inputBuffer.Length); 
    } 
    return msEncrypt.ToArray(); 
}