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

.NET 7解密加密字符串时出现内容截断问题求助

问题

将.NET Core 3.1中的字符串对称加解密代码迁移到.NET 7后,加密功能正常,但解密加密后的JSON字符串时,结果末尾会丢失6-8个字符;.NET Core 3.1中解密则能返回完整内容。加密结果在两个版本中一致,但解密结果存在差异。

原解密实现代码:

#region Settings

 private int _iterations = 2;
 private static int _keySize = 256;
 private string _hash = "SHA1";
 private string _salt = "xxx"; // Random
 private string _vector = "xxx"; // Random

 #endregion

 public string Run(string data, string key)
 {
     var jsonstring = Decrypt(data, key);
     return jsonstring;
 }


 private string Decrypt(string value, string password)
 {
     return Decrypt<AesManaged>(value, password);
 }

 private 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);

     byte[] decrypted;
     int decryptedByteCount = 0;

     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))
                     {
                         decrypted = new byte[valueBytes.Length];
                         decryptedByteCount = reader.Read(decrypted, 0, decrypted.Length);
                     }
                 }
             }
         }
         catch (Exception ex)
         {
             return String.Empty;
         }

         cipher.Clear();
     }

     var decrypt = Encoding.UTF8.GetString(decrypted, 0, decryptedByteCount);
     return decrypt;
 }
原因分析
  1. PasswordDeriveBytes跨版本行为差异:该类已被标记为过时,.NET 7与.NET Core 3.1中的实现存在细微差异,导致生成的密钥不完全一致,间接影响解密完整性。
  2. CryptoStream.Read单次调用的局限性:Read方法无法保证一次读取所有解密后的数据,.NET 7中CryptoStream的读取逻辑更严格,单次调用会导致部分末尾数据未被读取。
修复方案

1. 替换过时的密钥派生类

用Rfc2898DeriveBytes替代PasswordDeriveBytes,该类遵循PBKDF2标准,跨.NET版本行为一致,安全性更高。

2. 循环读取所有解密数据

不再依赖单次Read调用,改用CopyTo方法循环读取CryptoStream中的所有数据,确保解密内容完整。

修复后的解密方法代码:

private 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);

    using (T cipher = new T())
    {
        // 替换为Rfc2898DeriveBytes,参数与原逻辑对齐
        var deriveBytes = new Rfc2898DeriveBytes(password, saltBytes, _iterations, HashAlgorithmName.SHA1);
        byte[] keyBytes = deriveBytes.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))
            using (MemoryStream to = new MemoryStream())
            {
                // 读取所有解密后的数据
                reader.CopyTo(to);
                return Encoding.UTF8.GetString(to.ToArray());
            }
        }
        catch (Exception ex)
        {
            return string.Empty;
        }
    }
}

额外优化建议

  • 同步更新加密逻辑中的密钥派生类为Rfc2898DeriveBytes,确保新旧加密数据的密钥生成逻辑一致。
  • 替换AesManaged为Aes.Create(),AesManaged已过时,Aes.Create()能提供更好的跨版本兼容性与安全性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 11:04:51