Я нахожусь в ситуации, когда мне нужно надежно зашифровать / расшифровать файл n длины, в идеале с использованием Rijndael, но определенно с 256-битным шифрованием.
Я играл с шифрованием раньше и довольно счастливо зашифровал / расшифровал строки и байтовые массивы.
Однако, поскольку я не знаю размер файла (и вполне возможно, что рассматриваемые файлы могут быть довольно большими (~ 2,5 ГБ)), я не могу просто загрузить их в байтовый массив и зашифровать / расшифровать их в один, как у меня раньше.
Итак, после небольшого прочтения в Google, я понял, что ответом было зашифровать и расшифровать файл кусками, и поэтому я создал следующий код:
private static void Enc(string decryptedFileName, string encryptedFileName)
{
FileStream fsOutput = File.OpenWrite(encryptedFileName);
FileStream fsInput = File.OpenRead(decryptedFileName);
byte[] IVBytes = Encoding.ASCII.GetBytes("1234567890123456");
fsOutput.Write(BitConverter.GetBytes(fsInput.Length), 0, 8);
fsOutput.Write(IVBytes, 0, 16);
RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC};
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(passwordDB.GetBytes(256 / 8), IVBytes);
CryptoStream cryptoStream = new CryptoStream(fsOutput, encryptor, CryptoStreamMode.Write);
for (long i = 0; i < fsInput.Length; i += chunkSize)
{
byte[] chunkData = new byte[chunkSize];
fsInput.Read(chunkData, 0, chunkSize);
cryptoStream.Write(chunkData, 0, chunkData.Length);
}
cryptoStream.Close();
fsInput.Close();
fsInput.Dispose();
cryptoStream.Dispose();
}
private static void Dec(string encryptedFileName, string decryptedFileName)
{
FileStream fsInput = File.OpenRead(encryptedFileName);
FileStream fsOutput = File.OpenWrite(decryptedFileName);
byte[] buffer = new byte[8];
fsInput.Read(buffer, 0, 8);
long fileLength = BitConverter.ToInt64(buffer, 0);
byte[] IVBytes = new byte[16];
fsInput.Read(IVBytes, 0, 16);
RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC };
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(passwordDB.GetBytes(256 / 8), IVBytes);
CryptoStream cryptoStream = new CryptoStream(fsOutput,decryptor,CryptoStreamMode.Write);
for (long i = 0; i < fsInput.Length; i += chunkSize)
{
byte[] chunkData = new byte[chunkSize];
fsInput.Read(chunkData, 0, chunkSize);
cryptoStream.Write(chunkData, 0, chunkData.Length);
}
cryptoStream.Close();
cryptoStream.Dispose();
fsInput.Close();
fsInput.Dispose();
}
Все это "хорошо" выглядит для меня, но, к сожалению, выглядит обманчиво!
Шифрование работает без ошибок, но во время дешифрования метод cryptoStream.Close () выдает следующее исключение:
System.Security.Cryptography.CryptographicException
Сообщение было обработано
недействительный и не может быть удален. "
Source = "mscorlib" StackTrace:
в System.Security.Cryptography.RijndaelManagedTransform.DecryptData (Byte []
inputBuffer, Int32 inputOffset, Int32
inputCount, Byte [] & outputBuffer,
Int32 outputOffset, PaddingMode
paddingMode, Boolean fLast)
в System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock (Byte []
inputBuffer, Int32 inputOffset, Int32
inputCount)
в System.Security.Cryptography.CryptoStream.FlushFinalBlock ()
at System.Security.Cryptography.CryptoStream.Dispose (Boolean
утилизации)
в System.IO.Stream.Close ()
Также представляется, что размер незашифрованного файла не соответствует ожидаемому размеру файла (в диапазоне от около 8 байт до около 60)
Я «исправил» исключение, изменив строки создания объекта RijndaelManaged для включения типа заполнения, как показано ниже:
RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC,Padding=PaddingMode.None };
Но размеры файлов по-прежнему не совпадают, и, как и ожидалось, только что незашифрованный файл - вздор!
Я признаю, что теперь я за пределами своей зоны комфорта с шифрованием / дешифрованием, и это, вероятно, ошибка новичка - но я не могу это обнаружить!
Любая помощь в решении этой проблемы будет принята с благодарностью!