Skip to content

How to implement your own RNG provider

Rob Janssen edited this page Nov 25, 2015 · 3 revisions

This library also comes with three 'built-in' RNG providers (Random Number Generator). The RNG provider generates a number of random bytes and returns these bytes as a string. These values are then used to create the secret. By default (no RNG provider specified) TwoFactorAuth.Net will use the DefaultRngProvider. Each of the providers use their own method of generating a random sequence of bytes. The DefaultRngProvider returns a cryptographically secure sequence of random bytes whereas the HashRngProvider and PrngProvider return non-cryptographically secure sequences.

You can easily implement your own RNGProvider by simply implementing the IRngProvider interface. Some of the 'built-in' RNG providers have some constructor arguments that allow you to 'tweak' some of the settings to use when creating the random bytes such as which hashing algorithm to use. I encourage you to have a look at some of the 'built-in' RNG providers for details and the IRngProvider interface.

Demonstration

Let's try implementing our own!

  1. Create a class MyLCGProvider.cs
using System;

namespace MyNameSpace
{
    public class MyLCGProvider
    {
    }
}
  1. Implement the IRngProvider interface:
using System;
using TwoFactorAuthNet.Providers.Rng;

namespace MyNameSpace
{
    public class MyLCGProvider : IRngProvider
    {
    }
}
  1. Implement the IRngProvider interface members:
using System;
using TwoFactorAuthNet.Providers.Rng;

namespace MyNameSpace
{
    public class MyLCGProvider : IRngProvider
    {
        public bool IsCryptographicallySecure { 
            get { 
                return false;
            } 
        }

        public byte[] GetRandomBytes(int bytes)
        {
            // https://en.wikipedia.org/wiki/Linear_congruential_generator
            var result = new byte[bytes];

            int m = int.MaxValue, a = 2147483629, c = 2147483587;
            unchecked
            {
                int seed = (int)(DateTime.Now.Ticks & 0xFFFFFFFF);
                for (int i = 0; i < bytes; i++)
                {
                    seed = (a * seed + c) % m;
                    result[i] = (byte)(seed & 0xFF);
                }
            }
        }
    }
}

NOTE: Please note that this RNG is intended as an example. It is not cryptographically secure (altough this implementation has a fairly uniform distribution).

  1. Pass your newly created RNG provider to a TwoFactorAuth constructor overload that accepts an IRngProvider argument.

From here on the tfa instance will use your RNG provider.

See also:

Clone this wiki locally