是否存在在C#中产生64位散列大小的散列算法?

时间:2010-12-02 22:05:43

标签: c# hash ssis

我需要根据可变长度字符串生成一个Hash值,我可以将其存储在不超过16的字段中(由于供应商要求)。

我将几个正在通过C#脚本转换传递的字符串连接在一起,以便计算Hash。我受到供应商文件规范的限制,因为哈希的输出不能超过16。

有没有人有任何建议?例如,MD5算法的字符串转换长度为32。

5 个答案:

答案 0 :(得分:7)

加密函数的设计使得您可以将输出截断为某种大小,并且截断的散列函数仍然是安全的加密散列函数。例如,如果将SHA-512输出的前128位(16字节)应用于某些输入,则前128位是加密哈希,与任何其他128位加密哈希一样强。

解决方案是选择一些加密哈希函数 - SHA-256,SHA-384和SHA-512是不错的选择 - truncate the output到128位(16字节)。

<强> - 编辑 -

基于注释,当编码为ASCII时,哈希值必须符合16个ASCI字符,解决方案是

  • 首先,选择一些加密哈希函数(SHA-2系列包括SHA-256,SHA-384和SHA-512)
  • 然后,将所选散列函数的输出截断为96位(12字节) - 也就是说,保留散列函数输出的前12个字节并丢弃剩余的字节
  • 然后,对截断的输出进行base-64编码为16个ASCII字符(128位)
  • 有效地产生了96位加密的哈希值。

答案 1 :(得分:0)

如果您有16个字节存储128位数字不是问题。将128位值存储为16byte值,而不是将16字节值存储为HEX的32个字符串。

作为注释,我在数据库中使用了GUID / UUID字段来存储MD5哈希值。虽然不再具有加密安全性,但128位MD5哈希对于Checksums来说很好(并且比64位好得多。)

var result = MD5.Create().ComputeHash(new byte[] { 0 });

Console.WriteLine(result.Length);
Console.WriteLine(Convert.ToBase64String(result));
Console.WriteLine(result.Aggregate(new StringBuilder(),
                                    (sb, v) => sb.Append(v.ToString("x2"))));

//16
//k7iFrf4NoInN9jSQT9WfcQ==
//93b885adfe0da089cdf634904fd59f71

File.WriteAllBytes("tempfile.dat", result);

var input = File.ReadAllBytes("tempfile.dat");

Console.WriteLine(input.Length);
Console.WriteLine(Convert.ToBase64String(input));
Console.WriteLine(input.Aggregate(new StringBuilder(), 
                                    (sb, v) => sb.Append(v.ToString("x2"))));

//16
//k7iFrf4NoInN9jSQT9WfcQ==
//93b885adfe0da089cdf634904fd59f71

请注意,我没有显示文件内容,因为它很可能包含“不可打印”字符。

答案 2 :(得分:0)

您可以轻松地使用MD5哈希,但您必须改变它的存储方式。 MD5是128位,通常显示为32个4位(十六进制)值。但标准字符是8位,因此16个字符足以存储MD5哈希值。

要转换它,请尝试以下操作:

String hash32 = "d41d8cd98f00b204e9800998ecf8427e"
String hash16 = ""

for(int i = 0; i < 32; i+=2)
{
  uint high = Convert.ToUInt32(hash32[i], 16);
  uint low = Convert.ToUInt32(hash32[i+1], 16);
  char c = (char) ((high << 4) | low);

  hash16 += c;
}

答案 3 :(得分:0)

有关此代码的任何评论?似乎运作良好......

var p = new MD5CryptoServiceProvider();
var dic = new Dictionary<long, string>();

for (var i = 0; i < 10000000; i++)
{
    if (i%25000 == 0)
        Console.WriteLine("{0:n0}", i);

    var h = p.ComputeHash(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString()));
    var b = BitConverter.ToInt64(h, 0);

    // "b" is hashed Int64

    if (!dic.ContainsKey(b))
        dic.Add(i, null);
    else
        throw new Exception("Oops!");
}

答案 4 :(得分:0)

我注意到这个问题比较陈旧,但我确信有人会觉得这个答案很有价值。

我的建议是使用能够使用8位到512位的Blake2b。如果没有使用密钥大小,则使用默认值&#34; 512&#34;在这种情况下。 Blake2s默认值为256位。

        // BLAKE2b
        // using System.Data.HashFunction;
        //
        // String message to use.
        string str = "The quick brown fox jumps over the lazy dog";
        // Initialize
        System.Data.HashFunction.Blake2B Blake2B = new System.Data.HashFunction.Blake2B();
        // Get string hash bytes; create 64 bit hash.
        var HashBytes = Blake2B.ComputeHash(str, 64);
        // Convert bytes to string and remove the dashes.
        string hexString = BitConverter.ToString(HashBytes).Replace("-", string.Empty);
        // Display results.
        MessageBox.Show(hexString);
        /*
         * "The quick brown fox jumps over the lazy dog" produces a hash value of
         * "A8ADD4BDDDFD93E4877D2746E62817B116364A1FA7BC148D95090BC7333B3673F82401CF7AA2E4CB1ECD90296E3F14CB5413F8ED77BE73045B13914CDCD6A918"
         * and "2FD0F3FB3BD58455" hash for 64 bits.
         */

希望这有帮助!