将MD5转换为长整型

3

我有一个16字节的数组,是从MD5 JAVA方法得到的。我想将它转换为long类型以用作哈希键。对64位进行按位异或操作是一个好主意...然后如何从中获取long类型的值?请提供完整的按位异或和转换为long类型的代码示例。


如果你采用XOR方法,你只需要将一半的字节与另一半进行XOR运算,因为long类型是64位,比长度为16的字节数组中的位数少一半。更具体地说:你可以对最高的8个字节和最低的8个字节进行XOR运算。 - Matt Ball
3个回答

5
我发现的最好的解决方案(根据我的需求...速度和良好的哈希函数的混合)是Google的CityHash。输入可以是任何字节数组,包括MD5结果,输出是无符号64位长整型。
CityHash具有非常好但不完美的哈希分布,并且非常快。
我在半小时内将CityHash从C++移植到了C#。Java端口也应该很简单。
仅仅异或位并不能给出很好的分布(尽管这样做会非常快)。
我对Java不够熟悉,无法准确地告诉您如何从字节数组中填充长整型(可能有一些我不熟悉的好帮手,或者我在Java中进行算术运算时可能会出现一些细节问题)。然而,您需要类似于这样做:
long a = md5[0] + 
         256 * md5[1] + 
         256 * 256 * md5[2] + 
         256 * 256 * 256 * md5[3] + 
         256 * 256 * 256 * 256 * md5[4] + 
         256 * 256 * 256 * 256 * 256 * md5[5] +
         256 * 256 * 256 * 256 * 256 * 256 * md5[6] +
         256 * 256 * 256 * 256 * 256 * 256 * 256 * md5[7];

long b = md5[8] + 
         256 * md5[9] + 
         256 * 256 * md5[10] + 
         256 * 256 * 256 * md5[11] + 
         256 * 256 * 256 * 256 * md5[12] + 
         256 * 256 * 256 * 256 * 256 * md5[13] +
         256 * 256 * 256 * 256 * 256 * 256 * md5[14] +
         256 * 256 * 256 * 256 * 256 * 256 * 256 * md5[15];

long result = a ^ b;

请注意,我没有试图处理endianness。但是,如果您只关心在特定平台上获得一致的哈希值,则大小端字节序不应该影响。


CityHash 在其算法中广泛使用了 Java 不支持的 SSE4 扩展。 - Alan Jurgensen
@Alan:据我所知,它们在C#中也不可用,但是从C#调用C++版本的速度几乎与C#版本相同(因此SSE4的损失并不比Interop调用更昂贵)。 - Eric J.
你应该查看Guava的哈希 - Adam Gent
这是不正确的。long类型占用8个字节,而这个解决方案只设置了long类型中最低有效的4个字节。如果你想将MD5转换为int类型,那么这是一个足够好的解决方案,但这不是问题所在。 - oscfri

4

Guava拥有一些非常好用的哈希功能

Hashing.md5().hashString(s).asLong();

我相信上述实际上是 CityHash,但无论如何它都会生成哈希长整型值,以供您在任何哈希需求中使用。(我尝试了 @Eric J. 的 Java 代码,看起来像是 CityHash 32)。


抱歉,我要downvote了,因为这不是CityHash。根据文档,asLong只返回结果哈希的前8个字节。在你的例子中,它将通过一半减少md5的16字节分布(本身并不完美)。 - Alexey Sviridov

1

为了明确起见,加密摘要的任何子部分都不再具有许多摘要的加密属性,具体而言,这些属性不再成立:

  • 反演抗性(查找满足 H(X)的 X)
  • 碰撞抗性(查找 X、Y 使得 H(X)= H(Y))
  • 在可能输出范围内的随机分布

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接