计算的加密文件大小与真实大小不符

发布于 2024-09-11 15:01:10 字数 4194 浏览 3 评论 0原文

我需要计算使用 Rijndael 加密的文件的大小。

根据本网站和谷歌上的其他答案,以下是计算加密数据长度的正确方法:

EL = UL + (BS - (UL Mod BS) Mod BS)

Where: 
EL = Encrypted Length
UL = Unencrypted Length
BS = Block Size

在我的实例中,未加密文件长度为 5,101,972 字节,并且我使用 128 位加密key,给我一个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...我知道这一点,但不想使方程变得不必要的复杂化。

I have the need to calculate the size of a file I am encrypting using Rijndael.

According to other answers on this site, and on google, the following is the correct way of calculating encrypted data length:

EL = UL + (BS - (UL Mod BS) Mod BS)

Where: 
EL = Encrypted Length
UL = Unencrypted Length
BS = Block Size

In my instance, the unencrypted file length is 5,101,972 bytes, and I am using a 128bit encryption key, giving me a block size of 16 bytes.
Therefore, the equation is:

EL = 5101972 + (16 - (5101972 Mod 16) Mod 16)
EL = 5101972 + (16 - 4 Mod 16)
EL = 5101972 + (12 Mod 16)
EL = 5101972 + 12
EL = 5101984

Giving an encrypted file length of 5,101,984 bytes.

However, the size of my file after encryption weighs in at 5,242,896
A massive difference in sizes of 140,912 bytes!

Now.. I'm obviously doing SOMETHING wrong, but I can't work out what it is.
Below is my encryption and decryption test code, as well as the method used to calculate the encrypted size:

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());           
    }
}

Note: In the calculations at the start, I am NOT including the extra 24 bytes that are used at the start of the encrypted file by myself to store the original file length, and the IV... I know this, but didn't want to complicate the equation more than necessary.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

鸢与 2024-09-18 15:01:10

在实际加密过程之前,不应写入输出文件。 CryptoStream 将在关闭时处理所有必要的填充。此外,for 循环不是必需的,因为内部 while 循环将读取整个文件。另外,您应该只写入从文件中读取的内容。尝试这些改变。

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");

            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))
            {
                byte[] chunkData = new byte[chunkSize];
                int bytesRead = 0;
                while ((bytesRead = fsInput.Read(chunkData, 0, chunkSize)) > 0)
                {
                    cryptoStream.Write(chunkData, 0, bytesRead);  //KEY FIX
                }
            }
        }
    }            
}

[编辑]

哦,我错过了很多信息。我误读了你的尺寸,认为 140,912 是尺寸,而不是差异。现在我明白了,我可以做出更容易理解的回应。根据您的代码,大小差异应该与您的块大小相当。由于 chunkSize 可能有点大,因此您的代码通常会写入比输入文件中实际数据多的 chunkSize 数据(正如 Greg 和 caf 指出的那样)。我标记的行是差异的原因。

You shouldn't write to the output file before the actual encryption process. The CryptoStream will handle all the necessary padding when it is closed. Also the for loop isn't necessary as the inner while loop will read the entire file. Also you should only write as much as was read from the file. Try these changes.

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");

            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))
            {
                byte[] chunkData = new byte[chunkSize];
                int bytesRead = 0;
                while ((bytesRead = fsInput.Read(chunkData, 0, chunkSize)) > 0)
                {
                    cryptoStream.Write(chunkData, 0, bytesRead);  //KEY FIX
                }
            }
        }
    }            
}

[edit]

Oh I've missed out on a lot of information. I misread what your sizes were thinking 140,912 was the size, not difference. Now that I see that, I can make more intelligible response. Based on your code, the difference in sizes should be comparable to your chunk size. Since the chunkSize can be somewhat large, your code will typically write up to chunkSize more data than is actually in your input file (as Greg and caf pointed out). The line that I've marked is the reason for the discrepancy.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文