基于 .net ComputeHash 的 SQL CLR 函数不适用于西里尔语

2024-02-04

我写了以下内容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

我应该担心这个吗?


 Encoding.UTF8.GetBytes(...)

SQL Server 没有 UTF-8 的概念。使用 UCS-2 (UTF-16) 或 ASCII。使用的编码必须与您传递给的编码相匹配HASHBYTES。你可以很容易地看到HASHBYTES会有不同的哈希值VARCHAR vs. NVARCHAR:

select HASHBYTES('MD5', 'Foo')  -- 0x1356C67D7AD1638D816BFB822DD2C25D
select HASHBYTES('MD5', N'Foo') -- 0xB25FF0AD90D09D395090E8A29FF4C63C

最好的办法是更改 SQLCLR 函数以接受字节,而不是字符串,并处理转换为VARBINARY在呼叫者中。

 SELECT dbo.fn_Utils_GetHashBytes ('MD5', CAST(N'даровете на влъхвите' AS VARBINARY(MAX));

仅供参考 SQL Server 2016 取消了 8000 字节的限制HASHBYTES https://msdn.microsoft.com/en-us/library/ms174415.aspx:

For SQL Server 2014 及更早版本,允许的输入值限制为 8000 字节。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于 .net ComputeHash 的 SQL CLR 函数不适用于西里尔语 的相关文章

  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • 如何从 Visual Studio 将视图导航到其控制器?

    问题是解决方案资源管理器上有 29 个项目 而且项目同时具有 ASP NET MVC 和 ASP NET Web 表单结构 在MVC部分中 Controller文件夹中有大约100个子文件夹 每个文件夹至少有3 4个控制器 视图完全位于不同
  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • 无限循环与无限递归。两者都是未定义的吗?

    无副作用的无限循环是未定义的行为 看here https coliru stacked crooked com view id 24e0a58778f67cd4举个例子参考参数 https en cppreference com w cpp
  • 需要帮助优化算法 - 两百万以下所有素数的总和

    我正在尝试做一个欧拉计划 http projecteuler net问题 我正在寻找 2 000 000 以下所有素数的总和 这就是我所拥有的 int main int argc char argv unsigned long int su
  • 重载 (c)begin/(c)end

    我试图超载 c begin c end类的函数 以便能够调用 C 11 基于范围的 for 循环 它在大多数情况下都有效 但我无法理解和解决其中一个问题 for auto const point fProjectData gt getPoi
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • C# xml序列化必填字段

    我需要将一些字段标记为需要写入 XML 文件 但没有成功 我有一个包含约 30 个属性的配置类 这就是为什么我不能像这样封装所有属性 public string SomeProp get return someProp set if som
  • C 编程:带有数组的函数

    我正在尝试编写一个函数 该函数查找行为 4 列为 4 的二维数组中的最大值 其中二维数组填充有用户输入 我知道我的主要错误是函数中的数组 但我不确定它是什么 如果有人能够找到我出错的地方而不是编写新代码 我将不胜感激 除非我刚去南方 我的尝
  • 引用的程序集自动由 Visual Studio 替换

    我有 2 个项目 一个可移植类库和一个常规单元测试项目 在可移植类库中 我使用 NuGet 来引用 Microsoft BCL 可移植包 它附带 2 个程序集 System Threading Tasks dll and System Ru
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • 如何在 Android 中使用 C# 生成的 RSA 公钥?

    我想在无法假定 HTTPS 可用的情况下确保 Android 应用程序和 C ASP NET 服务器之间的消息隐私 我想使用 RSA 来加密 Android 设备首次联系服务器时传输的对称密钥 RSA密钥对已在服务器上生成 私钥保存在服务器
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • C++ 中的参考文献

    我偶尔会在 StackOverflow 上看到代码 询问一些涉及函数的重载歧义 例如 void foo int param 我的问题是 为什么会出现这种情况 或者更确切地说 你什么时候会有 对参考的参考 这与普通的旧参考有何不同 我从未在现
  • C# 使用“?” if else 语句设置值这叫什么

    嘿 我刚刚看到以下声明 return name null name NA 我只是想知道这在 NET 中叫什么 是吗 代表即然后执行此操作 这是一个俗称的 条件运算符 三元运算符 http en wikipedia org wiki Tern
  • 指针和内存范围

    我已经用 C 语言编程有一段时间了 但对 C 语言还是很陌生 有时我对 C 处理内存的方式感到困惑 考虑以下有效的 C 代码片段 const char string void where is this pointer variable l

随机推荐