Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

static RNGCryptoServiceProvider -- Is it secure & threadsafe for generating sessions and random passwords?

I'm building a web service that requires me to generate custom sessions and random passwords etc.

I was wondering if making a static class and using 1 static RNGCryptoServiceProvider instance for the entire website is a good idea? 1. Is it threadsafe from multiple http request instances? 2. Is it secure? If I allow someone to generate many sessions in a short amount of time, would it be possible to figure out the state of the RNG and predict the next sessions?

in my service other users know when someone signs in, and I originally created a new RNGCryptoServiceProvider when they login to generate a session, but my concern is if that is based off the current datetime, couldn't someone theoretically only have to go through a few thousand sessions to "guess" the session of another user if they knew roughly what second they logged in?

public static class random
{
    private static RandomNumberGenerator _rng;
    protected static RandomNumberGenerator rng
    {
        get
        {
            if (_rng == null) _rng = new RNGCryptoServiceProvider();
            return _rng;
        }
    }
    public static byte[] Bytes(int number)
    {
        var value = new byte[number];
        rng.GetBytes(value);
        return value;
    }
    public static byte Byte { get { return Bytes(1)[0]; } }
    public static int Int { get { return BitConverter.ToInt32(Bytes(4), 0); } }
    public static long Long { get { return BitConverter.ToInt64(Bytes(8), 0); } }
}
like image 914
Fox Avatar asked Aug 10 '09 23:08

Fox


2 Answers

The CSP based RNG in CLR is just a wrapper around CryptGenRandom. Like all CSP functions, they work around a HCRYPTPROV context handle. If I remember correctly the very first thing the provider does when entering the 'context' is to acquire a critical section that protects the 'context'. So while the function is most likely stable across threads, you really should use a separate one for each thread to avoid contention.

Update

According to this MSDN Magazine the CLR may use an instance buffer instead of a stack one, making the RNGCryptoServiceProvider unsafe across threads in future implementations:

Note that, as currently implemented in the .NET Framework 2.0, the parameterless constructor of RNGCryptoServiceProvider creates thread-safe instances. As such, we could have created our private member to instead have been a private static member, and in doing so not have to create a new RNGCryptoServiceProvider instance for each instance of CryptoRandom. However, this thread-safety is not currently documented nor is it in any way baked into the class's contract or interface. Given that, we haven't relied on it for our implementation.

Note that this use is not related to the native API thread safety, the buffer issue is a CLR wrapper issue. Also, if you use the RNGCryptoServiceProvider constructor that takes a byte[], then is unsafe for sure.

like image 103
Remus Rusanu Avatar answered Nov 07 '22 20:11

Remus Rusanu


1) If it's cryptographically secure, which it's supposed to be, then this sort of guessing should not be feasible.

2) On a side note, I suggest removing the JIT instantiation in the static property annd instead doing the following:

protected static readonly RandomNumberGenerator _rng = new RNGCryptoServiceProvider();
like image 39
Steven Sudit Avatar answered Nov 07 '22 21:11

Steven Sudit