始终获取“ CryptographicException:填充无效,无法删除。”即使使用填充,AES CBC加密也会出现错误

问题描述 投票:0回答:1

我已经审查了有关此主题的其他帖子,但似乎无法弄清楚我对此的错误。我正在尝试使用AES CBC流式传输加密文件(以后我会做其他的)。我知道我需要使用CBC进行填充并进行配置。但是我仍然收到相同的错误。

 Message: 
 System.Security.Cryptography.CryptographicException : Padding is invalid and cannot be removed.
     Stack Trace: 
  UniversalCryptoDecryptor.DepadBlock(Byte[] block, Int32 offset, Int32 count)
  UniversalCryptoDecryptor.UncheckedTransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
  UniversalCryptoTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
  CryptoStream.ReadAsyncCore(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken, Boolean useAsync)
  CryptoStream.Read(Byte[] buffer, Int32 offset, Int32 count)
  EncryptionFunctions.AESDecryptCBC(String encryptedFile, String plainTextFile, Byte[] key, Byte[] iv, Int32 blockSize, Int32 bufferSize) line 82
  EncryptionFunctionsUnitTests.TestEncryptAndDecryptFiles() line 39

我已经尝试了各种更改,例如不同类型的填充,但是我得到的最好的结果是某种垃圾输出。加密似乎可以正常工作,尽管我不能真正说出它输出的车库数据,因为它看起来像一堆汉字。输入文件只是我用于测试的3 KB维基百科文字。

这是我用于加密和解密的两个功能。

 public static void AESEncryptCBC(string plainTextFile, string encryptedFile, byte[] key, byte[] iv, int bufferSize = 65536)
    {
        using (FileStream fileStreamOutput = new FileStream(encryptedFile, FileMode.Create)) {
            using (FileStream fileStreamInput = new FileStream(plainTextFile, FileMode.Open))
            {
                using (Aes aes = Aes.Create())
                {
                    aes.Key = key;
                    aes.KeySize = key.Length*8; // Keysize is in bits, bytes to bits conversion
                    aes.BlockSize = 128; // bits
                    aes.Mode = CipherMode.CBC;
                    aes.IV = iv;
                    aes.Padding = PaddingMode.PKCS7;

                    using (CryptoStream cryptoStream = new CryptoStream(fileStreamOutput, aes.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        int read;
                        byte[] readBuffer = new byte[bufferSize];

                        while ((read = fileStreamInput.Read(readBuffer, 0, readBuffer.Length)) > 0)
                        {
                            cryptoStream.Write(readBuffer, 0, read);
                        }
                    }
                }
            }
        }

    }

    public static void AESDecryptCBC(string encryptedFile, string plainTextFile, byte[] key, byte[] iv, int bufferSize = 65536)
    {
        using (FileStream fileStreamOutput = new FileStream(plainTextFile, FileMode.Create))
        {
            using (FileStream fileStreamInput = new FileStream(encryptedFile, FileMode.Open))
            {
                using (Aes aes = Aes.Create())
                {
                    aes.Key = key;
                    aes.KeySize = key.Length * 8; // Keysize is in bits, bytes to bits conversion
                    aes.BlockSize = 128; // bits
                    aes.Mode = CipherMode.CBC;
                    aes.IV = iv;
                    aes.Padding = PaddingMode.PKCS7;

                    using (CryptoStream cryptoStream = new CryptoStream(fileStreamInput, aes.CreateDecryptor(), CryptoStreamMode.Read))
                    {
                        int read;
                        byte[] readBuffer = new byte[bufferSize];

                        while ((read = cryptoStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
                        {
                            fileStreamOutput.Write(readBuffer, 0, read);
                        }
                    }
                }
            }
        }
    }

我正在调用它们的单元测试方法。不用介意随机数生成器,我稍后将使用哈希函数输入密码,这是为了确保我拥有正确的大小键。

 public void TestEncryptAndDecryptFiles()
    {
        string outFile = "out.txt";
        string outFile2 = "out2.txt";

        byte[] salt = new byte[128];
        RandomNumberGenerator.Fill(salt);

        int numberOfBits = 256;
        int blockSize = 128;
        byte[] key = new byte[numberOfBits / 8];
        byte[] iv = new byte[blockSize /8];
        RandomNumberGenerator.Fill(key);
        RandomNumberGenerator.Fill(iv);
        EncryptionFunctions.AESEncryptCBC(SampleText, outFile, key, iv);
        Assert.IsTrue(File.Exists(outFile));

        EncryptionFunctions.AESDecryptCBC(outFile, outFile2, key, iv);
        Assert.IsTrue(File.Exists(outFile2));
        Assert.AreEqual(HashFunctions.Md5(outFile), HashFunctions.Md5(outFile2));

    }
}
c# encryption .net-core aes encryption-symmetric
1个回答
0
投票

[知道了,我需要更改代码以使用aes.CreateEncryptor(key,iv)。我终于发现,调用CreateEncryptor()CreateEncryptor(null, null)会自动生成一个初始化向量和一个密钥,这些密钥会覆盖我用aes.keyaes.iv设置的设置。我可以设置一些愚蠢的东西,然后用显然不打算这样做的函数将其覆盖。也许是一个错误,因为一页确实显示“使用当前的Key属性和初始化向量(IV)创建对称的加密对象”。它不是基于我之前的代码执行的。

无论如何,我在https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.symmetricalgorithm.generateiv?view=netframework-4.8#System_Security_Cryptography_SymmetricAlgorithm_GenerateIV

© www.soinside.com 2019 - 2024. All rights reserved.