Last active
December 17, 2015 16:49
-
-
Save rossmurray/5641553 to your computer and use it in GitHub Desktop.
Generates a random key using an arbitrary character set
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void Main() | |
{ | |
var charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray(); //which characters can appear in the string | |
var length = 32; //length of the string | |
Console.WriteLine(GenerateKey(charset, length)); | |
} | |
///Generate a random string of arbitrary length using RNGCryptoServiceProvider. | |
///characterSet is the set of characters that can appear in the string. | |
///length is the desired length of string. | |
public string GenerateKey(char[] characterSet, int length) | |
{ | |
var result = string.Empty; | |
using(var rng = new RNGCryptoServiceProvider()) | |
{ | |
while(result.Length < length) | |
{ | |
var bytes = new byte[4]; //4 bytes in a uint32 | |
rng.GetBytes(bytes); | |
var value = BitConverter.ToUInt32(bytes, 0); | |
result += ConvertToBase(value, characterSet); | |
} | |
} | |
return result.Substring(0, length); | |
} | |
///Converts a uint to an arbitrary base. | |
///charset is the characters used to represent the base. | |
///The length of charset is the base being converted to. | |
///For example: ConvertToBase(13, new []{'0', '1'}) would convert 13 to base 2 (binary): 1101 | |
public string ConvertToBase(uint value, char[] characterSet) | |
{ | |
var radix = (uint)characterSet.Length; | |
if(characterSet == null) | |
{ | |
throw new ArgumentNullException("charset"); | |
} | |
if(characterSet.Length < 2) | |
{ | |
throw new ArgumentException("charset must have at least 2 elements"); | |
} | |
if(characterSet.Distinct().Count() < characterSet.Length) | |
{ | |
throw new ArgumentException("charset has duplicate characters"); | |
} | |
var result = new List<char>(); | |
do | |
{ | |
var remainder = value % radix; | |
value = value / radix; | |
result.Add(characterSet[remainder]); | |
} while(value > 0); //repeatedly dividing will always reach 0 because: baseN is 2 or greater, and in C#, 1 divided by 2 = 0 | |
result.Reverse(); | |
return new string(result.ToArray()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment