简体   繁体   中英

Will C# system.Random with 14 characters always be guaranteed to be unique string (hash)

I have a utility function in which I want to have as part of my URL querystring . I need to be sure that it is always unique

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

If say I pass in 14 for the length , This generates hash like

 YS5bwVTjwEBhFp
 sNi6EfU5rUxI2Z
 sQKhqhklw22vb2

If i'm using talking about 20,000 uses a year of this, Is it safe to say that it should always be unique?

Again

http://:mywebsite.com?id=sQKhqhklw22vb2 is how i would use it

One way to ensure uniqueness is to save the generated values and validate before using that was never used in the past. An alternative is to pre-generate a large number of values, save them in a table, then pick the next available. Variations on this theme are the only way to ensure uniqueness if the parameter has no meaning (no semantics).

Another way is to add meaning. Instead of YS5bwVTjwEBhFp , sNi6EfU5rUxI2Z etc use 0 , 1 etc (an incremental value coming from DB). Of course, you can encode this, eg. by encryption, into a value that has no meaning for user, so the user still see sNi6EfU5rUxI2Z but that is base64 encoded encrypted value of 1 or something like that.

And finally, for all practical uses, just using a cryptographic random string (ie. RNGCryptoServiceProvider.GetBytes ) should be more than enough. Not guaranteed unique, but hugely improbable to collide.

Not sure if your System.Random is that great, but you could combine with a much better Cryptopgraphy scheme. 10 of your characters and 40 of better...

Here it is in Linqpad

example : yours generates h0UcVayzu2 the other better one generates LyR7SUYZ-ZPll36wzGI5kMPamKtyXV_rN0Ax6iZG

Combined is then 50 characters

h0UcVayzu2LyR7SUYZ-ZPll36wzGI5kMPamKtyXV_rN0Ax6iZG

Code:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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