Sanket.NET
Sanket.NET

Reputation: 23

generating random number with RNGCRYPTOSERVICEPROVIDER within specified range

I have come with the following coding to generate range within 1000-9999:

Dim byt As Byte() = New Byte(1000) {}

Dim rngCrypto As New RNGCryptoServiceProvider()
rngCrypto.GetBytes(byt)

Dim randomNumber As Integer = BitConverter.ToInt32(byt, 9999)
Label4.Text = randomNumber

It shows the error:

Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: startIndex

i have done following code. is it correct?

Public Sub secrand()

    Static r As Random = Nothing

    If r Is Nothing Then
        Dim seed() As Byte = New Byte(4) {}
        Dim rng As New RNGCryptoServiceProvider
        rng.GetBytes(seed)
        r = New Random(BitConverter.ToInt32(seed, 0))
        Label4.Text = r.Next(1000, 9999)
    End If
End Sub

Upvotes: 2

Views: 3041

Answers (1)

CodesInChaos
CodesInChaos

Reputation: 108830

The second parameter to BitConverter.ToInt32 is an offset into the byte array. It should be 0 for you. There is also no reason to get 1000 byttes if you're using only 4 of them.

A working version in C#:

public static int RandomUniform(int count)
{
    if(count <= 0)
         throw new ArgumentOutOfRangeException("count");
    var rng=new RNGCryptoServiceProvider();
    var bytes=new byte[8];
    rng.GetBytes(bytes, 0);
    return BitConverter.ToUInt64() % (uint)count;
}

Label4.Text = 1000 + RandomUniform(9000);

In VB.net this will look similar to

Public Shared Function RandomUniform(count As Integer) As Integer
    If count <= 0 Then
        Throw New ArgumentOutOfRangeException("count")
    End If
    Dim rng = New RNGCryptoServiceProvider()
    Dim bytes = New Byte(8) {}
    rng.GetBytes(bytes, 0)
    Return BitConverter.ToUInt64() Mod CUInt(count)
End Function

This code has two weaknesses:

  1. It's quite slow. The per-call overhead of RNGCryptoServiceProvider.GetBytes is large. For better performance use a buffer of several kilobytes and only call GetBytes when it's used up.
  2. It's not perfectly uniform, but the bias should be small enough for most applications.

    Even when using a value for count that exhibits maximal bias you will need over ten billion samples to detect it, whereas for System.Random a handful are enough. i.e the bias is about 8 billion times smaller than for System.Random.

If either weakness is unacceptable for you, you can look into my random number generator project which offers fast, secure and unbiased numbers. But this comes at the cost of adding an external library instead of simply writing a few lines of code.

Upvotes: 5

Related Questions