我在.net core 3.1中实现了字符串对称加密和解密的方法。现在我正在将一个项目从 .net core 3.1 迁移到 .net 7。加密工作正常,但是当我在 .net 7 实现中解密加密值(JSON 字符串)时,它会缩短结果字符串。 .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;
}
我在 .net core 3.1 和 .net7 中进行了测试,并加密和解密了我的示例字符串。 加密工作正常,我得到了相同的加密值。 .net core 3.1中的解密返回完整的初始值。 .net 7 中的解密返回初始值的较短版本(使用不同的字符串进行测试)。最后 6 到 8 个字符现在丢失了。
由于 DeflateStream、GZipStream 和 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);
string result = string.Empty;
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 memoryStream = new MemoryStream(valueBytes))
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
byte[] decryptedData = new byte[valueBytes.Length];
int bytesRead;
int offset = 0;
while ((bytesRead = cryptoStream.Read(decryptedData, offset, decryptedData.Length - offset)) > 0)
{
offset += bytesRead;
// If the offset reaches the end of the buffer, resize the buffer to accommodate more data
if (offset == decryptedData.Length)
{
Array.Resize(ref decryptedData, decryptedData.Length * 2);
}
}
Array.Resize(ref decryptedData, offset);
result = Encoding.UTF8.GetString(decryptedData);
}
}
catch (Exception ex)
{
return String.Empty;
}
cipher.Clear();
}
return result;
}