填充无效,不能删除.在cs.FlushFinalBlock()行触发ERROR

本文关键字:ERROR FlushFinalBlock cs 无效 不能 删除 填充 | 更新日期: 2023-09-27 18:18:46

我试图使用Rijndael方法加密和解密数据。它加密得很好,但当我试图解密它时,它在private static byte[] DecryptString(byte[] cipherData, byte[] Key, byte[] IV)方法的cs.FlushFinalBlock();行给出padding is invalid and cannot be removed。我尝试了很多来源,比如

  • RijndaelManaged "填充无效,无法删除"只有在生产中解密时才会发生
  • 在EOF抛出异常之前停止解密:填充无效且无法删除
  • http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/0fa69204-3bba-48a9-9bdc-32a12b0da4a0
我知道这是一个常见的问题,甚至可能是一个重复的。我从早上开始就在网上搜索,但没有找到解决方案。以下是我的代码:
    //clearText -> the string to be encrypted
    //passowrd -> encryption key
    public string EncryptString(string clearText, string Password)
    {
        // First we need to turn the input string into a byte array. 
        byte[] clearBytes =
            Encoding.Unicode.GetBytes(clearText);
        // Then, we need to turn the password into Key and IV 
        // We are using salt to make it harder to guess our key
        // using a dictionary attack - 
        // trying to guess a password by enumerating all possible words. 
        var pdb = new PasswordDeriveBytes(Password,
                                          new byte[]
                                              {
                                                  0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d,
                                                  0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76
                                              });
        // Now get the key/IV and do the encryption using the
        // function that accepts byte arrays. 
        // Using PasswordDeriveBytes object we are first getting
        // 32 bytes for the Key 
        // (the default Rijndael key length is 256bit = 32bytes)
        // and then 16 bytes for the IV. 
        // IV should always be the block size, which is by default
        // 16 bytes (128 bit) for Rijndael. 
        // If you are using DES/TripleDES/RC2 the block size is
        // 8 bytes and so should be the IV size. 
        // You can also read KeySize/BlockSize properties off
        // the algorithm to find out the sizes. 
        byte[] encryptedData = EncryptString(clearBytes,
                                             pdb.GetBytes(32), pdb.GetBytes(16));
        // Now we need to turn the resulting byte array into a string. 
        // A common mistake would be to use an Encoding class for that.
        //It does not work because not all byte values can be
        // represented by characters. 
        // We are going to be using Base64 encoding that is designed
        //exactly for what we are trying to do. 
        return Convert.ToBase64String(encryptedData);
    }
    //cipherText -> the string to be decrypted
    //passowrd -> decryption key
    public string DecryptString(string cipherText, string Password)
    {
        // First we need to turn the input string into a byte array. 
        // We presume that Base64 encoding was used 
        byte[] cipherBytes = Convert.FromBase64String(cipherText);
        // Then, we need to turn the password into Key and IV 
        // We are using salt to make it harder to guess our key
        // using a dictionary attack - 
        // trying to guess a password by enumerating all possible words. 
        var pdb = new PasswordDeriveBytes(Password,
                                          new byte[]
                                              {
                                                  0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65,
                                                  0x64, 0x76, 0x65, 0x64, 0x65, 0x76
                                              });
        // Now get the key/IV and do the decryption using
        // the function that accepts byte arrays. 
        // Using PasswordDeriveBytes object we are first
        // getting 32 bytes for the Key 
        // (the default Rijndael key length is 256bit = 32bytes)
        // and then 16 bytes for the IV. 
        // IV should always be the block size, which is by
        // default 16 bytes (128 bit) for Rijndael. 
        // If you are using DES/TripleDES/RC2 the block size is
        // 8 bytes and so should be the IV size. 
        // You can also read KeySize/BlockSize properties off
        // the algorithm to find out the sizes. 
        byte[] decryptedData = DecryptString(cipherBytes,
                                             pdb.GetBytes(32), pdb.GetBytes(16));
        // Now we need to turn the resulting byte array into a string. 
        // A common mistake would be to use an Encoding class for that.
        // It does not work 
        // because not all byte values can be represented by characters. 
        // We are going to be using Base64 encoding that is 
        // designed exactly for what we are trying to do. 
        return Encoding.Unicode.GetString(decryptedData);
    }
    // Encrypt a byte array into a byte array using a key and an IV 
    private static byte[] EncryptString(byte[] clearData, byte[] Key, byte[] IV)
    {
        // Create a MemoryStream to accept the encrypted bytes 
        var ms = new MemoryStream();
        // Create a symmetric algorithm. 
        // We are going to use Rijndael because it is strong and
        // available on all platforms. 
        // You can use other algorithms, to do so substitute the
        // next line with something like 
        //      TripleDES alg = TripleDES.Create(); 
        Rijndael alg = Rijndael.Create();
        // Now set the key and the IV. 
        // We need the IV (Initialization Vector) because
        // the algorithm is operating in its default 
        // mode called CBC (Cipher Block Chaining).
        // The IV is XORed with the first block (8 byte) 
        // of the data before it is encrypted, and then each
        // encrypted block is XORed with the 
        // following block of plaintext.
        // This is done to make encryption more secure. 
        // There is also a mode called ECB which does not need an IV,
        // but it is much less secure. 
        alg.Key = Key;
        alg.IV = IV;
        // Create a CryptoStream through which we are going to be
        // pumping our data. 
        // CryptoStreamMode.Write means that we are going to be
        // writing data to the stream and the output will be written
        // in the MemoryStream we have provided. 
        var cs = new CryptoStream(ms,
                                  alg.CreateEncryptor(), CryptoStreamMode.Write);
        // Write the data and make it do the encryption 
        cs.Write(clearData, 0, clearData.Length);
        // Close the crypto stream (or do FlushFinalBlock). 
        // This will tell it that we have done our encryption and
        // there is no more data coming in, 
        // and it is now a good time to apply the padding and
        // finalize the encryption process. 
        cs.FlushFinalBlock();
        // Now get the encrypted data from the MemoryStream.
        // Some people make a mistake of using GetBuffer() here,
        // which is not the right way. 
        byte[] encryptedData = ms.ToArray();
        return encryptedData;
    }
    private static byte[] DecryptString(byte[] cipherData,
                                        byte[] Key, byte[] IV)
    {
        // Create a MemoryStream that is going to accept the
        // decrypted bytes 
        var ms = new MemoryStream();
        // Create a symmetric algorithm. 
        // We are going to use Rijndael because it is strong and
        // available on all platforms. 
        // You can use other algorithms, to do so substitute the next
        // line with something like 
        //     TripleDES alg = TripleDES.Create(); 
        Rijndael alg = Rijndael.Create();
        // Now set the key and the IV. 
        // We need the IV (Initialization Vector) because the algorithm
        // is operating in its default 
        // mode called CBC (Cipher Block Chaining). The IV is XORed with
        // the first block (8 byte) 
        // of the data after it is decrypted, and then each decrypted
        // block is XORed with the previous 
        // cipher block. This is done to make encryption more secure. 
        // There is also a mode called ECB which does not need an IV,
        // but it is much less secure. 
        alg.Key = Key;
        alg.IV = IV;
        // Create a CryptoStream through which we are going to be
        // pumping our data. 
        // CryptoStreamMode.Write means that we are going to be
        // writing data to the stream 
        // and the output will be written in the MemoryStream
        // we have provided. 
        var cs = new CryptoStream(ms,
                                  alg.CreateDecryptor(), CryptoStreamMode.Write);
        // Write the data and make it do the decryption 
        cs.Write(cipherData, 0, cipherData.Length);
        // Close the crypto stream (or do FlushFinalBlock). 
        // This will tell it that we have done our decryption
        // and there is no more data coming in, 
        // and it is now a good time to remove the padding
        // and finalize the decryption process. 
        cs.FlushFinalBlock();
        // Now get the decrypted data from the MemoryStream. 
        // Some people make a mistake of using GetBuffer() here,
        // which is not the right way. 
        byte[] decryptedData = ms.ToArray();
        return decryptedData;
    }

非常感谢:)PS:我从网上获取了这段代码,并编辑了一些以适合我的程序

填充无效,不能删除.在cs.FlushFinalBlock()行触发ERROR

您需要越过异常,以便能够诊断出发生了什么。为了做到这一点,您需要将解密端设置为没有填充。这会让它接受任何事情。这样做之后,您就可以查看从解密中出现的内容并开始诊断错误。注意,这不是一个解决方案,它是一种忽略异常的方法。导致异常的原因仍然存在。

看看出现了什么。都是垃圾吗?它部分是垃圾,部分是原始明文吗?如果它是混合的,垃圾出现在哪里:在开始,在结束,两者,在中间的某个地方?告诉我们你看到了什么,我们可以指出问题的可能原因。

当一切正常时,将加密和解密设置为pkcs# 7填充。