Case不区分大小写的字符串哈希(SHA)

Ern*_*ieL 2 c# hash search

我将名称字符串及其SHA1值传递到数据库中.SHA值用作搜索的索引.实现完成后,我们要求使搜索名称不区分大小写.我们确实需要考虑所有语言(汉字是一个真实的用例).

我知道土耳其测试.如何在散列之前将输入字符串转换为不区分大小写?理想情况下,我希望它等同于InvariantCultureIgnoreCase.

换句话说,如何使此函数的输出不区分大小写?

private byte[] ComputeHash(string s)
{
     byte[] data = System.Text.Encoding.Unicode.GetBytes(s ?? string.Empty);
     SHA1 sha = new SHA1CryptoServiceProvider();     // returns 160 bit value
     return sha.ComputeHash(data);
}
Run Code Online (Sandbox Code Playgroud)

如果SHA不可能,我可能能够使String.GetHashCode()工作,但我也没有办法让这种情况不敏感.

我打赌这是不可能的.如果不是,有什么工作吗?

usr*_*usr 7

建议使用ToLower(Invariant)的现有答案是错误的:在执行ToLower之后比较字符串等于执行string.Compare(xxxIgnoreCase).请参阅此处接受的答案:字符串比较 - strA.ToLower()== strB.ToLower()或strA.Equals(strB,StringComparisonType)?它会因某些角色而崩溃.

解决方案是为每个字符串创建一个所谓的SortKey.这样的SortKey本质上是一个字节数组,其属性等于字节意味着相等的字符串.(另外,SortKeys可以以二进制方式进行比较,产生与string.Compare完全相同的顺序.但是我们这里不需要该属性).

简介:使用CompareInfo.GetSortKey(string).KeyData获取可清除的byte [].(MSDN上的GetSortKey)这适用于所有可能的文化.它也适用于不区分大小写的情况.

因此,对于任何给定字符串(即使使用土耳其语i),不区分大小写的哈希可以通过以下方式获得:

var sortKeyBytes = CultureInfo.InvariantCulture.CompareInfo.GetSortKey(anyString,
    CompareOptions.IgnoreCase).KeyData;
int hashCode = HashByteArray(sortKeyBytes); //Need to provide this function.
...
Run Code Online (Sandbox Code Playgroud)

我们不能使用byte []的GetHashCode(),因为这个方法没有被覆盖byte[],因此默认object.GetHashCode()使用对象标识而不是值.

您可以使用此答案中的哈希函数.这不好,但它完成了这项工作.


Ter*_*ver 6

您可以在生成哈希之前使用s.ToUpperInvariant().只要你两种方式(生成原始哈希,并生成一个哈希来测试原始哈希),它就会起作用.