将部分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,等等。必须有一定的速度/效率。
看起来没那么难,但它避开了我。任何帮助都将不胜感激。谢谢
首先,用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
。