【发布时间】:2020-01-14 10:37:02
【问题描述】:
我有一个 .NET 函数 MD5,它在“146.185.59.178acu-cell.com”上运行时返回 f36674ed3dbcb151e1c0dfe4acdbb9f5
public static String MD5(String s)
{
using (var provider = System.Security.Cryptography.MD5.Create())
{
StringBuilder builder = new StringBuilder();
foreach (Byte b in provider.ComputeHash(Encoding.UTF8.GetBytes(s)))
builder.Append(b.ToString("x2").ToLower());
return builder.ToString();
}
}
我在 TSQL 中编写了相同的代码,但由于某种原因,只有 varchar 返回了预期的结果。 nvarchar 返回不同的 md5:f04b83328560f1bd1c08104b83bc30ea
declare @v varchar(150) = '146.185.59.178acu-cell.com'
declare @nv nvarchar(150) = '146.185.59.178acu-cell.com'
select LOWER(CONVERT(VARCHAR(32), HashBytes('MD5', @v), 2))
--f36674ed3dbcb151e1c0dfe4acdbb9f5
select LOWER(CONVERT(VARCHAR(32), HashBytes('MD5',@nv), 2))
--f04b83328560f1bd1c08104b83bc30ea
不确定这里发生了什么,因为我确实希望 nvarchar 返回 f36674ed3dbcb151e1c0dfe4acdbb9f5 就像在 .NET 中一样
【问题讨论】:
-
你应该真的停止使用md5;这不是一个安全的哈希。根据HASHBYTES (Transact-SQL):“从 SQL Server 2016 (13.x) 开始,不推荐使用 MD2、MD4、MD5、SHA 和 SHA1 算法。改用 SHA2_256 或 SHA2_512。旧算法将继续工作,但它们会引发弃用事件。”
-
另外,您为什么希望
varchar和nvarchar的哈希值相同?它们不是相同的数据类型。 -
但确实如此,@IanKemp。包含相同字符的
nvarchar值和varchar值not 具有相同的值。像'I believe varchar and nvarchar are the same' = N'I believe varchar and nvarchar are the same'这样的东西会返回true 的唯一原因是varchar首先隐式 转换为nvarchar。如果您要比较它们的基础(二进制)值,它们将不相同。 -
@Larnu 是的,我有一个暂时的脑残 ;)
-
另请注意,SQL Server(2019 年之前的版本)不支持 UTF-8,因此,如果您包含除普通旧 ASCII 字符之外的任何内容,即使使用
VARCHAR,您也会看到差异 - - 通常的默认 (Latin1_) 排序规则更像 Windows-1252。使用Encoding.Unicode至少与NVARCHAR保持一致。