My ultimate goal is to create a URL that is unique and cannot be predicted / predicted. The purpose of this URL is to allow users to perform operations such as checking their email address and password reset. These URLs expire within the set time (currently set to 24 hours).
I originally used Guid for this purpose, but now I understand that it is somewhere between โjust fineโ and โvery insecure,โ depending on who you are listening to. So, I thought I would strengthen my code a bit just in case. At first it seemed to me that I was just using Guid , but I created it from random bytes, and not from the Guid.NewGuid() factory method. Here is the method I came up with:
public static Guid GetRandomGuid() { var bytes = new byte[16]; var generator = new RNGCryptoServiceProvider(); generator.GetBytes(bytes); return new Guid(bytes); }
I donโt quite understand what exactly happens when you use new Guid(bytes) instead of Guid.NewGuid() , but I think that this whole method creates an array of random bytes and stores it in the Guid data structure. In other words, it is no longer guaranteed to be unique; it is guaranteed to be random.
Since my URLs must be both unique and random, this doesn't seem like a solid solution. Now I think that I should base my URLs on a combination as a unique identifier (which can be a Guid , or, if available, an automatically incrementing database id) and a random sequence generated from RNGCryptoServiceProvider .
Questions
What is the best way to create a validation / password URL - reset, which is guaranteed to be unique and extremely difficult / impossible to predict / guess?
Should I just create my URL by combining a unique string with a random string?
Is there a built-in way in the .NET Framework to easily create a unique and random (unpredictable) sequence that can be used for URLs?
If not, is there an open source open source solution?
Update
If anyone has a similar requirement, I am currently using the following method:
public static string GenerateUniqueRandomToken(int uniqueId) // generates a unique, random, and alphanumeric token { const string availableChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; using (var generator = new RNGCryptoServiceProvider()) { var bytes = new byte[16]; generator.GetBytes(bytes); var chars = bytes .Select(b => availableChars[b % availableChars.Length]); var token = new string(chars.ToArray()); return uniqueId + token; } }
Please comment if you see any problems with this.