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

时间:2011-06-24 21:56:17

标签: c# arrays hash byte md5

我正在使用MD5算法来散列磁盘哈希表的密钥(我知道这是否是用于此的最佳算法是值得怀疑的,但我现在正在使用它。问题是可以推广到任何产生字节数组的算法。我的问题是:

哈希码的大小决定了哈希表中组合(桶)的数量。由于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等。必须有点快/高效。

看起来不那么难,但它让我望而却步。任何帮助将非常感激。谢谢。

3 个答案:

答案 0 :(得分:1)

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

然后,给定该整数,取最低N位。如果你真的想要在编译时不知道特定数量的位[两个桶的功率],~((-1)<<N)是获得2 ^ N-1的好方法。

或者你可以简单地使用ToUInt32代替模数素数[转换为UInt64可能稍好一些,那么你可以在这种情况下完全占据一半的位数]

答案 1 :(得分:0)

获取前10位,例如:

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

答案 2 :(得分:0)

如果您有这样的数组,

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