在C中将MD5结果转换为整数

在C中将MD5结果转换为整数,c,casting,md5,C,Casting,Md5,我的目标是使用MD5结果的结果对哈希表进行索引。我想对它执行模运算,以便在表中找到合适的插槽。我尝试将其转换为未签名的long-long类型。当我打印结果时,对于同一个MD5散列,每次都会得到一个不同的数字。MD5散列最初是一个无符号字符*。有人能告诉我我做错了什么吗 以下是我的功能: int get_fp_slot(unsigned char * fingerprint, int size) { return (unsigned long long)fingerprint % size; }

我的目标是使用MD5结果的结果对哈希表进行索引。我想对它执行模运算,以便在表中找到合适的插槽。我尝试将其转换为未签名的long-long类型。当我打印结果时,对于同一个MD5散列,每次都会得到一个不同的数字。MD5散列最初是一个无符号字符*。有人能告诉我我做错了什么吗

以下是我的功能:

int get_fp_slot(unsigned char * fingerprint, int size)
{
return (unsigned long long)fingerprint % size;
}

MD5哈希是一个128位的数字。因此,为了获得最佳性能,您可能应该保留所有128位

假设函数将128位哈希作为字符串,则需要将该字符串解析为一系列4个整数。您的字符串可能如下所示:

79054025255fb1a26e4bc422aef54eb4
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字节的十六进制字符串。如果是这样,则按如下方式提取二进制版本:

79054025255fb1a26e4bc422aef54eb4
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;

您正在投射指针,即散列的地址。当然,该地址与哈希值无关

如何修复它取决于您想要什么。例如,您可以使用散列的最后16个字节,并将其解析为无符号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;
}

在您的代码中,您正在转换指针本身,而不是形成MD5值的字节

MD5是128位,即16字节。假设您的
long-long
类型为64位(8字节),您可以将其表示为两个
long-long
值,然后对它们进行异或以获得哈希值。或者如果你愿意,你可以选择其中一个。。。散列质量可能类似

你没有说,但我假设你的指纹是一个指向MD5值的16字节数组的指针。然后:

unsigned long long a = *(unsigned long long*)fingerprint;
unsigned long long b = *(unsigned long long*)(fingerprint + 8);
return a ^ b;

请注意,
a
b
的值将取决于机器的端部。只要不将散列发送到不同的体系结构,这并不重要。

您试图投射一个指针,这没有多大意义。什么是“指纹”?指向哈希值的字符串表示形式的指针?我建议您构建哈希值的字符串表示形式的整数表示形式,然后重试。在上面的代码中,您使用的是指针,而不是散列的实际值。不完全是你想要达到的。此外,要注意碰撞的可能性,因为你要在这里压缩密钥。除了MD5之外,还应该考虑使用哈希算法来减少冲突。@ C0DEH4CKK-但是MD5是哈希算法。我说除了md5。这意味着输出更小,因此不需要压缩。在第二种解决方案中,while循环何时结束?在0终止符处,我忘记了增量:(因此,对于v1,sscanf将从指纹中获取尽可能多的数据,这些数据可以放在int右边吗?但这不只是前4个字节吗?为什么MD5本身是16个字节,但打印一个32字节的十六进制值?sscanf将解析尽可能多的字节,在本例中是8个字节。如果您觉得安全,您可以一次将8个字节复制到临时缓冲区中。)(例如,防止sscanf破裂)。每个字符仅编码4位1/2字节。字符本身为8位,但在本例中仅编码4位。哇-这可能是错误的。字符缓冲区可能是哈希的文本表示形式,而不是实际的哈希。哈希函数将以稀疏结尾。例如,如果执行此操作,许多位将始终为零。那么,实际的散列是一个数字?而且,就这个操作的结果而言,尽管它可能是错误的,但我从任何单个散列中得到的数字都是一致的。不过,我相信你的话。@Rafaelbatista-我不知道你为什么认为文本表示更可能。例如,请快速查看
man MD5_Final
声明它返回16个字节,这是散列的二进制表示。很自然,OP没有说他正在使用哪个库,所以我们只是猜测…你是对的,我们不知道。但是原型char*建议文本。我在linux内核中使用cypto Api。它要求一个无符号char缓冲区来放置结果。