将C#system.Random与14个字符始终保证是唯一的字符串(哈希)

时间:2017-05-30 18:25:08

标签: c# asp.net random hash

我有一个实用程序函数,我希望将其作为URL查询字符串的一部分。我需要确保它始终是唯一的

public static string RandomString(int length)
{
   const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz0123456789";
   var random = new Random();
   return new string(Enumerable.Repeat(chars, length)
     .Select(s => s[random.Next(s.Length)]).ToArray());
}

如果说我在14中传入了长度,则生成类似

的哈希值
 YS5bwVTjwEBhFp
 sNi6EfU5rUxI2Z
 sQKhqhklw22vb2

如果我使用一年的时间谈论20,000次使用,那么说它应该总是唯一的吗?

再次

http://:mywebsite.com?id=sQKhqhklw22vb2是我如何使用它

2 个答案:

答案 0 :(得分:3)

确保唯一性的一种方法是保存生成的值并在使用之前进行验证,这是过去从未使用过的。另一种方法是预先生成大量值,将它们保存在表中,然后选择下一个可用值。这个主题的变化是确保唯一性的唯一方法 如果参数没有意义(没有语义)。

另一种方法是增加意义。而不是YS5bwVTjwEBhFpsNi6EfU5rUxI2Z等使用01等(来自数据库的增量值)。当然,您可以对此进行编码,例如。通过加密,转换为对用户没有意义的值,因此用户仍然可以看到sNi6EfU5rUxI2Z,但这是base64编码的加密值1或类似的东西。

最后,对于所有实际用途,仅使用加密随机字符串(即。RNGCryptoServiceProvider.GetBytes)应该绰绰有余。不保证独特,但极不可能发生冲突。

答案 1 :(得分:0)

不确定你的System.Random是否那么棒,但你可以结合更好的Cryptopgraphy方案。你的10个角色和40个更好的角色......

这是Linqpad

示例:您的h0UcVayzu2生成 另一个更好的人生成LyR7SUYZ-ZPll36wzGI5kMPamKtyXV_rN0Ax6iZG

组合后是50个字符

h0UcVayzu2LyR7SUYZ-ZPll36wzGI5kMPamKtyXV_rN0Ax6iZG

代码:

void Main()
{

    var x = RandomString(10);
    x.Dump();

    var y = Example.GenerateIdentifier(40);
    y.Dump();

    var z = x + y;

    z.Dump();


}


public static string RandomString(int length)
{
  const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz0123456789";
  var random = new Random();
  return new string(Enumerable.Repeat(chars, length)
    .Select(s => s[random.Next(s.Length)]).ToArray());
}


public class Example {
  static readonly char[] AvailableCharacters = {
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 
    'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 
    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
  };

  internal static string GenerateIdentifier(int length) {
    char[] identifier = new char[length];
    byte[] randomData = new byte[length];

    using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) {
      rng.GetBytes(randomData);
    }

    for (int idx = 0; idx < identifier.Length; idx++) {
      int pos = randomData[idx] % AvailableCharacters.Length;
      identifier[idx] = AvailableCharacters[pos];
    }

    return new string(identifier);
  }
}