C# 哈希 SHA256Managed 不等于 TSQL SHA2_256
本文关键字:SHA2 TSQL 不等于 哈希 SHA256Managed | 更新日期: 2023-09-27 18:34:12
我正在使用带有盐(用户名)的散列密码。
问题是 c# 的哈希值不等于我通过 TSQL 脚本添加到数据库的初始值。
TSQL:
UPDATE [Users]
SET Password = HASHBYTES('SHA2_256', 'test123'+UPPER([UserName]))
GO;
C#:
var passBytes = new UnicodeEncoding().GetBytes(pass);
var saltBytes = new UnicodeEncoding().GetBytes(userName.ToUpper());
var dataToHash = new byte[passBytes.Length + saltBytes.Length];
Array.Copy(passBytes, dataToHash, passBytes.Length);
Array.Copy(saltBytes, dataToHash, saltBytes.Length);
var sha = new SHA256Managed();
return sha.ComputeHash(dataToHash);
我想这与编码有关。但我不知道如何解决这个问题。
用户名是 varchar(50)
数据库是现有的数据库,因此更改 varchar 不会那么容易。
我已经尝试过:
UPDATE [Users]
SET Password = HASHBYTES('SHA2_256', N'test123'+UPPER([UserName]))
GO;
在努力让它工作之后,以下是我最终开始工作的示例:
public string Hash(string input)
{
using (SHA256 hasher = SHA256.Create())
{
// Convert the input string to a byte array and compute the hash.
byte[] data = hasher.ComputeHash(Encoding.Unicode.GetBytes(input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("X2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
}
TSQL
declare @input as nvarchar(max) = 'Test';
select @input;
declare @hash as varbinary(max) = HASHBYTES('SHA2_256', @input );
select @hash;
declare @result as nvarchar(max) = CONVERT(NVARCHAR(MAX), @hash, 2);
select @result;
这些将产生相同的结果。
请注意,这是使用 nvarchar 数据类型,而不是 varchar。
如果将 SQL Server 数据库配置为使用默认的排序规则SQL_Latin1_General_CP1_CI_AS,则在 C# 代码中,使用代码页 1252 将字符转换为字节。因此,相当于
HASHBYTES('SHA2_256', 'test123' + UPPER([UserName]))
是
byte[] data = Encoding.GetEncoding(1252).GetBytes("test123" + userName.ToUpper());
var sha = new SHA256Managed();
byte[] hash = sha.ComputeHash(data);
哈希
处理字节,而不是字符。你正在做的是Hash(StringToBytes(str))
.您的StringToBytes
步骤是不同的。在 SQL 中,使用 ANSI varchar
字符串,在 C# UTF-16 字符串中使用。决定你想要哪一个并使用它。我推荐Unicode(nvarchar
)。
Encoding.UTF8.GetBytes(input)
= HASHBYTES('SHA2_256', @varcharVariable);
Encoding.Unicode.GetBytes(input)
= HASHBYTES('SHA2_256', @nvarcharVariable);