aes.create() 可能返回 null,应判空回退为 new aesmanaged();iv 必须每次随机生成并随密文存储;key 应用 rfc2898derivebytes 派生,长度严格匹配(如 aes-256 需 32 字节);加解密端 ciphermode、paddingmode、编码必须一致。

Aes.Create() 可能返回 null,别直接 new Aes() —— 用判空回退更稳
在 .NET Framework 4.5 以下、Unity IL2CPP 构建、或某些 AOT 编译环境里,Aes.Create() 会返回 null,不是你漏了 using 或写错了语法。硬写 new Aes() 会编译失败,因为 Aes 是抽象类。
- 正确做法是:
var aes = Aes.Create() ?? new AesManaged(); -
AesManaged是纯托管实现,.NET Core 3.1+ 和 .NET 5/6/7/8 全支持,跨平台无坑;AesCryptoServiceProvider调 Windows CryptoAPI,Linux/macOS 上直接抛PlatformNotSupportedException,别乱换 - .NET 6+ 推荐优先用
Aes.Create(),但必须判空——这是生产环境最常被忽略的兼容性断点
IV 必须随每次加密随机生成,且和密文一起存,不能硬编码
把 iv = Encoding.UTF8.GetBytes("1234567890123456") 写死在代码里,等于把 AES 降级成“带密码的凯撒位移”。攻击者拿到一个密文就能批量解密所有历史文件。
- 加密时调用
aes.GenerateIV(),之后aes.IV就是安全随机值 - 保存密文前,把 IV 拼在密文前面(比如前 16 字节),解密时先读出这 16 字节当 IV,再读剩余部分当密文
- 示例序列化逻辑:
var combined = new byte[16 + cipherBytes.Length]; Array.Copy(iv, 0, combined, 0, 16); Array.Copy(cipherBytes, 0, combined, 16, cipherBytes.Length); - 别用字符串拼接 IV 和 Base64 密文——Base64 编码后长度不可控,解码时无法准确定位 IV 边界
CryptoStream 解密时读不到完整内容?检查流关闭顺序和 StreamReader 编码
常见现象:解密后 StreamReader.ReadToEndAsync() 返回空字符串或截断,但没报错。根源往往是流生命周期管理混乱,或编码不匹配。
-
CryptoStream必须在StreamReader之前被using包裹,否则StreamReader关闭时可能触发CryptoStream的 flush 逻辑失败 -
StreamReader默认用 UTF-8,但如果原始明文是 GB2312 或含 BOM 的 UTF-16,解密后就会乱码或提前终止;显式传入编码:new StreamReader(cryptoStream, Encoding.UTF8) - 确保文件流以
FileMode.Open打开,且位置在开头;如果文件开头存了 IV,记得用fileStream.Position = 16跳过它再创建CryptoStream - 别在
CryptoStream外层套BufferedStream——它会干扰块对齐,导致CryptographicException: The input data is not a complete block
Key 长度不匹配是 CryptographicException 最高频原因
看到 CryptographicException 提示 “key size not valid” 或 “specified key is not a valid size”,基本就是 Key 字节数错了。AES-128 要 16 字节,AES-256 要 32 字节,差 1 字节都不行。
- 别用
Encoding.UTF8.GetBytes("mykey123")直接转字符串——长度不可控,且含可预测字符 - 生产环境用
Rfc2898DeriveBytes从口令派生 Key:给定 salt(至少 16 字节随机)和迭代次数(≥100000),输出指定字节数 - 设置
aes.KeySize = 256后,必须确保传给aes.Key的字节数组长度是 32;否则运行时报错,且错误信息不提示具体缺多少字节 - 密钥和 IV 的编码、长度、模式(
CipherMode.CBC)、填充(PaddingMode.PKCS7)三者必须在加解密两端完全一致,Java/Python 互操作时尤其注意对方是否用了NoPadding或PKCS5
IV 的随机性和 Key 的派生方式,比选 CBC 还是 GCM 更容易被忽视——它们一旦出错,问题不会立刻暴露,而是让整个加密体系形同虚设。










