Search code examples
c#.net.net-corerandomcryptography

How can I generate a cryptographically secure random integer within a range?


I have to generate a uniform, secure random integer within a given range for a program that generates passwords. Right now I use this:

RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] rand = new byte[4];
rng.GetBytes(rand);
int i = BitConverter.ToUInt16(rand, 0);
int result = i%max;   // max is the range's upper bound (the lower is 0)

Is this method safe to use for cryptographic purposes? If not, how should I do it?


Solution

  • You can have a look at the CryptoRandom class taken from niik/CryptoRandom.cs which is the original version by Stephen Toub and Shawn Farkas. In this class they implement several random generators that seem to be cryptographically secure.

    I have used the following version in my projects for random integer generation.

    public class RandomGenerator
    {
        readonly RNGCryptoServiceProvider csp;
    
        public RandomGenerator()
        {
            csp = new RNGCryptoServiceProvider();
        }
    
        public int Next(int minValue, int maxExclusiveValue)
        {
            if (minValue >= maxExclusiveValue)
                throw new ArgumentOutOfRangeException("minValue must be lower than maxExclusiveValue");
    
            long diff = (long)maxExclusiveValue - minValue;
            long upperBound = uint.MaxValue / diff * diff;
    
            uint ui;
            do
            {
                ui = GetRandomUInt();
            } while (ui >= upperBound);
            return (int)(minValue + (ui % diff));
        }
    
        private uint GetRandomUInt()
        {
            var randomBytes = GenerateRandomBytes(sizeof(uint));
            return BitConverter.ToUInt32(randomBytes, 0);
        }
    
        private byte[] GenerateRandomBytes(int bytesNumber)
        {
            byte[] buffer = new byte[bytesNumber];
            csp.GetBytes(buffer);
            return buffer;
        }
    }