必须使用 AesCryptoServiceProvider(推荐 AES-256),禁用 DES/RC2;密钥需 PBKDF2 派生、IV 随机生成且不复用;大文件流式加密;HMACSHA256 验证完整性;密钥严禁硬编码或明文存储。

用 AesCryptoServiceProvider 而不是 DES 或 RC2
DES 和 RC2 已被证实不安全,NIST 早在 2005 年就弃用 DES,.NET 中的 DES 类仅保留用于兼容旧系统。生产环境必须使用 AES(推荐 AES-256)。AesCryptoServiceProvider 是 Windows 上经 FIPS 验证的实现,比 AesManaged 更可靠(后者在 .NET Core/.NET 5+ 中已标记为过时)。
实操建议:
- 始终指定
KeySize = 256、BlockSize = 128、Mode = CipherMode.CBC、Padding = PaddingMode.PKCS7 - 避免手动构造 IV:用
GenerateIV()生成随机值,并随密文一起保存(无需保密,但绝不能复用) - 密钥不能硬编码或派生自弱口令——应使用
Rfc2898DeriveBytes(PBKDF2)从口令派生,迭代次数 ≥ 100,000
密钥管理不能绕过 Windows CNG 或 DPAPI 直接存文件
把密钥写进配置文件、注册表或本地 JSON,等于把锁芯焊死却把钥匙挂在门把手上。即使加密了密钥,只要解密逻辑和密钥材料都在同一进程里,攻击者仍可内存 dump 提取。
实操建议:
- 服务端场景优先用
ProtectedData.Protect()(DPAPI),它绑定当前用户/机器上下文,无需额外密钥管理 - 企业级应用考虑
CngKey+CngAlgorithm.Aes,利用 Windows CNG 密钥存储容器(如Microsoft Software Key Storage Provider) - 绝对不要用自定义“混淆”代替加密——比如
Convert.ToBase64String(key)后再简单异或,这类操作无密码学强度
加密大文件必须流式处理,禁用 File.ReadAllBytes()
对一个 2GB 的 PDF 调用 File.ReadAllBytes() 会瞬间申请 2GB 托管内存,极易触发 GC 压力甚至 OutOfMemoryException,且密钥和明文会在内存中长期驻留,增加泄露风险。
实操建议:
- 用
CryptoStream包裹FileStream,逐块加密(例如 8KB 缓冲区) - 务必在
using块中处理所有流和加密对象,确保Dispose()被调用——这会清零内部密钥缓冲区 - 加密后立即调用
Array.Clear()清理临时字节数组(尤其含 IV 或派生密钥的数组)
验证完整性必须用 HMACSHA256,别信“加密即认证”
AES-CBC 只保证机密性,不防篡改。攻击者可翻转密文某字节,导致解密后明文对应位置出错——这种错误可能被忽略,造成静默损坏或填充预言攻击(Padding Oracle)。
实操建议:
- 先计算明文 HMAC(用独立密钥),再加密明文+HMAC;或先加密再对密文算 HMAC——两种方式都行,但密钥必须分离
- 不要复用加密密钥生成 HMAC 密钥;可用
HMACSHA256对原始密钥做一次 HKDF 提取(.NET 6+ 有Rfc5869DeriveBytes) - 解密时先验 HMAC,失败则直接丢弃,绝不尝试解密或返回部分结果










