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

.NET 6升级后RijndaelManaged加密数据无法正常解密如何解决

故障根因

你遇到的解密失败问题和RijndaelManaged过时没有关系,核心原因是**.NET 6对Rfc2898DeriveBytes的默认哈希算法做了破坏性变更**:

  • .NET 5及更早版本默认使用HashAlgorithmName.SHA1生成密钥
  • .NET 6+默认改为HashAlgorithmName.SHA256,导致相同密码、盐值生成的密钥完全不一致,自然解密失败

另外纠正你的认知误区:AES是Rijndael算法的标准子集,你当前代码里RijndaelManaged设置的BlockSize=128、CipherMode.CBC、PaddingMode.PKCS7完全符合AES标准,使用Aes.Create()替换不会有任何历史数据兼容问题。


修复方案

按以下步骤修改代码即可同时解决过时警告+历史数据解密问题:

  1. 所有Rfc2898DeriveBytes初始化时显式指定哈希算法为SHA1,和老版本逻辑对齐
  2. 用Aes.Create()替换RijndaelManaged,参数保持不变
  3. 用更安全的RandomNumberGenerator替代已过时的RNGCryptoServiceProvider

修改后的完整代码如下:

private const int Keysize = 128;
private const int DerivationIterations = 10000;

public string Encrypt(string plainText, string passPhrase)
{
    var saltStringBytes = GenerateBitsOfRandomEntropy(16);
    var ivStringBytes = GenerateBitsOfRandomEntropy(16);
    var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
    // 显式指定SHA1和.NET5逻辑对齐
    using var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations, HashAlgorithmName.SHA1);
    var keyBytes = password.GetBytes(Keysize / 8);
    // 替换为Aes.Create,参数完全兼容原有RijndaelManaged配置
    using var symmetricKey = Aes.Create();
    symmetricKey.BlockSize = 128;
    symmetricKey.Mode = CipherMode.CBC;
    symmetricKey.Padding = PaddingMode.PKCS7;
    using var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes);
    using var memoryStream = new MemoryStream();
    using var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
    cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
    cryptoStream.FlushFinalBlock();
    var cipherTextBytes = saltStringBytes.Concat(ivStringBytes).Concat(memoryStream.ToArray()).ToArray();
    return Convert.ToBase64String(cipherTextBytes);
}

public string Decrypt(string cipherText, string passPhrase)
{
    var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText);
    var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray();
    var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray();
    var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).ToArray();
    // 显式指定SHA1和.NET5逻辑对齐
    using var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations, HashAlgorithmName.SHA1);
    var keyBytes = password.GetBytes(Keysize / 8);
    // 替换为Aes.Create,参数完全兼容原有RijndaelManaged配置
    using var symmetricKey = Aes.Create();
    symmetricKey.BlockSize = 128;
    symmetricKey.Mode = CipherMode.CBC;
    symmetricKey.Padding = PaddingMode.PKCS7;
    using var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes);
    using var memoryStream = new MemoryStream(cipherTextBytes);
    using var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
    using var streamReader = new StreamReader(cryptoStream, Encoding.UTF8);
    // 用StreamReader更简单可靠,避免手动处理字节计数的问题
    return streamReader.ReadToEnd();
}

private static byte[] GenerateBitsOfRandomEntropy(int size)
{
    var randomBytes = new byte[size];
    // 替换过时的RNGCryptoServiceProvider
    RandomNumberGenerator.Fill(randomBytes);
    return randomBytes;
}

验证说明

修改后:

  • 所有.NET5时期加密的历史数据均可正常解密
  • 新加密的数据逻辑和原有逻辑完全一致,无兼容性问题
  • 所有过时API警告全部消除,符合.NET6+的编码规范

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 15:54:05