简体   繁体   English

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

[英]Is there a hash algorithm that produces a hash size of 64 bits in C#?

I need to produce a Hash value based off of a variable length string that I can store within a field no longer than 16 (due to vendor requirements). 我需要根据可变长度字符串生成一个Hash值,我可以将其存储在不超过16的字段中(由于供应商要求)。

I am concatenating together several strings that are being passed through a C# script transformation in order to calculate the Hash. 我正在连接几个正在通过C#脚本转换传递的字符串,以便计算哈希值。 I am constrained by the vendor's file specification in that the output of the hash cannot be any longer than 16. 我受到供应商文件规范的限制,因为哈希的输出不能超过16。

Does anyone have any suggestions? 有没有人有什么建议? As an example the string conversion of the MD5 algorith has a length of 32. 作为示例,MD5算法的字符串转换具有32的长度。

The cryptographic has functions are designed such that you may truncate the output to some size and the truncated hash function remains a secure cryptographic hash function. 加密函数的设计使得您可以将输出截断为某种大小,并且截断的散列函数仍然是安全的加密散列函数。 For example, if you take the first 128 bits (16 bytes) of the output of SHA-512 applied to some input, then the first 128 bits are a cryptographic hash as strong as any other 128-bits cryptographic hash. 例如,如果将SHA-512输出的前128位(16字节)应用于某些输入,则前128位是与任何其他128位加密哈希一样强的加密哈希。

The solution is to choose some cryptographic hash function - SHA-256, SHA-384, and SHA-512 are good choices - and truncate the output to 128 bits (16 bytes). 解决方案是选择一些加密散列函数 - SHA-256,SHA-384和SHA-512是不错的选择 - 并将输出截断为128位(16字节)。

--EDIT-- - 编辑 -

Based on the comment that the hash value must, when encoded to ASCII, fit within 16 ASCI characters, the solution is 基于注释,当编码为ASCII时,哈希值必须符合16个ASCI字符,解决方案是

  • first, to choose some cryptographic hash function (the SHA-2 family includes SHA-256, SHA-384, and SHA-512) 首先,选择一些加密哈希函数(SHA-2系列包括SHA-256,SHA-384和SHA-512)
  • then, to truncate the output of the chosen hash function to 96 bits (12 bytes) - that is, keep the first 12 bytes of the hash function output and discard the remaining bytes 然后,将所选散列函数的输出截断为96位(12字节) - 也就是说,保留散列函数输出的前12个字节并丢弃剩余的字节
  • then, to base-64-encode the truncated output to 16 ASCII characters (128 bits) 然后,对截断的输出进行base-64编码,使其成为16个ASCII字符(128位)
  • yielding effectively a 96-bit-strong cryptographic hash. 有效地产生一个96位强的加密哈希。

You can easily use an MD5 hash for this, but you will have to alter the way it is stored. 您可以轻松地使用MD5哈希,但您必须改变它的存储方式。 An MD5 is 128-bits, which is typically displayed as 32 4-bit (hexadecimal) values. MD5是128位,通常显示为32个4位(十六进制)值。 A standard char is 8 bits, however, so 16 characters is exactly enough to store the value of an MD5 hash. 但是,标准字符串是8位,因此16个字符足以存储MD5哈希值。

To convert it, try the following: 要转换它,请尝试以下操作:

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;
}

Any comments about this code? 有关此代码的任何评论? Seems works well... 似乎运作良好......

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!");
}

I've noticed this question is relatively old, but I'm sure someone will find this answer to it valuable. 我注意到这个问题比较陈旧,但我相信有人会觉得这个答案很有价值。

My suggestion would be to use Blake2b which has the ability to use 8 bit through 512 bits. 我的建议是使用Blake2b,它能够使用8位到512位。 If no key size is used, the default value is used "512" in this case. 如果未使用密钥大小,则在这种情况下使用默认值“512”。 Blake2s default value 256 bits. 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.
         */

Hope this helps! 希望这可以帮助!

If you have 16 bytes storing a 128bit number is not an issue. 如果你有16个字节存储128位数字不是问题。 Store the 128bit value as a 16byte value instead of a 32 character string that stored the 16 byte value as HEX. 将128位值存储为16byte值,而不是将16字节值存储为HEX的32字符串。

As a note I have used GUID/UUID fields in databases to store MD5 hashes. 作为注释,我在数据库中使用了GUID / UUID字段来存储MD5哈希值。 While no longer cryptographically secure, 128bit MD5 hashes are fine for Checksums (and is much better than 64 bits.) 虽然不再具有加密安全性,但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

Note that I don't show the file content because there is a good chance that it will contain "unprintable" characters. 请注意,我不显示文件内容,因为它很可能包含“不可打印”字符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM