Ваша проблема начинается с использования StreamWriter в шифровании.Он предназначен для написания текстового файла, а не произвольного файла.Когда вы вызываете sw.Write (content), он просто вызывает content.ToString (), который возвращает «System.Byte []» вместо того, что вы, вероятно, ожидаете, каждый байт массива.Чтобы это исправить, просто напишите CryptoStream, не нужно использовать StreamWriter, например:
using (var rijAlg = new AesCng())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
ICryptoTransform encryptor = rijAlg.CreateEncryptor();
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cs.Write(content, 0, content.Length);
}
contentEnc = ms.ToArray();
}
}
Вы, наверное, заметили, что я использовал AesCng вместо RijndaelManaged.Зачем?Потому что в моем тесте это намного быстрее, и если вам не нужен нестандартный блок, использование RijndaelManaged не дает никаких преимуществ.Кроме того, я использую CreateEncryptor без параметров, потому что вы уже установили Key & IV в предыдущих строках.
То же самое в расшифровке.Вы не должны рассматривать их как текст, таким образом:
var buffer = new byte[content.Length]; //at first its size is actual size+padding
using (var rijAlg = new AesCng())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
ICryptoTransform decryptor = rijAlg.CreateDecryptor();
using (MemoryStream ms = new MemoryStream(content))
{
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
var actualSize = cs.Read(buffer, 0, content.Length);
//we write the decrypted content to the buffer, and get the actual size
Array.Resize(ref buffer, actualSize);
//then we resize the buffer to the actual size
}
}
}
return buffer;
Кроме того, использование вами Enc и Dec излишне сложно.Он уже способен обрабатывать весь файл сам по себе.Поэтому, чтобы зашифровать файл, просто используйте
var original = File.ReadAllBytes("originalPath");
var enc = Enc(original, rM.Key, rM.IV);
File.WriteAllBytes("encryptedPath", enc);
А чтобы расшифровать файл, просто используйте
var enc = File.ReadAllBytes("encryptedPath");
var dec = Dec(enc, rM.Key, rM.IV);
File.WriteAllBytes("decryptedPath", dec);
Как видите, я выбрасываю fileLength, filepath, chunkSize иbytesToRead на Enc & Dec, потому что ваш текущий код на самом деле не использует их в любом случае.Я пробовал код с коротким текстовым файлом на ASCII, Unicode и UTF-8, а также с большими двоичными файлами, все они успешно зашифрованы и расшифрованы с идентичным хешем для окончательно расшифрованных файлов.
Редактировать:
Превращение кода в дело прямой записи файлового потока на самом деле делает все намного проще.
public static void Transform(string source, string target, ICryptoTransform transf)
{
var bufferSize = 65536;
var buffer = new byte[bufferSize];
using (var sourceStream = new FileStream(source, FileMode.Open))
{
using (var targetStream = new FileStream(target, FileMode.OpenOrCreate))
{
using (CryptoStream cs = new CryptoStream(targetStream, transf, CryptoStreamMode.Write))
{
var bytesRead = 0;
do
{
bytesRead = sourceStream.Read(buffer, 0, bufferSize);
cs.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
}
}
}
}
public static void Enc(string source, byte[] Key, byte[] IV, string target)
{
using (var rijAlg = new AesCng())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
ICryptoTransform encryptor = rijAlg.CreateEncryptor();
Transform(source, target, encryptor);
}
}
public static void Dec(string source, byte[] Key, byte[] IV, string target)
{
using (var rijAlg = new AesCng())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
ICryptoTransform decryptor = rijAlg.CreateDecryptor();
Transform(source, target, decryptor);
}
}
Использование:
Enc(@"originalPath", key, iv, @"encryptedPath");
Dec(@"encrypedPath", key, iv, @"decryptedPath");