我的目标是使用MD5结果的结果来索引哈希表。我想对它执行Modulo操作以在表中找到适当的插槽。我已经尝试将它作为无符号长long类型进行投射。当我打印结果时,我每次都获得相同的MD5哈希值。 MD5哈希最初是unsigned char *。有人能告诉我我做错了吗?
这是我的功能:
int get_fp_slot(unsigned char * fingerprint, int size)
{
return (unsigned long long)fingerprint % size;
}
答案 0 :(得分:2)
MD5哈希值是128位数。因此,为了获得最佳性能,您应该保留所有128位。
鉴于您的函数将128位散列作为字符串,您需要将该字符串解析为一系列4个整数。你的字符串看起来像这样:
79054025255fb1a26e4bc422aef54eb4
这是一个32字节的十六进制字符串。如果是这样,您可以像这样提取二进制版本:
int v1, v2, v3, v4;
sscanf( &fingerprint[0], "%x", &v1 );
sscanf( &fingerprint[8], "%x", &v2 );
sscanf( &fingerprint[16], "%x", &v3 );
sscanf( &fingerprint[24], "%x", &v4 );
你现在所做的事实上取决于你希望你的哈希值有多好。如果你真的需要使用32位数字,那么只需将所有这些数字进行异或运算:
int hash = v1 ^ v2 ^ v3 ^v4;
答案 1 :(得分:1)
您正在投射指针,即散列的地址。当然,该地址与散列值无关。
如何解决这个问题取决于你想要什么。例如,您可以使用哈希的最后16个字节并将其解析为unsigned long long
,
// sanity and error checking omitted for brevity
int get_fp_slot(unsigned char *fingerprint, int size)
{
size_t len = strlen(fingerprint);
size_t offset = len < 16 ? 0 : len-16;
unsigned long long hash_tail = strtoull(fingerprint + offset,NULL,16);
return hash_tail % size;
}
或以递增方式进行模数
// uses a helper hex_val that converts a hexadecimal digit to the integer it signifies
int get_fp_slot(unsigned char *fingerprint, int size)
{
unsigned long long hash_mod = 0;
while(*fingerprint) {
hash_mod = (16*hash_mod + hex_val(*fingerprint)) % size;
++fingerprint;
}
return hash_mod;
}
答案 2 :(得分:0)
在您的代码中,您正在转换指针本身,而不是转换形成MD5值的字节!
MD5是128位,即16字节。假设您的long long
类型是64位(8字节),您可以将其表示为两个long long
值,然后将它们XOR以获取哈希值。或者如果你愿意,你可以简单地选择其中一个...哈希质量可能类似。
您没有说出来,但我假设您的指纹是指向具有MD5值的16字节数组的指针。然后:
unsigned long long a = *(unsigned long long*)fingerprint;
unsigned long long b = *(unsigned long long*)(fingerprint + 8);
return a ^ b;
请注意,a
和b
的值取决于计算机的字节顺序。只要你不将散列发送到不同的架构就无所谓了。