You need to enable JavaScript to run this app. AES CBC 128位加密后解密无法返回原始值,代码哪里出错了?
优惠活动
大模型
产品
解决方案
定价
更多

AES CBC 128位加密后解密无法返回原始值,代码哪里出错了?

你的代码存在以下几个核心问题:

  • Aes实例被提前释放:GetAes方法中你给创建的Aes实例加了using声明,当方法返回时该实例就会被自动销毁,后续调用加密解密方法时访问已释放对象就会抛出异常,这是你去掉PaddingMode.Zeros配置后程序直接崩溃的根因。
  • 加密结果读取时机错误:加密逻辑中你在CryptoStream的using块内部就调用MemoryStream.ToArray(),此时CryptoStream还未完成最终块的刷新写入,拿到的加密数据是不完整的,自然无法正确解密。
  • IV处理逻辑不严谨:AES-CBC模式要求IV长度必须等于AES块大小(16字节),你加密时传入空字节数组虽然会让Aes自动生成合法IV,但逻辑上存在隐患,且如果后续传入长度不符合要求的IV会直接报错。
  • PaddingMode.Zeros的固有缺陷:零填充不会在解密后自动移除填充的0字节,解密结果末尾会多出多余的空字符,同时如果明文长度刚好是块大小的整数倍,零填充不会追加额外块,也容易引发解析异常,默认的PaddingMode.PKCS7才是更通用、更安全的选择。
  • 编码逻辑不明确:代码中keyText.ToByteArray()以及StreamWriter/StreamReader都没有显式指定编码,如果依赖系统默认编码,跨环境运行时可能出现密钥不匹配、明文乱码的问题。

修正方案

1. 修正GetAes方法

private static Aes GetAes(string keyText, byte[] iv)
{
    // 显式指定UTF8编码转密钥字节,避免编码不一致问题
    var key = Encoding.UTF8.GetBytes(keyText);
    // 移除错误的using声明,避免对象提前释放
    var result = Aes.Create();
    result.Mode = CipherMode.CBC;
    // 改用PKCS7填充,和官方标准实现对齐
    result.Padding = PaddingMode.PKCS7;
    result.KeySize = 128;
    result.BlockSize = 128;
    result.Key = key;
    // 仅传入合法长度IV时才赋值,否则使用自动生成的安全IV
    if (iv.Length == result.BlockSize / 8)
    {
        result.IV = iv;
    }
    return result;
}

2. 修正加密解密逻辑

public static AesEncryptionInfo EncryptWithAes(this string plainText, string keyText)
{
    // 转移using声明到当前方法,Aes使用完成后再释放
    using var aesAlg = GetAes(keyText, Array.Empty<byte>());
    var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
    byte[] encrypted;
    using (var msEncrypt = new MemoryStream())
    {
        using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
        {
            // 显式指定UTF8编码写入明文,和解密逻辑对齐
            using (var swEncrypt = new StreamWriter(csEncrypt, Encoding.UTF8))
            {
                swEncrypt.Write(plainText);
            }
        }
        // 移动ToArray到CryptoStream释放后,确保已写入完整加密数据
        encrypted = msEncrypt.ToArray();
    }
    return new AesEncryptionInfo(encrypted, aesAlg.IV);
}

public static string DecryptFromAes(this byte[] cipherText, string keyText, byte[] iv)
{
    using var aesAlg = GetAes(keyText, iv);
    var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
    using (var msDecrypt = new MemoryStream(cipherText))
    {
        using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
        {
            // 显式指定UTF8编码读取明文,和加密逻辑对齐
            using (var srDecrypt = new StreamReader(csDecrypt, Encoding.UTF8))
            {
                return srDecrypt.ReadToEnd().TrimEnd('\0');
            }
        }
    }
}

修正后你原有调用代码可以直接运行,解密可以正常得到原始明文,也可以正常移除自定义的PaddingMode.Zeros配置不会触发崩溃。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 12:45:04