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

.NET Core 6与.NET 4.5上ASP.NET MVC的加解密差异及适配问题

.NET 6与.NET 4.5解密结果不一致的修复方案

问题根源

  1. PasswordDeriveBytes实现差异:.NET Framework 4.5中的PasswordDeriveBytes默认使用PBKDF1算法,而.NET 6中该类已过时且内部改用PBKDF2,导致生成的密钥字节数组完全不同。
  2. CryptoStream.Read行为变化:.NET 6中CryptoStream.Read不会一次性返回所有解密数据,单次调用仅读取部分字节,直接导致解密内容不完整。
  3. RijndaelManaged已过时:.NET 6中RijndaelManaged被标记为过时,官方推荐使用标准Aes算法实现,避免潜在的兼容性问题。

具体修改步骤

1. 替换PasswordDeriveBytes为兼容的PBKDF1实现

由于.NET 6不再原生支持PBKDF1的密钥生成逻辑,需要手动实现匹配.NET 4.5的PBKDF1流程:

// 替换原PasswordDeriveBytes代码段
byte[] salt = Array.Empty<byte>(); // 对应原代码salt为null的情况
int iterations = 100; // .NET 4.5 PasswordDeriveBytes默认迭代次数
using (HashAlgorithm hashAlgorithm = SHA1.Create())
{
    byte[] passPhraseBytes = Encoding.UTF8.GetBytes(passPhrase);
    byte[] combinedBytes = new byte[passPhraseBytes.Length + salt.Length];
    passPhraseBytes.CopyTo(combinedBytes, 0);
    salt.CopyTo(combinedBytes, passPhraseBytes.Length);

    byte[] hash = hashAlgorithm.ComputeHash(combinedBytes);
    for (int i = 1; i < iterations; i++)
    {
        hash = hashAlgorithm.ComputeHash(hash);
    }

    byte[] keyBytes = new byte[keysize / 8];
    Array.Copy(hash, keyBytes, keyBytes.Length);
    // 后续密钥使用逻辑不变
}

2. 修复CryptoStream.Read的读取逻辑

将单次读取改为循环读取或使用CopyTo方法,确保获取全部解密字节:

// 替换原CryptoStream内的读取代码段
using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes))
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
using (MemoryStream plainStream = new MemoryStream())
{
    cryptoStream.CopyTo(plainStream);
    decryptedArray.Add(Encoding.UTF8.GetString(plainStream.ToArray()));
}

或者使用循环读取的方式:

byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int totalBytesRead = 0;
int bytesRead;
while ((bytesRead = cryptoStream.Read(plainTextBytes, totalBytesRead, plainTextBytes.Length - totalBytesRead)) > 0)
{
    totalBytesRead += bytesRead;
}
decryptedArray.Add(Encoding.UTF8.GetString(plainTextBytes, 0, totalBytesRead));

3. 替换RijndaelManaged为Aes算法

使用.NET 6推荐的Aes.Create()替代过时的RijndaelManaged,保持参数配置与原代码一致:

// 替换原RijndaelManaged代码段
using (Aes symmetricKey = Aes.Create())
{
    symmetricKey.Mode = CipherMode.CBC;
    symmetricKey.Key = keyBytes;
    symmetricKey.IV = initVectorBytes;
    symmetricKey.Padding = PaddingMode.PKCS7; // 匹配RijndaelManaged默认填充模式
    // 后续解密逻辑不变
}

完整修改后的Decrypt方法

public static Dictionary<string, string> Decrypt(string[] cipherTexts, string passPhrase)
{
    var decryptedValues = new Dictionary<string, string>();

    if (cipherTexts == null || cipherTexts.Length == 0 || string.IsNullOrEmpty(passPhrase))
    {
        return decryptedValues;
    }

    cipherTexts = cipherTexts.Where(q => !string.IsNullOrEmpty(q))
                             .Distinct().ToArray();

    byte[] salt = Array.Empty<byte>();
    int iterations = 100;
    using (HashAlgorithm hashAlgorithm = SHA1.Create())
    {
        byte[] passPhraseBytes = Encoding.UTF8.GetBytes(passPhrase);
        byte[] combinedBytes = new byte[passPhraseBytes.Length + salt.Length];
        passPhraseBytes.CopyTo(combinedBytes, 0);
        salt.CopyTo(combinedBytes, passPhraseBytes.Length);

        byte[] hash = hashAlgorithm.ComputeHash(combinedBytes);
        for (int i = 1; i < iterations; i++)
        {
            hash = hashAlgorithm.ComputeHash(hash);
        }

        byte[] keyBytes = new byte[keysize / 8];
        Array.Copy(hash, keyBytes, keyBytes.Length);

        using (Aes symmetricKey = Aes.Create())
        {
            symmetricKey.Mode = CipherMode.CBC;
            symmetricKey.Key = keyBytes;
            symmetricKey.IV = initVectorBytes;
            symmetricKey.Padding = PaddingMode.PKCS7;

            using (ICryptoTransform decryptor = symmetricKey.CreateDecryptor())
            {
                foreach (var cipherTextOrig in cipherTexts)
                {
                    var cipherTextFixed = cipherTextOrig.Trim(',').Replace("-", "+").Replace("_", "/");
                    var decryptedArray = new List<string>();

                    foreach (var cipherText in cipherTextFixed.Split(','))
                    {
                        byte[] cipherTextBytes = Convert.FromBase64String(cipherText);

                        using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes))
                        using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
                        using (MemoryStream plainStream = new MemoryStream())
                        {
                            cryptoStream.CopyTo(plainStream);
                            decryptedArray.Add(Encoding.UTF8.GetString(plainStream.ToArray()));
                        }
                    }

                    decryptedValues.Add(cipherTextOrig, string.Join(",", decryptedArray));
                }
            }
        }
    }

    return decryptedValues;
}

注意:需确保keysize和initVectorBytes的定义与原.NET 4.5代码完全一致,否则仍会出现解密结果差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 01:45:20