1 module dcrypt.random.fortuna.sources.systemtick;
2 
3 import core.time;
4 
5 
6 import dcrypt.random.fortuna.entropysource;
7 import dcrypt.random.fortuna.fortuna: addEntropy;
8 
9 /// Generate entropy data with the system clock.
10 @safe
11 public class SystemTickEntropySource: EntropySource
12 {
13 
14 	override void collectEntropy() nothrow {
15 		ubyte[64] buf;
16 
17 		getTimingEntropy(buf);
18 
19 		sendEntropyEvent(buf);
20 	}
21 
22 	@nogc @property nothrow
23 	override public string name() {
24 		return "SystemTickSource";
25 	}
26 
27 	@safe @nogc nothrow
28 	override uint scheduleNext() {
29 		return 250;
30 	}
31 
32 }
33 
34 /// Fill the buffer with timing measurements.
35 /// Params:
36 /// buf = The buffer to fill.
37 @safe @nogc nothrow
38 static void getTimingEntropy(ubyte[] buf) {
39 	foreach(ref b; buf) {
40 		ulong ticks = MonoTime.currTime.ticks;
41 		b = cast(ubyte) (ticks^(ticks>>8)^(ticks>>16)); // Combine three bytes for the case if the system clock has low resolution.
42 	}
43 }
44 
45 unittest {
46 	ubyte[32] buf1, buf2;
47 	
48 	getTimingEntropy(buf1);
49 	getTimingEntropy(buf2);
50 	
51 	assert(buf1 != buf2, "Measurements are not at all random!");
52 }