首页 > 解决方案 > 使用 UTF8 生成 TSQL MD5

问题描述

我有一个 .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像在 .NET 中一样返回f36674ed3dbcb151e1c0dfe4acdbb9f5

标签: c#.nettsql

解决方案


您会得到不同的哈希值,因为文本的二进制表示不同。以下查询演示了这一点:

declare @v  varchar(150)  = '146.185.59.178acu-cell.com'
declare @nv nvarchar(150) = '146.185.59.178acu-cell.com'

select convert(varbinary(max), @v)  -- 0x3134362E3138352E35392E3137386163752D63656C6C2E636F6D
select convert(varbinary(max), @nv) -- 0x3100340036002E003100380035002E00350039002E003100370038006100630075002D00630065006C006C002E0063006F006D00

额外的 0 字节nvarchar是由于它是 2 字节 Unicode 数据类型。有关 SQL Server 中 Unicode 的详细信息,请参阅 MSDN。


推荐阅读