Difference between revisions of "Dev random"
m (remove ignored display title) |
(several things) |
||
Line 3: | Line 3: | ||
Following the paradigm “everything is a file” they usually exist on Unix and *nix-based operating systems, like [[Linux]] or [[FreeBSD]]. | Following the paradigm “everything is a file” they usually exist on Unix and *nix-based operating systems, like [[Linux]] or [[FreeBSD]]. | ||
− | The <code>u</code> in <code>urandom</code> stands for | + | The <code>u</code> in <code>urandom</code> stands for “unlimited”. |
− | + | Theoretically there is no limit on how much data one may obtain <code>/dev/urandom</code>. | |
== quality == | == 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. | 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 <code>/dev/random</code> versus <code>/dev/urandom</code> is | + | The key difference between <code>/dev/random</code> versus <code>/dev/urandom</code> is whether a threshold of enough entropy has to be reached before random numbers are generated. |
− | * {{Doc|package=RTL|unit=baseunix|identifier=fpread|text=Reading}} from <code>/dev/random</code> will be put on hold | + | * {{Doc|package=RTL|unit=baseunix|identifier=fpread|text=Reading}} from <code>/dev/random</code> will be put on hold if the kernel has not gathered enough entropy to provide the requested amount of data. |
− | * <code>/dev/urandom</code> on the other hand will not block to wait for more entropy. It will fall back to a pseudo-random number generator (PRNG) | + | * <code>/dev/urandom</code> 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 == | == application == | ||
=== seed === | === seed === | ||
− | Prior any call of {{Doc|package=RTL|unit=system|identifier=random|text=<syntaxhighlight lang="pascal" | + | 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 [https://svn.freepascal.org/cgi-bin/viewvc.cgi/tags/release_3_0_4/rtl/linux/system.pp?view=markup#l142 default implementation] uses the system clock for this, since this a value sort of available on all supported platforms. | The [https://svn.freepascal.org/cgi-bin/viewvc.cgi/tags/release_3_0_4/rtl/linux/system.pp?view=markup#l142 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" | + | 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" | + | 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. |
<syntaxhighlight lang="pascal" line start="3"> | <syntaxhighlight lang="pascal" line start="3"> | ||
{$ifdef UNIX} | {$ifdef UNIX} | ||
Line 58: | Line 58: | ||
else | else | ||
begin | begin | ||
− | // do not call | + | // do not call oneself => fully qualified identifier |
system.randomize; | system.randomize; | ||
end; | end; | ||
Line 67: | Line 67: | ||
else | else | ||
begin | begin | ||
− | // do not call | + | // do not call oneself => fully qualified identifier |
system.randomize; | system.randomize; | ||
end; | end; | ||
Line 85: | Line 85: | ||
uses | uses | ||
− | // | + | // familiarize with C types |
cTypes, | cTypes, | ||
// familiarize with exception classes | // familiarize with exception classes | ||
Line 138: | Line 138: | ||
=== multiple values === | === multiple values === | ||
− | Multiple random values can be read by utilizing {{Doc|package=RTL|unit=system|identifier=blockread|text=<syntaxhighlight lang="pascal" | + | Multiple random values can be read by utilizing {{Doc|package=RTL|unit=system|identifier=blockread|text=<syntaxhighlight lang="pascal" inline>system.blockRead</syntaxhighlight>}}: |
<syntaxhighlight lang="delphi" line highlight="31"> | <syntaxhighlight lang="delphi" line highlight="31"> | ||
− | program multipleRandomValuesDemo(input, output, | + | program multipleRandomValuesDemo(input, output, stdErr); |
// include objpas unit | // include objpas unit | ||
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]] |
Revision as of 09:50, 24 June 2020
│
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.