You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

.NET 5升级至.NET 6后AES加密服务解密返回不完整文本问题求助

解决.NET 6中AES解密文本不完整的问题

你的问题根源在于解密时只调用了一次CryptoStream.Read方法Read并不保证一次性读取所有可用数据——它只会返回当前能读取的字节数,剩余数据需要循环读取直到返回0。在.NET 5中可能因为流实现的特性刚好能一次性读全,但.NET 6对流的处理逻辑更严谨,这个潜在问题就暴露出来了。

修复后的解密方法

修改Decrypt<T>方法,把一次性读取改成循环读取,动态收集所有解密后的字节:

private static string Decrypt<T>(string value, string password) where T : SymmetricAlgorithm, new()
{
    byte[] vectorBytes = Encoding.UTF8.GetBytes(_vector);
    byte[] saltBytes = Encoding.UTF8.GetBytes(_salt);
    byte[] valueBytes = Convert.FromBase64String(value);
    List<byte> decryptedBytes = new List<byte>(); // 用List动态收集解密后的字节

    using (T cipher = new T())
    {
        PasswordDeriveBytes _passwordBytes = new PasswordDeriveBytes(password, saltBytes, _hash, _iterations);
        byte[] keyBytes = _passwordBytes.GetBytes(_keySize / 8);

        cipher.Mode = CipherMode.CBC;

        try
        {
            using (ICryptoTransform decryptor = cipher.CreateDecryptor(keyBytes, vectorBytes))
            {
                using (MemoryStream from = new MemoryStream(valueBytes))
                {
                    using (CryptoStream reader = new CryptoStream(from, decryptor, CryptoStreamMode.Read))
                    {
                        byte[] buffer = new byte[1024]; // 定义固定大小的缓冲区,可按需调整
                        int bytesRead;
                        // 循环读取直到没有更多数据
                        while ((bytesRead = reader.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            decryptedBytes.AddRange(buffer.Take(bytesRead)); // 只添加实际读取到的有效字节
                        }
                    }
                }
            }
        }
        catch (Exception)
        {
            return String.Empty;
        }
        cipher.Clear();
    }
    return Encoding.UTF8.GetString(decryptedBytes.ToArray());
}

关键修改说明

  1. List<byte>替代固定长度的byte[],避免缓冲区大小限制导致的截断问题
  2. 通过循环调用reader.Read,确保读取所有解密后的数据,直到返回0表示读取完成
  3. 每次读取后只保留实际读到的有效字节,避免混入空字节影响最终字符串转换

额外优化建议

PasswordDeriveBytes在.NET 5+中已被标记为过时,推荐使用更符合现代密码学标准的Rfc2898DeriveBytes替代,替换后的密钥生成代码如下:

// 替换原来的PasswordDeriveBytes代码块
using (Rfc2898DeriveBytes passwordBytes = new Rfc2898DeriveBytes(password, saltBytes, _iterations, HashAlgorithmName.SHA1))
{
    byte[] keyBytes = passwordBytes.GetBytes(_keySize / 8);
    // 后续加密/解密逻辑保持不变
}

修改后重新运行测试案例,所有长文本都能完整解密并匹配原始内容了。

内容的提问来源于stack exchange,提问作者Silvair L. Soares

火山引擎 最新活动