1 module dcrypt.random.urandom; 2 3 import std.stdio; 4 import std.file; 5 import std.exception; 6 import std.conv: text; 7 8 import dcrypt.random.prng; 9 10 /// This module wraps the /dev/urandom special file into a dcrypt PRNG. 11 /// Available for Linux only. 12 13 version(linux) { 14 15 /// Test /dev/urandom based PRNG. 16 unittest { 17 URandomRNG rng = new URandomRNG; 18 19 ubyte[16] buf; 20 21 assert(rng.isAvailable); 22 23 rng.nextBytes(buf); 24 25 assert(buf != x"000000000000000000000000000000", "failed to get entropy from /dev/urandom"); 26 } 27 28 } 29 30 unittest { 31 if(URandomRNG.isAvailable) { 32 PRNG rand = new URandomRNG(); 33 34 auto buf1 = new ubyte[64]; 35 auto buf2 = new ubyte[64]; 36 37 rand.nextBytes(buf1); 38 rand.nextBytes(buf2); 39 40 assert(buf1 != buf2, "data is not random"); 41 } 42 } 43 44 /// 45 /// URandomRNG provides an interface to the /dev/urandom RNG of 46 /// most Unix like systems. 47 /// 48 @safe 49 public class URandomRNG: PRNG { 50 51 /** 52 Throws: exception if /dev/urandom is not available 53 */ 54 public this() { 55 if (isAvailable()) { 56 urandFile = File(urand , "r"); 57 } else { 58 throw new Exception(urand~" not available"); 59 } 60 } 61 62 ~this() { 63 urandFile.close(); 64 } 65 66 /// Evaulates at runtime if /dev/urandom is available. 67 /// Returns: `true` if /dev/urandom PRNG is available. 68 @property 69 public static bool isAvailable() nothrow { 70 return exists(urand); 71 } 72 73 override { 74 75 /// Returns: Get the name of this PRNG. 76 @property 77 public pure nothrow string name() { 78 return "/dev/urandom"; 79 } 80 81 @trusted 82 public void nextBytes(ubyte[] buf) { 83 try { 84 urandFile.rawRead(buf); 85 }catch(Exception e) { 86 assert(false, text("URandomPRNG failed to get entropy from ",urand)); 87 } 88 } 89 90 public void addSeed(in ubyte[] seed) { 91 // dont do anything 92 } 93 } 94 95 private { 96 enum urand = "/dev/urandom"; 97 File urandFile; 98 } 99 100 }