C# 哈希 SHA256Managed 不等于 TSQL SHA2_256

问题描述 投票:0回答:5

我使用带盐(用户名)的哈希密码。

问题是 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;
c# sql-server t-sql encoding hash
5个回答
13
投票

在努力让它工作之后,这是我最终开始工作的示例:

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。


11
投票

如果您的 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);

5
投票

哈希值适用于字节,而不适用于字符。你正在做的是

Hash(StringToBytes(str))
。您的
StringToBytes
步骤有所不同。在 SQL 中,您使用 ANSI
varchar
字符串,而在 C# 中则使用 UTF-16 字符串。决定你想要哪一个并使用它。我推荐 Unicode (
nvarchar
)。


0
投票

.Net 8 - 2024

当我寻找答案时,没有太多最新数据,而且没有一个接近。对副驾驶查询进行一些调整后,我发现它的效果就像冠军一样。

public static byte[] HashPassword5(string userName, string password)
{
  var bytes = Encoding.Unicode.GetBytes($"{userName}{Your-Salt}{password}");

  return SHA256.HashData(bytes);
}

当然,您的

bytes
值可能会有不同的构造。但无论如何,请将
Your-Salt
替换为您实际的盐字符串。

另外,SQL Server 的结果是:

0x001CE6A014B7C918B0CE40C68D411EB003E0407970E5E27131DF1C33A81FA5FD

C# 结果是:

001CE6A014B7C918B0CE40C68D411EB003E0407970E5E27131DF1C33A81FA5FD
.

请注意,SQL 结果的唯一区别是 0x 前缀。


-1
投票

Encoding.UTF8.GetBytes(input)
=
HASHBYTES('SHA2_256', @varcharVariable);

Encoding.Unicode.GetBytes(input)
=
HASHBYTES('SHA2_256', @nvarcharVariable);

© www.soinside.com 2019 - 2024. All rights reserved.