Click here to Skip to main content
15,895,011 members
Articles / Web Development / ASP.NET
Article

Generating Unique Keys in .Net

Rate me:
Please Sign up or sign in to vote.
3.74/5 (64 votes)
17 Jun 20063 min read 431.3K   10.2K   118   62
I need to create some unique IDs. GUIDs are great as they give Globally Unique identifier but they are big. I mean if you want to issue unique number in your application which you want to give as Booking Number or any reference number then GUIDs is obviously not a solution.

Introduction

I have few applications where I need to create some unique IDs. GUIDs are great as they give Globally Unique identifier but they are big. I mean if you want to issue unique number in your application which you want to give as Booking Number or any reference number then GUIDs is obviously not a solution. Therefore, I need some simple Id which is unique too. For example when I send a request to my Credit Card Processor there's an ID that correlates my invoice with the transaction at the provider. A GUID isn't what I'd want here.

But one relatively simple solution is to create sequential ID which will be of appropriate size as well as it will guarantee uniqueness. Very Good and Simple solution!!! Isn’t it !! My answer would be NO !! Because it is security threat for your website. In case of Web Application where you can Retrieve your Order or Booking Details by just giving Order Reference number, you can easily BruteForce Sequential Reference numbers to retrieve records.

In this article I will discuss some of my research and techniques.

Using DateTime and HashCode:

Using DateTime for generating unique keys is very common practice. I have remixed this approach by inducing HashCode in it also. Like

DateTime.Now.ToString().GetHashCode().ToString("x"); 

It will give you some key like 496bffe0. At the first glance it seems to be satisfied Unique key as its using current time and hashing to generate key but GetHashCode() doesn’t procduce unique code everytime. Althought Microsoft is using Double Hashing algorithms with N Number of collision resolving double hash function but during my experimentation I found lot of collisions.

Using GUIDs and HashCode:

So then I tried

<BR>Guid.NewGuid().ToString().GetHashCode().ToString("x"); 

It gives key something like 649cf2e3

Somehow I don't think that this string representation at least is unique… 38 characters represented as 8? Ok 32 bits, but still it's 8 digits and characters limited to hex values and yes my doubt got right as I wrote program which generated 100,000 keys and checked it for collisions and found several keys duplicated.

Using RNGCryptoServiceProvider and Character Masking

The .net Framwork provides RNGCryptoServiceProvider class which Implements a cryptographic Random Number Generator (RNG) using the implementation provided by the cryptographic service provider (CSP). This class is usually used to generate random numbers. Although I can use this class to generate unique number in some sense but it is also not collision less. Moreover while generating key we can make key more complicated by making it as alpha numeric rather than numeric only. So, I used this class along with some character masking to generate unique key of fixed length. Below is code sample:

private string GetUniqueKey()
{
int maxSize  = 8 ;
int minSize = 5 ;
char[] chars = new char[62];
string a;
a = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
chars = a.ToCharArray();
int size  = maxSize ;
byte[] data = new byte[1];
RNGCryptoServiceProvider  crypto = new RNGCryptoServiceProvider();
crypto.GetNonZeroBytes(data) ;
size =  maxSize ;
data = new byte[size];
crypto.GetNonZeroBytes(data);
StringBuilder result = new StringBuilder(size) ;
foreach(byte b in data )
{ result.Append(chars^__b % (chars.Length - )>); }
 <span class="code-keyword">return result.ToString();
}

Analysis:

For lab testing purposes, I created 10,00,000 unique keys by using above three procedures and found the following results :

Generation Method<o:p>

Time Taken<o:p>

Number of Generated Keys<o:p>

Number of Duplicate Keys<o:p>

All Fixed Length Keys<o:p>

<o:p> 

Using DateTime and HashCode<o:p>

01.56 sec  <o:p>

10,00,000<o:p>

500131<o:p>

No<o:p>

<o:p> 

Using GUIDs and HashCode<o:p>

04.45 sec<o:p>

10,00,000<o:p>

113<o:p>

No<o:p>

<o:p> 

Using RNGCryptoServiceProvider and Character Masking<o:p>

<o:p> 

00.40 sec<o:p>

10,00,000<o:p>

0 (Wow!!)<o:p>

Yes<o:p>

<o:p> 


The above analysis shows that RNGCrypto with Character Masking is best method to generate Unique keys.

Note: The above research is for study purpose only. Yes there can be another methods which are better than the ones mentioned above.

 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United Arab Emirates United Arab Emirates
Altaf Al-Amin Najvani
Project Manager
Commercial Bank Of Dubai


Qualifications:
BS - Computer Science
Masters In Project Management
Masters In Business Administration

Certifications:
CISA - Certified Information Systems Auditor
ITIL (Foundation)
Microsoft Certified Technology Specialist (SQL Server 2005)
Microsoft Certified Technology Specialist (Web Applications)
Microsoft Certified Application Developer (.NET)
Microsoft Certified Solution Developer (.NET)

Comments and Discussions

 
GeneralRe: An easier way Pin
Scoby92-Aug-07 9:43
Scoby92-Aug-07 9:43 
Generalfrequency distibution of generated letters Pin
System.Object13-Jun-06 2:22
System.Object13-Jun-06 2:22 
GeneralRe: frequency distibution of generated letters Pin
Altaf Al-Amin13-Jun-06 4:40
Altaf Al-Amin13-Jun-06 4:40 
GeneralRe: frequency distibution of generated letters Pin
System.Object13-Jun-06 7:48
System.Object13-Jun-06 7:48 
GeneralShortened GUID Pin
Paul Charles13-Jun-06 1:19
Paul Charles13-Jun-06 1:19 
GeneralBirthday Paradox Pin
ttobler12-Jun-06 6:25
ttobler12-Jun-06 6:25 
GeneralGetHashcode Pin
Roger Alsing11-Jun-06 23:33
Roger Alsing11-Jun-06 23:33 
GeneralRe: GetHashcode Pin
mitchell5019-Jun-06 7:40
mitchell5019-Jun-06 7:40 
Back in the olden days (1980's) we used hash codes to create faster database indexing. We could count on a collision every once in a while so we did the same thing MS does; we checked the table.

Why not simply apply randomness to a sequential order? Mathematically, it is impossible to avoid collisions given a number with this set of permutations. If you think of a seeded system that addresses points on a euclidian plane, it would be relatively easy to create a token that is both unique and random. This would guarantee uniqueness that the modulus hash math cannot.

Here's a "seed" for an idea:

The "plane" is a representation of your token universe placed in
some unique order like this:

0akL|U4yr<br />
        t2iZ|8wTK<br />
        ou1R|qcHm<br />
        A9Wh|eQzP<br />
        ----+----<br />
        If6s|YMCx<br />
        qNdX|ESgj<br />
        B7vh|l3bG<br />
        nJ5S|DFVO 


This plane would be represented by the string:
"0akLU4yrt2iZ8wTKou1RqcHmA9WheQzPIf6sYMCxqNdXESgjB7vhl3bGnJ5SDFVO"

Sequentially, all the possible keys are represented by a base 64 number like this:

123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz (or whatever)

1. Randomly select one of the 4 quadrants of a plane<br />
2. Randomly select a direction (clockwise or counter-clockwise)<br />
3. Compute a radian from a pre-selected center that is <br />
   n+x of the previous seed:<br />
   Where: n is the previous seed (stored so your web server could crash:()<br />
          x is a bounded random number<br />
4. Compute a random point described somewhere along the arc created by <br />
   the radian within the selected quadrant<br />
5. Repeat steps 1, 2 and 4 8 times


Look at this as a random spiral through all the points in the plane. (Since it's a finite plane you will have to adjust for the "corners".) It's relatively random but since it increments or decrements sequentially, it's unique. I'm sure there is a flaw in my thinking but in theory, this should work fairly well with no collisions.

Eventually, you would traverse the entire universe, generating keys that could be ordered into a sequential list. It's just that the order in which you generate the keys is random. If I'm not mistaken, you would have to readjust your radians in a very limited increment to make sure you traverse every possible path. Someone smarter than I can probably tell you how to do this mathematically. As a matter of fact, I'm sure there is a theorum or something that covers what I've just described.

Please note that you can introduce additional randomness by the manner in which you arrange the "plane". The number of ways you can arrange the plane is the same as the permutations for the key itself. This would make it extremely difficult for someone to randomly select a matching key even if they know your methodology. They might be able to guess the correct direction, the radian and even the seed but can they guess where you placed all of the tokens in the plane?

The three downsides to this that I can see are:

1. You need to maintain your "seed"<br />
2. You have to maintain a fixed plane (you can't move the tokens<br />
   around on the plane without creating the possibility of a collision.)<br />
3. I don't know how to represent this mathematically


Could someone that understands this type of math please comment on the weaknesses?
GeneralRe: GetHashcode [modified] Pin
mitchell5019-Jun-06 8:01
mitchell5019-Jun-06 8:01 
QuestionNot unique? Pin
vodzurk11-Jun-06 22:49
vodzurk11-Jun-06 22:49 
AnswerRe: Not unique? Pin
Altaf Al-Amin12-Jun-06 18:51
Altaf Al-Amin12-Jun-06 18:51 
GeneralComment Pin
wout de zeeuw10-Jun-06 2:50
wout de zeeuw10-Jun-06 2:50 
GeneralRe: Comment Pin
Altaf Al-Amin10-Jun-06 3:43
Altaf Al-Amin10-Jun-06 3:43 
GeneralAnalysis Pin
afterburn10-Jun-06 1:31
afterburn10-Jun-06 1:31 
GeneralRe: Analysis Pin
Ashaman19-Jun-06 1:43
Ashaman19-Jun-06 1:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.