我写了以下内容SQL CLR
函数,以散列大于 8000 字节的字符串值(输入值的限制T-SQL
内置的HASHBYTES
功能):
[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true)]
public static SqlBinary HashBytes(SqlString algorithm, SqlString value)
{
HashAlgorithm algorithmType = HashAlgorithm.Create(algorithm.Value);
if (algorithmType == null || value.IsNull)
{
return new SqlBinary();
}
else
{
byte[] bytes = Encoding.UTF8.GetBytes(value.Value);
return new SqlBinary(algorithmType.ComputeHash(bytes));
}
}
它对于拉丁字符串工作得很好。例如,以下哈希值是相同的:
SELECT dbo.fn_Utils_GetHashBytes ('MD5', 'test'); -- 0x098F6BCD4621D373CADE4E832627B4F6
SELECT HASHBYTES ('MD5', 'test'); -- 0x098F6BCD4621D373CADE4E832627B4F6
问题是它不适用于西里尔字符串。例如:
SELECT dbo.fn_Utils_GetHashBytes ('MD5 ', N'даровете на влъхвите') -- NULL
SELECT HashBytes ('MD5 ',N'даровете на влъхвите') -- 0x838B1B625A6074B2BE55CDB7FCEA2832
SELECT dbo.fn_Utils_GetHashBytes ('SHA256', N'даровете на влъхвите') -- 0xA1D65374A0B954F8291E00BC3DD9DF655D8A4A6BF127CFB15BBE794D2A098844
SELECT HashBytes ('SHA2_256',N'даровете на влъхвите') -- 0x375F6993E0ECE1864336E565C8E14848F2A4BAFCF60BC0C8F5636101DD15B25A
我正进入(状态NULL
for MD5
,尽管代码如果作为控制台应用程序执行则返回值。谁能告诉我我做错了什么吗?
另外,我得到了来自的功能here https://stackoverflow.com/a/9327704/1080354其中一条评论说:
小心 CLR SP 参数被静默截断为 8000 字节
- 我必须用 [SqlFacet(MaxSize = -1)] 标记参数,否则第 8000 个之后的字节将被忽略!
但我已经测试过它并且工作正常。例如,如果我生成 8000 字节字符串的哈希值和同一字符串加一个符号的第二个哈希值,我会得到不同的哈希值。
DECLARE @A VARCHAR(MAX) = '8000 bytes string...'
DECLARE @B VARCHAR(MAX) = @A + '1'
SELECT LEN(@A), LEN(@B)
SELECT IIF(dbo.fn_Utils_GetHashBytes ('MD5', @A + '1') = dbo.fn_Utils_GetHashBytes ('MD5', @B), 1, 0) -- 0
我应该担心这个吗?