解密失败主因是密钥、iv、模式、填充四者未对齐;同一aes实例中createencryptor()与createdecryptor()默认各自生成iv,导致cbc下iv不一致而抛出padding异常;iv须显式获取并复用,key需用rfc2898derivebytes派生,严禁硬编码或utf8直接转字符串。

解密失败不是算法问题,而是密钥、IV、模式、填充四者中至少有一项没对齐——差一个字节就抛 CryptographicException,不会给你乱码,直接中断。
为什么 CreateEncryptor() 和 CreateDecryptor() 用同一个 Aes 实例也解不开?
因为默认调用时不传参,两者会各自执行 GenerateIV(),生成两套完全不同的 IV。CBC 模式下,IV 不一致会导致解密时抛出 "Padding is invalid and cannot be removed" 或 "Bad Data"。
- 加密后必须显式读取
aes.IV字节数组(长度恒为 16) - 解密时必须把该字节数组原样传给
CreateDecryptor(key, iv),不能只传aes.IV(此时它已是新生成的) - 别依赖
aes.IV在多次调用间“保持”,它只在你调用GenerateIV()后那一刻有效
Key 和 IV 怎么生成才不裸奔?
硬编码字符串如 "1234567890123456" 当 Key 或 IV,等于把 AES 当凯撒密码用——熵低、长度不可控、可复现。
- IV 必须每次加密都调用
aes.GenerateIV()生成,长度固定 16 字节;可明文传输(比如拼在密文前),但绝不可复用 - Key 别用
Encoding.UTF8.GetBytes("pass")直接转——长度可能为 8/12/15 字节,而Aes.KeySize = 256要求 Key 正好 32 字节 - 生产环境用
Rfc2898DeriveBytes派生:盐值随机、迭代 ≥10000,输出指定长度字节数组 - 测试时若需固定 Key/IV,用
new byte[32]+RandomNumberGenerator.Fill()初始化,而非全零或字符串
Aes.Create() 返回 null 怎么办?
在 .NET Framework 4.5 以下、Unity IL2CPP 构建、或某些 AOT 环境中,Aes.Create() 可能返回 null——不是你代码错,是运行时没加载实现。
- 别写
new Aes()(编译失败,Aes是抽象类) - 正确回退:
var aes = Aes.Create() ?? new AesManaged(); -
AesManaged是纯托管实现,.NET Core 3.1+ 和所有新版 .NET 全支持;AesCryptoServiceProvider仅 Windows 可用,Linux/macOS 上抛PlatformNotSupportedException - 即使用了
Aes.Create(),也必须用using包裹,否则底层加密句柄泄漏
Base64 密文解不开?先查这三处
报错如 "The input data is not a complete block"、"Length of the data to decrypt is invalid",基本都不是算法问题,而是序列化断点。
- 加密输出是否包含完整 IV + 密文?如果只存了 Base64 密文,解密时就没法还原 IV
- Base64 解码后字节数组长度是否是 16 的整数倍?如果不是,说明原始字节数组被截断、拼接错误,或编码前漏了 IV
- 两端
CipherMode(默认CBC)、PaddingMode(默认PKCS7)是否完全一致?Java/Python 对端若用NoPadding,你这边也得显式设aes.Padding = PaddingMode.None
最易被忽略的是:文件加解密时,用 StreamReader 直接读加密流,会因 BOM 或编码不匹配导致提前终止或空结果;必须用 BinaryReader 处理原始字节,或确保 StreamReader 显式传入正确编码且 CryptoStream 在其外层被 using 管理。










