为什么C#与SQL Server对Uniqueidentifier的SHA1哈希结果不匹配
问题原因分析
- 核心原因:两端使用的字符串编码不一致
C#代码中是把GUID转成字符串后用Encoding.UTF8.GetBytes()获取字节流,每个英文字符占1字节;而SQL Server里nvarchar类型为UTF-16LE编码,每个字符占2字节,输入给哈希函数的原始字节流完全不同,自然得到的哈希结果不一致。 - 次要原因:GUID转字符串的默认格式存在差异
C#中Guid.ToString()默认输出小写的带连字符GUID字符串,而SQL Server中CONVERT(nvarchar(50), uniqueidentifier)默认输出大写的同格式字符串,字符内容本身存在大小写区别,就算编码统一也会得到不同哈希。
两端哈希对齐方案
方案1:C#侧适配SQL侧规则
C#代码统一使用UTF-16LE编码,同时把字符串转成大写和SQL输出对齐:
using (SHA1Managed sha1 = new SHA1Managed()) { Guid g = new Guid("81FE483B-39ED-4052-8FFC-55A710907D9B"); var appGateId = g.ToString().ToUpper(); // Encoding.Unicode对应UTF-16LE编码,和SQL的nvarchar编码一致 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().ToUpper()); }
运行后输出结果和SQL侧的CC34B1E702F6E7FE0EE92ED4D5390BB4765B9A21完全一致。
方案2:SQL侧适配C#侧规则
SQL侧统一使用UTF-8编码(SQL Server 2019及以上版本原生支持),同时把字符串转成小写和C#输出对齐:
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), 2)
运行后输出结果和C#侧的ebb52fefab48f428b6ee03174276c8ade0b4ef1a完全一致。
内容的提问来源于stack exchange,提问作者Shruti Singh
相关产品推荐
相关产品推荐

