1 module dcrypt.random.random; 2 3 /// Handling global source of randomness. 4 5 6 import dcrypt.random.fortuna.fortuna; 7 8 import dcrypt.random.rdrand; 9 import dcrypt.random.urandom; 10 11 import dcrypt.random.fortuna.entropysource; 12 import dcrypt.random.fortuna.sources.rdrand; 13 import dcrypt.random.fortuna.sources.systemtick; 14 import dcrypt.random.fortuna.sources.filesource; 15 16 version = FortunaRNG; 17 18 version (FortunaRNG) { 19 private Fortuna globalRNG; 20 21 /// Initialize Fortuna 22 private shared static this() { 23 /// Initialize entropy sources. 24 25 debug import std.stdio; 26 27 if(RDRand.isSupported) { 28 // start rdrand entropy source 29 30 debug writeln("Starting RDRAND entropy source."); 31 EntropySource rdrand_src = new RDRandEntropySource; 32 rdrand_src.start(); 33 34 } else { 35 debug writeln("RDRAND entropy source is not available."); 36 } 37 38 try { 39 debug writeln("Starting /dev/urandom entropy source."); 40 EntropySource urandom_src = new FileEntropySource(urandom); 41 urandom_src.start(); 42 } catch(Exception e) { 43 debug writeln("/dev/urandom entropy source is not available.", e); 44 } 45 46 debug writeln("Starting system-tick entropy source."); 47 EntropySource systick_src = new SystemTickEntropySource; 48 systick_src.start(); 49 } 50 } else { 51 private PRNG globalRNG; 52 53 // Initialize the global random number generator. 54 private shared static this() { 55 if (URandomRNG.isAvailable) { 56 globalRNG = new URandomRNG; 57 } 58 else if (RDRand.isSupported) { 59 globalRNG = new RDRandRNG; 60 } 61 } 62 } 63 64 private enum urandom = "/dev/urandom"; 65 66 /// Fill a buffer with random bytes from the default random number generator. 67 public void nextBytes(ubyte[] buf) @safe nothrow @nogc { 68 globalRNG.nextBytes(buf); 69 } 70 71 unittest { 72 ubyte[50] buf1, buf2; 73 74 nextBytes(buf1); 75 nextBytes(buf2); 76 77 assert(buf1 != buf2); 78 } 79