You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

迁移RijndaelManaged至AES后解密报错:填充无效无法移除

问题:AES替换RijndaelManaged后抛出「填充无效且无法移除」异常

将加密组件从RijndaelManaged替换为Aes后,代码无法正常运行,抛出Padding is invalid and cannot be removed异常,此前使用RijndaelManaged时代码可正常工作。

代码中两次调用DecryptStringFromBytes_Aes方法:

  • 第一次传入长度为80的byte[],可正常执行并返回预期字符串;
  • 将返回字符串转换为长度48的byte[]后第二次调用该方法,触发上述异常。已尝试调整填充模式或加密模式,问题仍未解决。

相关代码

// encryptedText comes as a post from another web application
public static string DecryptStringAES(string encryptedText, string key)
{
    var keybytes = Encoding.UTF8.GetBytes(key);
    var iv = keybytes;

    var encryptStringToBytes = EncryptStringToBytes_Aes(encryptedText, keybytes, iv);

    // roundtrip value is same as encryptedText -- which came from another webapp.
    // Decrypt the bytes to a string. here encryptStringToBytes is byte[80]
    // this line does not throw the exception
    var roundtrip = DecryptStringFromBytes_Aes(encryptStringToBytes, keybytes, iv);

    //DECRYPT FROM CRIPTOJS
    var encrypted = Convert.FromBase64String(roundtrip);

    //here encryptStringToBytes is byte[48]
    //This Line throws the exception --Padding is invalid and cannot be removed
    var id = DecryptStringFromBytes_Aes(encrypted, keybytes, iv);

    return id;
}

private static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
{
    if (cipherText == null || cipherText.Length <= 0) throw new ArgumentNullException("cipherText");
    if (Key == null || Key.Length <= 0) throw new ArgumentNullException("Key");
    if (IV == null || IV.Length <= 0) throw new ArgumentNullException("IV");

    string plaintext = null;

    try
    {
        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.Mode = CipherMode.CFB;
            aesAlg.Padding = PaddingMode.PKCS7;
            aesAlg.Key = Key;
            aesAlg.IV = IV;

            ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

            using (MemoryStream msDecrypt = new MemoryStream(cipherText))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    {
                        plaintext = srDecrypt.ReadToEnd();
                    }
                }
            }
        }
    }
    catch (Exception ex)
    {
        string err = ex.Message;
        throw;
    }

    return plaintext;
}

private static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
{
    if (plainText == null || plainText.Length <= 0) throw new ArgumentNullException("plainText");
    if (Key == null || Key.Length <= 0) throw new ArgumentNullException("Key");
    if (IV == null || IV.Length <= 0) throw new ArgumentNullException("IV");

    byte[] encrypted;

    try
    {
        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.Mode = CipherMode.CFB;
            aesAlg.Padding = PaddingMode.PKCS7;
            aesAlg.Key = Key;
            aesAlg.IV = IV;

            ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        swEncrypt.Write(plainText);
                    }

                    encrypted = msEncrypt.ToArray();
                }
            }
        }
    }
    catch (Exception ex)
    {
        string er = ex.Message;
        throw ex;
    }

    return encrypted;
}

问题分析与修复方案

核心原因

  1. CFB模式参数不匹配:RijndaelManaged支持自定义块大小,而Aes固定为128位块大小。此外,.NET的Aes默认CFB反馈大小为8位,而CryptoJS默认使用128位反馈大小,参数不一致会导致解密数据错位,触发填充错误。
  2. IV复用问题:代码中直接将密钥字节作为IV,不符合加密规范——IV应随机生成并与加密端完全一致,复用密钥会导致块对齐错误。
  3. 跨平台编码差异:CryptoJS和.NET在字符串转字节、Base64处理上可能存在编码差异,导致解密时数据不完整或错位。

具体修复步骤

  • 统一CFB反馈大小:在Aes配置中明确设置FeedbackSize为128(匹配CryptoJS默认值):
    aesAlg.FeedbackSize = 128;
    
  • 修正IV使用逻辑:确保解密时使用的IV与CryptoJS加密时的IV完全一致。如果CryptoJS通过密钥派生IV(如PBKDF2),需在.NET中实现相同的派生逻辑,不要复用密钥作为IV。
  • 调整解密读取方式:对于流模式(CFB),改用BinaryReader读取原始字节再转字符串,避免StreamReader编码转换引入的问题:
    using (BinaryReader brDecrypt = new BinaryReader(csDecrypt))
    {
        byte[] plainBytes = brDecrypt.ReadBytes((int)csDecrypt.Length);
        plaintext = Encoding.UTF8.GetString(plainBytes);
    }
    
  • 验证数据完整性:检查Convert.FromBase64String(roundtrip)得到的byte[]是否与CryptoJS加密输出的原始字节完全一致,排除Base64转换错误。

内容的提问来源于stack exchange,提问作者istudent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 08:22:41