将部分MD5哈希代码转换为长

本文关键字:转换 代码 哈希 MD5 | 更新日期: 2023-09-27 18:00:33

我正在使用MD5算法对磁盘上哈希表的密钥进行哈希处理(我知道这是否是最好的算法值得怀疑,但我现在还是用它。这个问题可以推广到任何生成字节数组的算法)。我的问题是:

哈希代码的大小决定了哈希表中组合(bucket)的数量。由于MD5是128位,所以有大量的组合(~3.4e38),这对我的目的来说太大了。因此,我想做的是提取MD5生成的字节数组的前n位,并将其转换为长(或ulong)值。由于MD5产生一个字节数组,如果我想要一个整数字节,这将很容易做到,但这会导致组合数量的跳跃太大。我发现单比特版本要复杂得多。

目标:

n = 10  // I.e. I want 2^10 combinations
long pos = someFcn(byte[] key, n)

其中key是要散列的值,n是我想要使用的MD5结果的位数。那么,Pos将是从0到1023的整数(在n=10的情况下)。如果n=11,代码将从0到2^11-1=2027,等等。必须有一定的速度/效率。

看起来没那么难,但它避开了我。任何帮助都将不胜感激。谢谢

将部分MD5哈希代码转换为长

首先,用BitConverter.ToInt32将前四个字节转换为整数。不管怎样,它都会得到四个字节,但这可能不会使它变得更慢,因为你无论如何都要使用32位寄存器进行其余的计算,而像"如果它<16,那么就用前两个字节来做"这样的复杂东西只会使变得更复杂

然后,给定该整数,取最低的N位。如果你真的想要在编译时不知道的特定数量的比特[两个桶的幂],~((-1)<<N)是一个很好的技巧,可以得到2^N-1。

或者,您可以简单地使用ToUInt32,并对素数进行模运算[转换为UInt64可能会稍微好一点,然后您就可以从完全一半的比特开始,在这种情况下]

获取前10位,例如:

int result = ((int)key[0] << 2) | (((int)key[1] >> 6) & 0x03)

如果你有这样的数组,

unsigned char data[2000];

然后你可以把前n个比特刮成一个整数,比如

typedef unsigned long long int MyInt;
MyInt scrape(size_t n, unsigned char * data)
{
    MyInt result = 0;
    size_t b;
    for (b = 0; b < n / 8; ++b)
    {
       result <<= 8;
       result += data[b];
    }
    const size_t remaining_bits = n % 8;
    result <<= remaining_bits;
    result += (data[b] >> (8 - remaining_bits));
    return result;
 }

我假设CHAR_BITS == 8,如果您愿意,可以随意概括代码。此外,数组的大小乘以8必须至少为n