One of the apps I have been working on recently required that I present the user with a truly random sequence of values. The concept of being random is actually a bit more complicated than one would assume, in fact the idea of randomness is based in mathematics (which I will not get into here).
The following code represents a cryptographically sound random name generator. It takes advantage of the System.Security.Cryptography namespace which provides secure encoding and decoding of data, as well as hashing, and random number generation. Additionally I copped some code from Michael Giagnocavo, who helps resolve the problem of converting the bytes produce by the service into a Base32 string. Please see my notes in line.
public sealed class RandomValue { //This value determines how long the random number will be (every 5 bytes produces 8 characters) //... the bigger the better private const int FOLDERNAME_BYTES = 20; private RandomValue() { } public static string GenerateValues() { //This provider fills an array with a cryptographically strong sequence of random byte values. RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); byte[] buffer = new byte[FOLDERNAME_BYTES]; rng.GetBytes(buffer); //Convert the byte value into a string using "Base32" return Base32.ToBase32String(buffer); } } public sealed class Base32 { // the valid chars for the encoding ... // the order and the values can be changed e.g. 0,1,O,I ... // but it still needs to be 32 characters. // Standard base32 encoding uses A-Z and six digits 2-7 // (see http://en.wikipedia.org/wiki/Base32). private static string ValidChars = "QAZ2WSX3" + "EDC4RFV5" + "TGB6YHN7" + "UJM8K9LP"; ////// Converts an array of bytes to a Base32-k string. /// public static string ToBase32String(byte[] bytes) { StringBuilder sb = new StringBuilder(); // holds the base32 chars byte index; int hi = 5; int currentByte = 0; while (currentByte < bytes.Length) { // do we need to use the next byte? if (hi > 8) { // get the last piece from the current byte, shift it to the right // and increment the byte counter index = (byte)(bytes[currentByte++] >> (hi - 5)); if (currentByte != bytes.Length) { // if we are not at the end, get the first piece from // the next byte, clear it and shift it to the left index = (byte)(((byte)(bytes[currentByte] << (16 - hi)) >> 3) | index); } hi -= 3; } else if (hi == 8) { index = (byte)(bytes[currentByte++] >> 3); hi -= 3; } else { // simply get the stuff from the current byte index = (byte)((byte)(bytes[currentByte] << (8 - hi)) >> 3); hi += 5; } sb.Append(ValidChars[index]); } return sb.ToString(); } }
Comments are closed.