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

AES解密结果末尾出现随机字符的问题及代码修正方案

AES解密后末尾出现多余字符的问题解决及代码优化

问题根源

解密后末尾出现多余字符,核心原因是禁用了AES的自动填充(PaddingMode.None)。AES属于块加密算法,要求明文长度必须是块大小(16字节)的整数倍。当明文长度不足时,加密过程会自动补全到块大小的倍数,解密后这些补全内容就成了多余的乱码字符。

核心修改方案

恢复AES默认的PKCS7填充模式(行业标准安全填充方式),移除代码中禁用填充的语句即可解决问题。

修改后的加密方法

public static byte[] Encrypt(int key, string plainText, int iv)
{
    byte[] encryptedText;
    // 使用using包裹Aes实例,避免资源泄漏
    using (Aes aesAlg = Aes.Create())
    {
        string keyString = key.ToString();
        Rfc2898DeriveBytes sourceDeriveBytes = new(keyString, Encoding.UTF8.GetBytes(keyString));
        byte[] keyBytes = sourceDeriveBytes.GetBytes(16);
        aesAlg.Key = keyBytes;

        string ivString = iv.ToString();
        Rfc2898DeriveBytes zendeskDeriveBytes = new(ivString, Encoding.UTF8.GetBytes(ivString));
        byte[] ivBytes = zendeskDeriveBytes.GetBytes(16);
        aesAlg.IV = ivBytes;

        // 移除PaddingMode.None,使用默认的PKCS7填充
        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, Encoding.UTF8))
                {
                    swEncrypt.Write(plainText);
                }
            }
            encryptedText = msEncrypt.ToArray();
        }
    }
    return encryptedText;
}

修改后的解密方法

public static string Decrypt(int key, byte[] encryptedText, int iv)
{
    string plainText;
    // 使用using包裹Aes实例,避免资源泄漏
    using (Aes aesAlg = Aes.Create())
    {
        string keyString = key.ToString();
        Rfc2898DeriveBytes pbkdf = new(keyString, Encoding.UTF8.GetBytes(keyString));
        byte[] keyBytes = pbkdf.GetBytes(16);
        aesAlg.Key = keyBytes;

        string ivString = iv.ToString();
        Rfc2898DeriveBytes zendeskDeriveBytes = new(ivString, Encoding.UTF8.GetBytes(ivString));
        byte[] ivBytes = zendeskDeriveBytes.GetBytes(16);
        aesAlg.IV = ivBytes;

        // 移除PaddingMode.None,使用默认的PKCS7填充
        ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
        using (MemoryStream msDecrypt = new MemoryStream(encryptedText))
        {
            using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
            {
                using (StreamReader srDecrypt = new StreamReader(csDecrypt, Encoding.UTF8))
                {
                    plainText = srDecrypt.ReadToEnd();
                }
            }
        }
    }
    return plainText;
}

代码中的不良实践及改进建议

  • 密钥/IV生成不安全:
    • 用同一个字符串作为Rfc2898DeriveBytes的密码和盐,等于没有加盐,大幅降低密钥安全性。正确做法是生成随机盐,将盐与加密数据一同存储/传输,解密时复用该盐。
    • 用int类型的key和iv转字符串生成密钥/IV,密钥空间太小,易被暴力破解。建议直接使用足够长度的随机字节作为密钥,或用强密码配合随机盐生成密钥。
  • 资源泄漏问题:原代码未用using包裹Aes实例,修改后的代码已补上,确保资源正确释放。
  • 编码显式化:修改后的代码显式指定Encoding.UTF8,避免环境编码差异导致的明文乱码问题。

验证效果

修改完成后,解密过程会自动识别并移除PKCS7填充的多余字节,返回的明文将不再包含末尾的乱码字符,比如之前的TEST ...会恢复为干净的TEST。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 00:13:14