在 C# 中从输入字符串生成 16 个字母数字字符的哈希函数

Hash Function to Generate 16 Alphanumerical Characters from Input String in C#

我需要一个函数来接收输入字符串,无论其长度如何,并将输出 0-9A-Z 的 16 个字符的固定长度。如果输入相同的字符串,函数应该有相同的输出。

有什么建议吗?谢谢

您可以使用 LINQ:

var c = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var rn = new Random();
var res = new string(Enumerable.Repeat(c, 16)
              .Select(x => x[rn.Next(x.Length)])
              .ToArray());

另请参阅:RNGCryptoServiceProvider Class

Implements a cryptographic Random Number Generator (RNG) using the implementation provided by the cryptographic service provider (CSP). This class cannot be inherited.

或者你可以试试这个:

Guid g = Guid.NewGuid();
MD5 md5 = MD5.Create();
Guid hashed = new Guid(md5.ComputeHash(g.ToByteArray()));

您可以使用类似的东西:

public static string HashString(string text)
{
    const string chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    byte[] bytes = Encoding.UTF8.GetBytes(text);

    SHA256Managed hashstring = new SHA256Managed();
    byte[] hash = hashstring.ComputeHash(bytes);

    char[] hash2 = new char[16];

    // Note that here we are wasting bits of hash! 
    // But it isn't really important, because hash.Length == 32
    for (int i = 0; i < hash2.Length; i++)
    {
        hash2[i] = chars[hash[i] % chars.Length];
    }

    return new string(hash2);
}

SHA256Managed 将生成 32 字节的散列。然后使用 % (模数)运算符,我们 select 每个字节一个字符。请注意,我们以这种方式浪费了很多位,但这并不重要,因为我们拥有的位比我们需要的多得多(我们需要 log2(36) * 16 == 82.7,我们有 256 位哈希)

如果你想创建一个散列,你应该研究一下散列算法。一个最广为人知的是 MD5 但那是一个 128bits 哈希算法。这意味着如果您将原始字节转换为十六进制字符串,它将有 32 个字符长(大多数人都知道),这意味着您需要一个 64 位 的哈希函数。我快速搜索了一下,找到了 SipHash (http://en.wikipedia.org/wiki/SipHash) and then I found a C# implementation (https://github.com/BrandonHaynes/siphash-csharp)

如果您使用 SipHash 算法,您应该得到一个 16 个字符长度的字符串。

试试这个,它使用 MD5Hash 算法。

public string GenerateHash(string str)
{
    using (var md5Hasher = MD5.Create())
    {
        var data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(str));
        return BitConverter.ToString(data).Replace("-", "").Substring(0, 16);
    }
}

我非常喜欢@Xanatos 的回答并决定实施它。 就在那时我意识到我正在创建一个我看到的常见问题的实例。

当我输入用于安装 Windows 的密钥时,我有时会输入错误的数字。特别是当我正在阅读的条形码被划伤或褪色时。简直就是相似字符的组合,视力不好,条码磨损。

以下是从@Xanatos的回答中抄袭的扩展方法,但删除了相似的字符(例如'1','I','O','0'等)。

public static string ConstantLengthHash(this string Input)
{
    const string chars = "234679ACDEFGHJKLMNPQRTUVWXYZ";
    byte[] bytes = Encoding.UTF8.GetBytes(Input);

    SHA256Managed hashstring = new SHA256Managed();
    byte[] hash = hashstring.ComputeHash(bytes);

    char[] hash2 = new char[16];

    // Note that here we are wasting bits of hash! 
    // But it isn't really important, because hash.Length == 32
    for (int i = 0; i < hash2.Length; i++)
    {
        hash2[i] = chars[hash[i] % chars.Length];
    }

    return new string(hash2);
}