Difference between revisions of "Dev random"
m (→multiple values: typo) |
m (→multiple values: camelCase) |
||
Line 156: | Line 156: | ||
type | type | ||
/// base type for numbers in this program | /// base type for numbers in this program | ||
− | number = | + | number = dWord; |
var | var |
Revision as of 23:27, 21 November 2018
│
Deutsch (de) │
English (en) │
français (fr) │
/dev/random
and /dev/urandom
are two pseudo character devices providing user-land access to random data generated by the system.
Following the paradigm “everything is a file” they usually exist on Unix and *nix-based operating systems, like Linux or FreeBSD.
The u
in urandom
stands for the Greek letter μ, meaning “micro”.
The randomness of /dev/urandom
is reduced, in comparison to /dev/random
.
quality
On Linux the kernel will occasonially gather “environmental noise” like memory, disc, network throughput, or dumps from the kernel, as well as cryptography hardware if present and enabled.
The key difference between /dev/random
versus /dev/urandom
is, whether a threshold of enough entropy has to be reached, before random numbers are generated.
- Reading from
/dev/random
will be put on hold, if the kernel has not gathered enough entropy to provide the requested amount of data. /dev/urandom
on the other hand will not block to wait for more entropy. It will fall back to a pseudo-random number generator (PRNG), if and as long as there is a too small entropy pool.
application
seed
Prior any call of system.random
the programmer has to invoke system.randomize
once, so system.randSeed
provides a “random” value for the PRNG.
The default implementation uses the system clock for this, since this a value sort of available on all supported platforms.
However, its predictability is kind of unpleasant, although the argument system.randomize
's behavior should not differ significantly regarding quality and speed among platforms is reasonable.
If we want to, we can shadow system.randomize
by our own “better” implementation, while still relying on the fast Mersenne-Twister PRNG the standard runtime library comes with.
3{$ifdef UNIX}
4(**
5 initializes PRNG with data read from /dev/random
6
7 Randomize initializes the pseudo-random number generator
8 by storing a value read from /dev/random to system.randSeed.
9 If reading fails, system.randomize will be used instead.
10*)
11procedure randomize;
12const
13 /// file name for random(4) device
14 randomDeviceName = '/dev/random';
15var
16 /// reading buffer
17 // same type as system.randSeed
18 randomNumber: cardinal;
19 /// file handle
20 randomReader: file of cardinal;
21begin
22 assign(randomReader, randomDeviceName);
23 {$push}
24 // turn off run-time error generation
25 {$IOChecks off}
26 reset(randomReader);
27
28 if IOResult() <> 0 then
29 begin
30 // will possibly cause the error
31 // EInOutError: Read past end of file
32 // if /dev/random is depleted
33 read(randomReader, randomNumber);
34
35 if IOResult() <> 0 then
36 begin
37 system.randSeed := randomNumber;
38 end
39 else
40 begin
41 // do not call one-self => fully qualified identfier
42 system.randomize;
43 end;
44
45 close(randomReader);
46 end
47 {$pop}
48 else
49 begin
50 // do not call one-self => fully qualified identfier
51 system.randomize;
52 end;
53end;
54{$else}
55{$hint program does not use randomize based on /dev/random}
56{$endif}
When using gmp, the same applies.
1program gmpRandomDemo(input, output, stderr);
2
3// objFPC mode for try..finally-construct
4{$mode objFPC}
5{$typedAddress on}
6
7uses
8 // familiarze with C types
9 cTypes,
10 // familiarize with exception classes
11 sysUtils,
12 // use GNU multiple precision arithmetic library
13 gmp;
14
15const
16 /// file name for random(4) device
17 randomFileName = '/dev/random';
18
19var
20 /// reading buffer
21 randomNumber: CULong;
22 /// file handle for random number source
23 randomReader: file of CULong;
24 /// keeps GMP random number generator state
25 prngState: randState_T;
26 /// some arbitrary number
27 i: MPZ_T;
28begin
29 MP_randInit_MT(prngState);
30 assign(randomReader, randomFileName);
31 try
32 reset(randomReader);
33 try
34 try
35 read(randomReader, randomNumber);
36 except on eInOutError do
37 begin
38 randomize;
39 randomNumber := random(high(int64));
40 end;
41 end;
42 finally
43 close(randomReader);
44 end;
45 MP_randSeed_UI(prngState, randomNumber);
46
47 MPZ_init(i);
48 try
49 MPZ_uRandomB(i, prngState, 256);
50 MP_printF('%Zd' + lineEnding, @i);
51 finally
52 MPZ_clear(i);
53 end;
54 finally
55 MP_randClear(prngState);
56 end;
57end.
multiple values
Multiple random values can be read by utilizing system.blockRead
:
1program multipleRandomValuesDemo(input, output, stderr);
2
3// include objpas unit
4{$mode objFPC}
5
6uses
7 // familiarize with exception classes
8 sysUtils;
9
10const
11 /// file name for random(4) device
12 randomDeviceName = '/dev/random';
13
14type
15 /// base type for numbers in this program
16 number = dWord;
17
18var
19 /// file handle for random number source
20 randomFile: file of number;
21 /// an array of numbers
22 population: packed array[0..5] of number;
23 /// temporary iterator variable
24 i: number;
25
26begin
27 assignFile(randomFile, randomDeviceName);
28 try
29 reset(randomFile);
30 try
31 blockRead(randomFile, population, length(population));
32 except on eInOutError do
33 exitCode := 1;
34 end;
35 finally
36 closeFile(randomFile);
37 end;
38
39 for i in population do
40 begin
41 writeLn(i);
42 end;
43end.