c# - AES 加密错误 : Padding is invalid and cannot be removed

标签 c# .net-2.0 aes

谁能帮我解决下面的代码,错误是填充无效且无法删除。我正在搜索所有 SO 并应用了他们的所有建议,但填充仍然无效。我正在使用 NET-2.0

下面是我的代码

static public String AES_encrypt(String Input)
    {
        string AES_Key = "PSVJQRk9QTEpNVU1DWUZCRVFGV1VVT0ZOV1RRU1NaWQ=";
        string AES_IV = "YWlFLVEZZUFNaWlhPQ01ZT02qWU5HTFJQVFNCRUJZVA=";
        var aes = new RijndaelManaged();
        aes.KeySize = 256;
        aes.BlockSize = 256;
        aes.Padding = PaddingMode.PKCS7;
        aes.Key = Convert.FromBase64String(AES_Key);
        aes.IV = Convert.FromBase64String(AES_IV);

        var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);
        byte[] xBuff = null;
        using (var ms = new MemoryStream())
        {
            using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
            {
                byte[] xXml = Encoding.UTF8.GetBytes(Input);
                cs.Write(xXml, 0, xXml.Length);
            }

            xBuff = ms.ToArray();
        }

        String Output = Convert.ToBase64String(xBuff);
        return Output;
    }

    static public String AES_decrypt(String Input)
    {
        string AES_Key = "PSVJQRk9QTEpNVU1DWUZCrOFGV1VVT0ZOV1RRU1NaWQ=";
        string AES_IV = "YWlFLVEZZUFNaWlhPQ01ZT02qWU5HTFJQVFNCRUJZVA=";
        RijndaelManaged aes = new RijndaelManaged();
        aes.KeySize = 256;
        aes.BlockSize = 256;
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
        aes.Key = Convert.FromBase64String(AES_Key);
        aes.IV = Convert.FromBase64String(AES_IV);

        var decrypt = aes.CreateDecryptor();
        byte[] xBuff = null;
        using (var ms = new MemoryStream())
        {
            using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
            {
                byte[] xXml = Convert.FromBase64String(Input);
                cs.Write(xXml, 0, xXml.Length);
            }

            xBuff = ms.ToArray();
        }

        String Output = Encoding.UTF8.GetString(xBuff);
        return Output;
    }

我认为这里的问题是 AES_encrypt,因为如果我将加密字符串从 PHP 传递到我的项目,AES_decrypt 将成功解密它。但是,每当我使用 AES_encrypt 时,AES_decrypt 都会抛出错误。

如有任何帮助,我们将不胜感激。

最佳答案

Mahr - 正如 Patrick 指出的那样,我应该花时间解释我对您的原件所做的更改..

首先,您的解密器是在没有任何参数的情况下创建的,因此它不理解要使用的 ciperkey 其次, key 和 IV 以字节为单位,因此在传递 key 大小之前必须除以 8

我还添加了一些额外的东西来防止进一步的问题 1:您必须在完成后清除 RijndaelManaged 对象 2:我简化了字符串转换,让它更清晰一点 3:这只是因为我喜欢它们,我将这些方法创建为扩展方法以便于使用。

这应该有效..

private static byte[] _salt = Encoding.ASCII.GetBytes("o6806642kbM7c5");

    /// <summary>
    /// Encrypt the given string using AES.  The string can be decrypted using 
    /// DecryptStringAES().  The sharedSecret parameters must match.
    /// </summary>
    /// <param name="plainText">The text to encrypt.</param>
    /// <param name="sharedSecret">A password used to generate a key for encryption.</param>
    public static string EncryptStringAES(this string plainText)
    {
        string sharedSecret = "abcd";
        if (string.IsNullOrEmpty(plainText))
            throw new ArgumentNullException("plainText");
        if (string.IsNullOrEmpty(sharedSecret))
            throw new ArgumentNullException("sharedSecret");

        string outStr = null;                       // Encrypted string to return
        RijndaelManaged aesAlg = null;              // RijndaelManaged object used to encrypt the data.

        try
        {
            // generate the key from the shared secret and the salt
            Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt);

            // Create a RijndaelManaged object
            // with the specified key and IV.
            aesAlg = new RijndaelManaged();
            aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
            aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);

            // Create a decrytor to perform the stream transform.
            ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

            // Create the streams used for encryption.
            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {

                        //Write all data to the stream.
                        swEncrypt.Write(plainText);
                    }
                }
                outStr = Convert.ToBase64String(msEncrypt.ToArray());
            }
        }
        finally
        {
            // Clear the RijndaelManaged object.
            if (aesAlg != null)
                aesAlg.Clear();
        }

        // Return the encrypted bytes from the memory stream.
        return outStr;
    }

    /// <summary>
    /// Decrypt the given string.  Assumes the string was encrypted using 
    /// EncryptStringAES(), using an identical sharedSecret.
    /// </summary>
    /// <param name="cipherText">The text to decrypt.</param>
    /// <param name="sharedSecret">A password used to generate a key for decryption.</param>
    public static string DecryptStringAES(this string cipherText)
    {
        string sharedSecret = "abcd";
        if (string.IsNullOrEmpty(cipherText))
            throw new ArgumentNullException("cipherText");
        if (string.IsNullOrEmpty(sharedSecret))
            throw new ArgumentNullException("sharedSecret");

        // Declare the RijndaelManaged object
        // used to decrypt the data.
        RijndaelManaged aesAlg = null;

        // Declare the string used to hold
        // the decrypted text.
        string plaintext = null;

        try
        {
            // generate the key from the shared secret and the salt
            Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt);

            // Create a RijndaelManaged object
            // with the specified key and IV.
            aesAlg = new RijndaelManaged();
            aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
            aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);

            // Create a decrytor to perform the stream transform.
            ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
            // Create the streams used for decryption.                
            byte[] bytes = Convert.FromBase64String(cipherText);
            using (MemoryStream msDecrypt = new MemoryStream(bytes))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))

                        // Read the decrypted bytes from the decrypting stream
                        // and place them in a string.
                        plaintext = srDecrypt.ReadToEnd();
                }
            }
        }
        finally
        {
            // Clear the RijndaelManaged object.
            if (aesAlg != null)
                aesAlg.Clear();
        }

        return plaintext;
    }

关于c# - AES 加密错误 : Padding is invalid and cannot be removed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17177641/

相关文章:

c# - 在列表中查找项目的最快方法?

c# - 如何从另一个表格打开一个新表格

python - 增加 AES-CBC 加密算法在 pycrypto for python 中的传播

c++ - 使用 Crypto++ 库的 CBC 模式实现中的 AES128

iphone - 使用 openssl 加密并使用 AES 128、ecb 模式在 iPhone 上解密

c# - 将方法分配给动态创建的控件

c# - 使用 RX 在不同时间触发事件?

asp.net - 您可以在 IIS/ASP.Net 的应用程序中创建子应用程序吗

javascript - 在 OnBeforeUnload 上显示函数 "True/false"的返回值

c# - 如何将 unicode 字符放在 C# 中的 System.Windows.Forms.Button 上?