.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()); }
关键修改说明
- 用
List<byte>替代固定长度的byte[],避免缓冲区大小限制导致的截断问题 - 通过循环调用
reader.Read,确保读取所有解密后的数据,直到返回0表示读取完成 - 每次读取后只保留实际读到的有效字节,避免混入空字节影响最终字符串转换
额外优化建议
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




