Random AlphaNumeric Generator

 

Recently I needed to write a simple token generator for a project. In order to make it print-friendly and easy to read, I decided to make it an uppercase alphanumeric string. The code uses the ASCII (American Standard Code for Information Interchange) numeric representation of the character.

A-Z (uppercase) is any number between 65 and 90. To get round the problem that 0-9 falls between 48-57, there is where a clause that subtracts 43 if the random number is greater than 90. This allows the code to use only one random number generator and effectively means that 0-9 follows after Z in the logic.

I thought this was a more elegant way of writing the code instead of using an array with all the characters required.

 


public static string GenerateRandomAlphaNumeric(int length)
{
  Random rnd = new Random((int)DateTime.Now.Ticks);
  string output = new string(
      Enumerable.Range(1, length)
      .Select(i =>
      {
          int rndNum = rnd.Next(65, 101);
          return (char)(rndNum > 90 ? rndNum - 43 : rndNum); // Return a character A-Z / 0-9
      })
      .ToArray()); // Concat the array to string

  return output;
}

 

However, the problem with system.Random is that isn’t strictly speaking, random. It is pseudo-random, which relies on the CPU clock to generate a seed. This then goes through an algorithm to produce a number. In essence, this means that if someone is able to guess the parameters that were used to generate the “random” number, then they are able to predict the likely outcome.

A simpler way to think of this is if you ask someone to pick a colour at random and try to guess it. The chances are they might pick their choice based on their favourite colour or one they’ve seen in the room.

A more secure approach of the above would be to use the System.Security.RNGCryptoServiceProvider, which bases its seed on much more diverse parameters, such as mouse position, keyboard timings, CPU temperature, etc.

An example of this can be seen below.

 


// using System.Security.Cryptography
public static string GenerateRandomAlphaNumeric(int length)
{
	var rng = new RNGCryptoServiceProvider();
	
	string output = new string(
		Enumerable.Range(1, length)
		.Select(i =>
		{		  
			var data = new byte[4];
			rng.GetBytes(data);
			
			int generatedValue = Math.Abs(BitConverter.ToInt32(data, startIndex: 0));
			
			int rndNum = (generatedValue % 36) + 65;
			return (char)(rndNum > 90 ? rndNum - 43 : rndNum); // Return a character A-Z / 0-9
		})
		.ToArray()); // Concat the array to string

  return output;
}

 

Post Categories