1 module dcrypt.random.fortuna.sources.filesource; 2 3 /// Read entropy from a file or special file (/dev/urandom). 4 5 import dcrypt.random.fortuna.entropysource; 6 import dcrypt.random.fortuna.fortuna; 7 8 import std.stdio; 9 import std.file; 10 11 //version (linux) { 12 // /// Get entropy from /dev/urandom 13 // unittest { 14 // import std.algorithm: any; 15 // FileEntropySource fs = new FileEntropySource("/dev/urandom"); 16 // 17 // ubyte[32] buf; 18 // ubyte[] slice = fs.getEntropy(buf); 19 // 20 // assert(slice.length == buf.length, "No data read from /dev/urandom"); 21 // assert(any!"a != 0"(slice), "Got only zeros from /dev/urandom"); 22 // } 23 //} 24 25 @safe 26 public class FileEntropySource: EntropySource 27 { 28 29 private string seedFile; 30 private File inputFile; 31 private uint delay = 250; 32 33 /// Params: 34 /// seedFile = The file to load the seed from and to store new seed. 35 /// Throws: `ErrnoException` if the seed file can not be opened for reading. 36 this(string seedFile) 37 { 38 this.seedFile = seedFile; 39 inputFile = File(seedFile, "rb"); 40 } 41 42 /// Read entropy from file. 43 @trusted 44 override public void collectEntropy() nothrow { 45 46 ubyte[32] buf; 47 ubyte[] slice = buf[0..0]; 48 49 if(inputFile.isOpen) { 50 // get entropy 51 try { 52 53 slice = inputFile.rawRead(buf); 54 55 if(slice.length < buf.length) { 56 // No remaining data in file 57 // disable scheduling 58 59 delay = 0; 60 } 61 62 } catch (Exception e) { 63 // TODO 64 assert(false, "error reading entropy file"); 65 } 66 } else { 67 delay = 0; // disable scheduling 68 } 69 70 sendEntropyEvent(slice); 71 } 72 73 @nogc @property nothrow 74 override public string name() { 75 return "FileSource"; 76 } 77 78 @safe @nogc nothrow 79 override uint scheduleNext() { 80 return delay; 81 } 82 83 84 ~this() { 85 if(inputFile.isOpen) { 86 inputFile.close(); 87 } 88 } 89 } 90