1 module dcrypt.random.fortuna.sources.reboot; 2 3 /// The reboot entropy source loads entropy from a specified file 4 /// and updates the seed in this file with new random data. 5 /// The goal of this entropy source is to provide good entropy at start of 6 /// the program. This is however not the case when the program is run the first time. 7 8 import dcrypt.random.fortuna.entropysource; 9 import dcrypt.random.fortuna.fortuna; 10 11 import std.stdio; 12 import std.file; 13 14 private enum blockSize = 32*32; 15 private enum blocksPerFile = 16; 16 17 @safe 18 public class RebootEntropySource: EntropySource 19 { 20 21 private string seedFile; 22 private Fortuna rng; 23 private uint blockCounter = 0; 24 private uint delay = 1; 25 26 /// Params: 27 /// seedFile = The file to load the seed from and to store new seed. 28 this(string seedFile) nothrow 29 { 30 this.seedFile = seedFile; 31 } 32 33 /// Read entropy from file. 34 @trusted 35 override public void collectEntropy() nothrow { 36 37 delay = 0; // one shot 38 39 if(exists(seedFile)) { 40 try { 41 // read whole file and send it to the accumulator 42 File inputFile = File(seedFile, "rb"); 43 44 scope(exit) { 45 inputFile.close(); 46 } 47 48 foreach(ubyte[] c; inputFile.chunks(32)) { 49 sendEntropyEvent(c); 50 } 51 52 53 } catch (Exception e) { 54 55 // TODO 56 assert(false, "error opening entropy file"); 57 } 58 } 59 } 60 61 @nogc @property nothrow 62 override public string name() { 63 return "RebootSource"; 64 } 65 66 @safe @nogc nothrow 67 override uint scheduleNext() { 68 return delay; 69 } 70 71 /// Get random data from Fortuna and store it to a file for use at next program start. 72 @trusted 73 private void storeEntropy() nothrow { 74 try { 75 ubyte[32] buf; 76 77 File f = File(seedFile, "wb"); 78 79 //f.seek(blockSize*blockCounter, SEEK_SET); // FIXME seek does not work as intended 80 81 foreach(i; 0..32) { 82 rng.nextBytes(buf); 83 f.rawWrite(buf); 84 } 85 86 blockCounter++; 87 blockCounter %= blocksPerFile; 88 89 }catch (Exception e) { 90 version(assert) { 91 assert(false, "'reboot' entropy source: could not store entropy to file!"); 92 } 93 // TODO use a logger 94 } 95 } 96 97 ~this() { 98 storeEntropy(); 99 } 100 } 101