Author Topic: [C#] Thread Safe Random and CryptoRandom  (Read 2336 times)

0 Members and 1 Guest are viewing this topic.

Offline xor

  • Peasant
  • *
  • Posts: 59
  • Cookies: 32
    • View Profile
[C#] Thread Safe Random and CryptoRandom
« on: June 26, 2015, 04:49:56 am »
Code: [Select]

    /// <summary>
    /// Thread-Safe Random
    /// </summary>
    public static class SafeRandom
    {
        private static readonly Random Global = new Random();
        [ThreadStatic]
        private static Random _local;


        public static int Next()
        {
            var inst = _local;
            if (inst != null) return inst.Next();


            int seed;
            lock (Global) seed = Global.Next();
            _local = inst = new Random(seed);
            return inst.Next();
        }
    }


Code: [Select]

    /// <summary>
    /// Thread-Safe Cryptographic Random
    /// </summary>
    public static class SafeCryptoRandom
    {
        private static readonly RNGCryptoServiceProvider Global = new RNGCryptoServiceProvider();
        [ThreadStatic]
        private static Random _local;


        public static int Next()
        {
            var inst = _local;
            if (inst != null) return inst.Next();


            var buffer = new byte[4];
            Global.GetBytes(buffer);
            _local = inst = new Random(BitConverter.ToInt32(buffer, 0));
            return inst.Next();
        }
    }


-- xor
« Last Edit: June 26, 2015, 04:51:05 am by xor »

Offline skruf

  • NULL
  • Posts: 3
  • Cookies: 0
    • View Profile
Re: [C#] Thread Safe Random and CryptoRandom
« Reply #1 on: December 14, 2015, 03:52:12 pm »
Cool, but the instance members of the  RNGCryptoServiceProvier are not thread safe you'll need to lock it. So something like
Code: (javascript) [Select]
lock (Global) Global.GetBytes
But in general just implement it as a static class with a lazy loder. so you can simply:

Code: (javascript) [Select]
static readonly ThreadLocal<Random> instance= new ThreadLocal<Random>(() => New Random(etc...)
« Last Edit: December 14, 2015, 03:55:45 pm by skruf »

Offline Mordred

  • Knight
  • **
  • Posts: 360
  • Cookies: 135
  • Nvllivs in Verba
    • View Profile
Re: [C#] Thread Safe Random and CryptoRandom
« Reply #2 on: December 14, 2015, 04:37:36 pm »
Cool share, thank you!

@skruf
I'm a bit rusty on my C#, but doesn't using a static class screw up unit tests? You can't mockup a static object if I recall correctly, no?
The lock solution seems nice though, I think I remember reading an article about it a while back as well.

L.E.: Found the article. It's from 2009 so it might be a bit dated, but the guy suggests both the lock solution as well as using one Random instance per thread, rather than one per AppDomain (which he claims is faster).

« Last Edit: December 14, 2015, 04:39:42 pm by Mordred »
\x57\x68\x79\x20\x64\x69\x64\x20\x79\x6f\x75\x20\x65\x76\x65\x6e\x20\x66\x75\x63\x6b\x69\x6e\x67\x20\x73\x70\x65\x6e\x64\x20\x74\x68\x65\x20\x74\x69\x6d\x65\x20\x74\x6f\x20\x64\x65\x63\x6f\x64\x65\x20\x74\x68\x69\x73\x20\x6e\x69\x67\x67\x72\x3f\x20\x44\x61\x66\x75\x71\x20\x69\x73\x20\x77\x72\x6f\x6e\x67\x20\x77\x69\x74\x68\x20\x79\x6f\x75\x2e

Offline skruf

  • NULL
  • Posts: 3
  • Cookies: 0
    • View Profile
Re: [C#] Thread Safe Random and CryptoRandom
« Reply #3 on: December 14, 2015, 04:43:58 pm »
Cool share, thank you!

@skruf
I'm a bit rusty on my C#, but doesn't using a static class screw up unit tests? You can't mockup a static object if I recall correctly, no?

Not that rusty :) You are absolutely correct, there are several workarounds, such as adding Reset methods or using reflection to invoke the initializer, but those are ugly and ruins the tests imho.

However, the static class is about 9x faster than the locking method, which is nice :) (Atleast when I ran them just now:P)

Offline multi168

  • NULL
  • Posts: 3
  • Cookies: 0
    • View Profile
Re: [C#] Thread Safe Random and CryptoRandom
« Reply #4 on: February 02, 2016, 04:51:36 pm »
You can use something like this to make static methods testable: http://urasandesu.github.io/Prig/
It's not always ideal, but actually quite good it exists for those cases that you really need it.

Offline Fur

  • Knight
  • **
  • Posts: 216
  • Cookies: 34
    • View Profile
Re: [C#] Thread Safe Random and CryptoRandom
« Reply #5 on: February 02, 2016, 07:02:53 pm »
Code: (CSharp) [Select]
var buffer = new byte[4];
Global.GetBytes(buffer);
_local = inst = new Random(BitConverter.ToInt32(buffer, 0));
return inst.Next();
System.Random isn't cryptographically secure to my knowledge -- which is limited since I couldn't find much information about it -- and its seed space apparently is 2^32 - not outside the range of a bruteforce search and certainly faster than bruteforcing a 2^128 AES key generated using this class. You should really be using RNGCryptoServiceProvider here, or was there a technical reason you used Random instead?
« Last Edit: February 02, 2016, 07:13:16 pm by Fur »