Truly Random

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();
    }
}


Comment Section

Comments are closed.