1 module dcrypt.crypto.random.urandom; 2 3 import std.stdio; 4 import std.file; 5 import std.exception; 6 import std.conv: text; 7 8 import dcrypt.crypto.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 RNG 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: RNG { 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 // HACK: problem with different standard library version 71 version(LDC) { 72 try { 73 return exists(urand); 74 }catch(Exception e) {} 75 76 return false; 77 } else { 78 return exists(urand); 79 } 80 } 81 82 override { 83 84 /// Returns: Get the name of this PRNG. 85 @property 86 public pure nothrow string name() { 87 return "/dev/urandom"; 88 } 89 90 @trusted 91 public void nextBytes(ubyte[] buf) { 92 try { 93 urandFile.rawRead(buf); 94 }catch(Exception e) { 95 assert(false, text("URandomPRNG failed to get entropy from ",urand)); 96 } 97 } 98 99 public void addSeed(in ubyte[] seed) { 100 // dont do anything 101 } 102 } 103 104 private { 105 enum urand = "/dev/urandom"; 106 File urandFile; 107 } 108 109 }