在SQL server中创建哈希是不同的。为什么不一样呢?
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 Server和以下代码:
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 Server中,您使用的是nvarchar
,这是UTF-16;这些是不可比较的。
varchar
,并将字符更改为小写(正如在T-SQL中转换为基于字符串的数据类型时将uniqueidentifier
更改为大写),则确实得到相同的值。您可以(如果您在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 Server正在使用UTF-16
- c#用小写生成,SQL Server用大写生成
你可以修改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 Server代码
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<的在小提琴
老实说,我不明白你为什么要散列字符串表示。您也可以简单地散列实际的Guid字节。