Difference between revisions of "Dev random"
(several things) |
m (→seed: update Run‑Time Library source code link [Subversion → Git Laboratory]) |
||
(One intermediate revision by the same user not shown) | |||
Line 16: | Line 16: | ||
=== seed === | === seed === | ||
Prior any call of {{Doc|package=RTL|unit=system|identifier=random|text=<syntaxhighlight lang="pascal" inline>system.random</syntaxhighlight>}} the programmer has to invoke {{Doc|package=RTL|unit=system|identifier=randomize|text=<syntaxhighlight lang="pascal" inline>system.randomize</syntaxhighlight>}} once, so {{Doc|package=RTL|unit=system|identifier=randseed|text=<syntaxhighlight lang="pascal" inline>system.randSeed</syntaxhighlight>}} provides a “random” value for the PRNG. | Prior any call of {{Doc|package=RTL|unit=system|identifier=random|text=<syntaxhighlight lang="pascal" inline>system.random</syntaxhighlight>}} the programmer has to invoke {{Doc|package=RTL|unit=system|identifier=randomize|text=<syntaxhighlight lang="pascal" inline>system.randomize</syntaxhighlight>}} once, so {{Doc|package=RTL|unit=system|identifier=randseed|text=<syntaxhighlight lang="pascal" inline>system.randSeed</syntaxhighlight>}} provides a “random” value for the PRNG. | ||
− | The | + | The {{gitlab|repository|FPC|release_3_2_0/rtl/linux/system.pp#L231-234|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 <syntaxhighlight lang="pascal" inline>system.randomize</syntaxhighlight>’s behavior should not differ significantly regarding quality and speed among platforms is reasonable. | However, its predictability is kind of unpleasant, although the argument <syntaxhighlight lang="pascal" inline>system.randomize</syntaxhighlight>’s behavior should not differ significantly regarding quality and speed among platforms is reasonable. | ||
If we want to, we can shadow <syntaxhighlight lang="pascal" inline>system.randomize</syntaxhighlight> by our own “better” implementation, while still relying on the fast Mersenne-Twister PRNG the standard [[RTL|run-time library]] comes with. | If we want to, we can shadow <syntaxhighlight lang="pascal" inline>system.randomize</syntaxhighlight> by our own “better” implementation, while still relying on the fast Mersenne-Twister PRNG the standard [[RTL|run-time library]] comes with. | ||
Line 188: | Line 188: | ||
* [https://en.wikipedia.org/wiki//dev/random <code>/dev/random</code> on Wikipedia, the free online encyclopedia] | * [https://en.wikipedia.org/wiki//dev/random <code>/dev/random</code> on Wikipedia, the free online encyclopedia] | ||
* [[Generating Random Numbers|generating random numbers]], alternative algorithms | * [[Generating Random Numbers|generating random numbers]], alternative algorithms | ||
− | * [https://gmplib.org/manual/Random-State-Seeding.html#Random-State-Seeding “random state seeding” in | + | * [https://gmplib.org/manual/Random-State-Seeding.html#Random-State-Seeding “random state seeding” in GMP’s documentation] |
[[Category:Code]] | [[Category:Code]] |
Latest revision as of 13:49, 28 September 2022
│
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 “unlimited”.
Theoretically there is no limit on how much data one may obtain /dev/urandom
.
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 run-time 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 oneself => fully qualified identifier
42 system.randomize;
43 end;
44
45 close(randomReader);
46 end
47 {$pop}
48 else
49 begin
50 // do not call oneself => fully qualified identifier
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 // familiarize 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 urandom(4) device
12 randomDeviceName = '/dev/urandom';
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:10);
42 end;
43end.