这是在C#中截断哈希的正确方法吗?

时间:2014-01-29 21:49:13

标签: c# hash byte bit-manipulation bitarray

我需要散列输入字符串并产生14位十进制数作为输出。

math I am using告诉我最多可以有一个46位无符号整数。

我知道46位uint意味着对任何潜在的哈希函数的碰撞阻力更小。但是,我创建的哈希数量使碰撞概率保持在可接受的范围内。

如果社区可以帮助我验证我将方法截断为46位的方法是否可靠,我将不胜感激。我有一种直觉,认为有优化和/或更简单的方法来做到这一点。我的函数如下(调用此函数时bitLength为46):

    public static UInt64 GetTruncatedMd5Hash(string input, int bitLength)
    {
        var md5Hash = MD5.Create();

        byte[] fullHashBytes = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));

        var fullHashBits = new BitArray(fullHashBytes);

        // BitArray stores LSB of each byte in lowest indexes, so reversing...
        ReverseBitArray(fullHashBits);

        // truncate by copying only number of bits specified by bitLength param
        var truncatedHashBits = new BitArray(bitLength);
        for (int i = 0; i < bitLength - 1; i++)
        {
            truncatedHashBits[i] = fullHashBits[i];
        }

        byte[] truncatedHashBytes = new byte[8];

        truncatedHashBits.CopyTo(truncatedHashBytes, 0);

        return BitConverter.ToUInt64(truncatedHashBytes, 0);
    }

感谢您查看此问题。我感谢任何反馈!

1 个答案:

答案 0 :(得分:0)

在上述评论的帮助下,我精心设计了以下解决方案:

 public static UInt64 GetTruncatedMd5Hash(string input, int bitLength)
 {
        if (string.IsNullOrWhiteSpace(input)) throw new ArgumentException("input must not be null or whitespace");

        if(bitLength > 64) throw new ArgumentException("bitLength must be <= 64");

        var md5Hash = MD5.Create();

        byte[] fullHashBytes = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));

        if(bitLength == 64)
            return BitConverter.ToUInt64(fullHashBytes, 0);

        var bitMask = (1UL << bitLength) - 1UL;

        return BitConverter.ToUInt64(fullHashBytes, 0) & bitMask;
    }

它比我之前尝试做的更紧凑(也更快)。