1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
  
10
  
11
  
12
  
13
  
14
  
15
  
16
  
17
  
18
  
19
  
20
  
21
  
22
  
23
  
24
  
25
  
26
  
27
  
28
  
29
  
30
  
31
  
32
  
33
  
34
  
35
  
36
  
37
  
38
  
39
  
40
  
41
  
42
  
43
  
44
  
45
  
46
  
47
  
48
  
49
  
50
  
51
  
52
  
#pike __REAL_VERSION__ 
#pragma strict_types 
 
inherit Random.Fast; 
 
constant dont_dump_program = 1; 
 
//! This module contains a pseudo random number generator (PRNG) 
//! designed to give you the best possible random number generation. 
//! The current design is based on the Fortuna PRNG, but uses the 
//! system random source as input. 
 
protected System.Timer last_seed = System.Timer(); 
 
protected void reseed(string(8bit)data) 
{ 
  last_seed->get(); 
  ::reseed(data); 
} 
 
//! Returns a string of length @[len] with random content. The content 
//! is generated by a Fortuna random generator that is updated with 
//! output from /dev/urandom on UNIX and CryptGenRandom on NT. 
string(8bit) random_string(int(0..) len) 
{ 
  // The original Fortuna design has an entropy pool reseeding the 
  // generator when enough external events have been collected, but 
  // not more often than every 100 ms. Since we are pulling entropy 
  // rather than having it pushed, we do it if more than 100 ms has 
  // passed since last call. 
  if( last_seed->peek()>0.1 ) 
    create(); 
  return ::random_string(len); 
} 
 
//! Inject additional entropy into the random generator. One possible 
//! use is to persist random data between executions of an 
//! application. The internal state is approximately 256 bits, so 
//! storing 32 bytes from @[random_string()] at shutdown and injecting 
//! them through @[add_entropy()] again at startup should carry over 
//! the entropy. Note that this doesn't affect the independent 
//! initialization that happens in the generator at startup, so the 
//! output sequence will be different than if the application had 
//! continued uninterrupted. 
//! @param data 
//!   The random string. 
void add_entropy(string(8bit) data) 
{ 
  reseed(data); 
}