У меня есть необходимость рассчитать размер файла, который я шифрую, используя Rijndael.
Согласно другим ответам на этом сайте и в Google, следующий правильный способ расчета длины зашифрованных данных:
EL = UL + (BS - (UL Mod BS) Mod BS)
Where:
EL = Encrypted Length
UL = Unencrypted Length
BS = Block Size
В моем случае длина незашифрованного файла составляет 5 101 972 байта , и я использую 128-битный ключ шифрования, что дает мне размер блока 16 байтов ,Следовательно, уравнение имеет вид:
EL = 5101972 + (16 - (5101972 Mod 16) Mod 16)
EL = 5101972 + (16 - 4 Mod 16)
EL = 5101972 + (12 Mod 16)
EL = 5101972 + 12
EL = 5101984
Предоставление зашифрованного файла длиной 5 101 984 байта .
Однако размер моего файла после шифрования составляет 5 242 896 А.огромная разница в размерах 140 912 байт!
Теперь .. Я, очевидно, что-то неправильно делаю, но не могу понять, что это такое.Ниже приведен мой тестовый код шифрования и дешифрования, а также метод, используемый для вычисления зашифрованного размера:
private static void Enc(string decryptedFileName, string encryptedFileName)
{
PasswordDeriveBytes passwordDB = new PasswordDeriveBytes("ThisIsMyPassword", Encoding.ASCII.GetBytes("thisIsMysalt!"), "MD5", 2);
byte[] passwordBytes = passwordDB.GetBytes(128 / 8);
using (FileStream fsOutput = File.OpenWrite(encryptedFileName))
{
using(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,Padding=PaddingMode.Zeros};
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(passwordBytes, IVBytes);
using (CryptoStream cryptoStream = new CryptoStream(fsOutput, encryptor, CryptoStreamMode.Write))
{
for (long i = 0; i < fsInput.Length; i += chunkSize)
{
byte[] chunkData = new byte[chunkSize];
int bytesRead = 0;
while ((bytesRead = fsInput.Read(chunkData, 0, chunkSize)) > 0)
{
cryptoStream.Write(chunkData, 0, chunkSize);
}
}
}
}
}
}
private static void Dec(string encryptedFileName, string decryptedFileName)
{
PasswordDeriveBytes passwordDB = new PasswordDeriveBytes("ThisIsMyPassword", Encoding.ASCII.GetBytes("thisIsMysalt!"), "MD5", 2);
byte[] passwordBytes = passwordDB.GetBytes(128 / 8);
using (FileStream fsInput = File.OpenRead(encryptedFileName))
{
using (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,Padding=PaddingMode.Zeros};
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(passwordBytes, IVBytes);
using (CryptoStream cryptoStream = new CryptoStream(fsOutput, decryptor, CryptoStreamMode.Write))
{
for (long i = 0; i < fsInput.Length; i += chunkSize)
{
byte[] chunkData = new byte[chunkSize];
int bytesRead = 0;
while ((bytesRead = fsInput.Read(chunkData, 0, chunkSize)) > 0)
{
cryptoStream.Write(chunkData, 0, bytesRead);
}
}
fsOutput.SetLength(fileLength);
}
}
}
}
private static void CalcEncSize(string decryptedFileName)
{
FileInfo fi = new FileInfo(decryptedFileName);
if (fi.Exists)
{
long blockSize = 128/8;
long fileLength = fi.Length;
long encryptedSize = fileLength + ((blockSize - (fileLength % blockSize)) % blockSize);
encryptedSize += 24; //16 bytes for the IV, and 8 more for the filelength, both stored at the start of the file.
Console.WriteLine("Estimated Encryption Size: " + encryptedSize.ToString());
}
}
Примечание. В вычислениях в начале я НЕ включаю дополнительные 24 байта, которые используютсяв самом начале зашифрованного файла, чтобы сохранить исходную длину файла и IV ... Я знаю это, но не хотел усложнять уравнение более, чем необходимо.