1 module dcrypt.crypto.random.prng; 2 3 import std.range; 4 import dcrypt.crypto.random.fortuna.fortuna; 5 import dcrypt.crypto.random.fortuna.generator; 6 7 import dcrypt.crypto.engines.aes; 8 import dcrypt.crypto.digests.sha2; 9 10 alias FortunaGenerator!(AES, SHA256) DRNG; /// Deterministic PRNG 11 12 // TODO implement PRNGs as input ranges 13 14 /// 15 /// Test if T is a random number generator. 16 /// Returns: Returns $(D true) if T can be used as a PRNG. 17 /// 18 @safe 19 template isRNG(T) 20 { 21 enum bool isRNG = 22 is(T == struct) && 23 is(typeof( 24 { 25 ubyte[] buf; 26 T rng = void; 27 string name = rng.name; 28 rng.nextBytes(buf); 29 rng.addSeed(cast(const ubyte[]) buf); 30 })); 31 } 32 33 @safe 34 public abstract class RNG { 35 36 // TODO: default RNG 37 // /** 38 // * Creates a default PRNG. Type depends on your system. 39 // */ 40 // public static PRNG getInstance() nothrow 41 // out (result) { 42 // assert(result !is null, "failed to initialize PRNG instance"); 43 // } 44 // body { 45 // return new Fortuna(); 46 // } 47 48 /// Fill the buffer with random bytes. 49 /// Params: 50 /// buf = output buffer to be filled with PRNG data 51 public abstract void nextBytes(ubyte[] buf) nothrow; 52 53 /// Returns: The name of the RNG algorithm. 54 @property 55 public abstract string name() pure nothrow; 56 57 /// 58 /// Add a seed value to the PRNG. 59 /// 60 /// Params: 61 /// seed = The seed value to add to the PRNG. 62 public abstract void addSeed(in ubyte[] seed) nothrow; 63 64 } 65 66 /// 67 /// Wrapper class for PRNGs. 68 /// 69 @safe 70 public class WrapperPRNG(R) if(isRNG!R): RNG { 71 72 private R rng; 73 74 override: 75 /// fill the buffer with random bytes 76 /// Params: 77 /// buf = output buffer to be filled with PRNG data 78 public void nextBytes(ubyte[] buf) nothrow @nogc { 79 rng.nextBytes(buf); 80 } 81 82 /// Returns: the name of the RNG algorithm 83 @property 84 public string name() pure nothrow @nogc { 85 return rng.name; 86 } 87 88 /// 89 /// Add a seed value to the PRNG. 90 /// 91 /// Params: 92 /// seed = the seed value to add to the PRNG 93 public void addSeed(in ubyte[] seed) nothrow @nogc { 94 rng.addSeed(seed); 95 } 96 97 }