SQL Uniqueidentifier 和 hashbytes 与 c# 不匹配

SQL Uniqueidentifier and hashbytes does not match with c#

在 SQL 服务器中使用 C# 创建哈希是不同的。为什么不一样?

using (SHA1Managed sha1 = new SHA1Managed())
{
    Guid g = new Guid("81FE483B-39ED-4052-8FFC-55A710907D9B");
    var appGateId = g.ToString();
    
    var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(appGateId));
    var sb = new StringBuilder();

    foreach (byte b in hash)
    {
        sb.Append(b.ToString("x2"));
    }

    Console.WriteLine(sb.ToString());
}

这里的结果是ebb52fefab48f428b6ee03174276c8ade0b4ef1a.

使用 SQL 服务器和此代码:

declare @a uniqueidentifier = '81FE483B-39ED-4052-8FFC-55A710907D9B', @b nvarchar(50)

select @b = CONVERT(nvarchar(50), @a)
select convert(varchar(50), hashbytes('SHA1', @b), 2)

结果是CC34B1E702F6E7FE0EE92ED4D5390BB4765B9A21

@Marc Gravell的评论说明了这里的问题。在 C# 中,您使用的是 UTF-8 字符串,但在 SQL 服务器中,您使用的是 nvarchar,它是 UTF-16;这些没有可比性。

但是,如果您实际使用 varchar,并将字符更改为小写(因为在 T-[=21 中转换为基于字符串的数据类型时,uniqueidentifier 会更改为大写=]) 你 do 得到相同的值。您也可以(如果您使用的是 2019 年以上)将该值显式整理为 UTF-8 值,但考虑到 GUID 仅由十六进制字符 (0-9A-F) 组成,这似乎有点毫无意义:

DECLARE @a uniqueidentifier = '81FE483B-39ED-4052-8FFC-55A710907D9B', @b varchar(50);
SELECT @b = LOWER(CONVERT(varchar(50), @a));

SELECT @b, LOWER(CONVERT(varchar(50), HASHBYTES('SHA1', @b), 2));

要使它们相等,您有两个问题:

  • 如前所述,您请求的是 UTF-8,SQL 服务器使用的是 UTF-16
  • C# 生成小写,SQL 服务器大写

您可以更改 C# 代码

using (SHA1Managed sha1 = new SHA1Managed())
{
    Guid g = new Guid("81FE483B-39ED-4052-8FFC-55A710907D9B");
    var appGateId = g.ToString().ToUpper().Dump();

    var hash = sha1.ComputeHash(Encoding.Unicode.GetBytes(appGateId));
    var sb = new StringBuilder();

    foreach (byte b in hash)
    {
        sb.Append(b.ToString("x2"));
    }

    Console.WriteLine(sb.ToString());
}

dotnetfiddle

或者您可以更改 SQL 服务器代码

declare @a uniqueidentifier = '81FE483B-39ED-4052-8FFC-55A710907D9B', @b varchar(50)

select @b = LOWER(CONVERT(varchar(50), @a))
select convert(varchar(50), hashbytes('SHA1', @b COLLATE Latin1_General_100_BIN2_UTF8 ), 2)

db<>fiddle


老实说,我不明白你为什么要散列 字符串表示形式 。您可以轻松地散列实际的 Guid 字节。