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