我有一个独特的情况,我需要动态产生哈希。这是我的情况。此问题与here有关。我需要在数据库中存储许多需要编制索引的URL。一个URL可以超过2000个字符。数据库抱怨超过900字节的字符串无法编入索引。我的解决方案是使用MD5或SHA256散列URL。我不确定使用哪种哈希算法。这是我的要求
我并不担心安全问题。我担心角色长度,速度和碰撞。有人知道这个算法很好吗?
答案 0 :(得分:1)
在你的情况下,我不会使用任何加密哈希函数(即MD5,SHA),因为它们在设计时考虑了安全性:它们主要是想尽可能地使用它来创建两个不同的字符串相同的哈希。我认为这不会是你的问题。 (随机碰撞的可能性当然是散列所固有的)
我强烈建议使用String.GetHashCode()
,因为实现未知,MSDN表示它可能因框架的不同版本而异。甚至x86和x64版本之间的结果也可能不同。因此,当您尝试使用较新(或不同)版本的.NET框架访问同一数据库时,您会遇到麻烦。
我在维基百科(here)上找到了hashCode
的Java实现算法,它似乎很容易实现。即使是简单的实现也会比MD5或SHA imo的实现更快。您还可以使用long
值来降低碰撞的可能性。
还有对.NET GetHashCode
实现here的简短分析(不是算法本身,而是一些实现细节),我猜你也可以使用这个。 (或尝试以类似的方式实现Java版本......)
答案 1 :(得分:0)
我建议使用System.Security.Cryptography.SHA1Cng
课程。它是160位或20字节长,因此它应该足够小。如果你需要它是一个字符串,它只需要40个字符,所以这应该很适合你的需要。它也应该足够快,据我所知,还没有发现碰撞。
答案 2 :(得分:0)
我个人使用String.GetHashCode()。这是基本的哈希函数。老实说,与其他实现相比,我不知道它的表现如何,但应该没问题。
您命名的两个散列函数中的任何一个都应该足够快,以至于您不会注意到它们之间的差异。除非这个网站需要超高性能,否则我不会太担心它们。我个人可能会选择MD5。这可以格式化为64个字符的十六进制字符串或44个字符的基本64字符串。
我选择MD5的原因是因为你不太可能遇到冲突,即使你这样做,你也可以使用“where urlhash = @hash和url = @url”构建你的查询。数据库引擎应该确定一个是索引的而另一个不是索引,并使用该信息进行合理的搜索。
如果存在合并,则urlhash上的索引扫描将返回一些结果,这些结果很容易进行文本比较以获得正确的结果。但这不太可能经常发生。你以这种方式获得碰撞的可能性很小。
答案 3 :(得分:0)
URLString.GetHashCode().ToString("x")
答案 4 :(得分:0)
虽然MD5和SHA1都被证明无效,但防撞是必不可少的,我怀疑你的应用是否足够。我不确定,但我怀疑MD5会更简单,更快捷。
答案 5 :(得分:0)
.net 4.0中反映了GetHashCode函数的源代码
public override unsafe int GetHashCode()
{
fixed (char* str = ((char*) this))
{
char* chPtr = str;
int num = 0x15051505;
int num2 = num;
int* numPtr = (int*) chPtr;
for (int i = this.Length; i > 0; i -= 4)
{
num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
if (i <= 2)
{
break;
}
num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
numPtr += 2;
}
return (num + (num2 * 0x5d588b65));
}
}
存在O(n)个简单运算(+,&lt;&lt;,^)和一个乘法。所以这很快。
我在3毫升DB上测试了这个功能,包含长度不超过256个字符的字符串,大约97%的字符串没有冲突。 (最多5个字符串具有相同的哈希值)
答案 6 :(得分:0)
您可能需要查看以下项目:
CMPH - C Minimal Perfect Hashing Library
查看以下热门话题列表中的完美哈希:
Hottest 'perfect-hash' Answers - Stack Overflow
您还可以考虑在SQL中使用全文索引而不是哈希: