Sign in Join
Wiki copytemporary

Dev random: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Dev random

OldNewLine
1+`/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]].
2+
3+The `u` in `urandom` stands for “unlimited”. Theoretically there is no limit on how much data one may obtain `/dev/urandom`.
4+
5+## quality
6+
7+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.
8+
9+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.
10+
11+- [Reading](https://www.freepascal.org/docs-html/rtl/baseunix/fpread.html) from `/dev/random` will be put on hold if the kernel has not gathered enough entropy to provide the requested amount of data.
12+- `/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.
13+
14+## application
15+
16+### seed
17+
18+Prior any call of [`system.random`](https://www.freepascal.org/docs-html/rtl/system/random.html) the programmer has to invoke [`system.randomize`](https://www.freepascal.org/docs-html/rtl/system/randomize.html) once, so [`system.randSeed`](https://www.freepascal.org/docs-html/rtl/system/randseed.html) provides a “random” value for the PRNG. The [default implementation](https://gitlab.com/freepascal.org/fpc/source/-/tree/release_3_2_0/rtl/linux/system.pp#L231-234) 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 [[RTL|run-time library]] comes with.
19+
20+``` pascal
21+{$ifdef UNIX}
22+(**
23+ initializes PRNG with data read from /dev/random
24+
25+ Randomize initializes the pseudo-random number generator
26+ by storing a value read from /dev/random to system.randSeed.
27+ If reading fails, system.randomize will be used instead.
28+*)
29+procedure randomize;
30+const
31+ /// file name for random(4) device
32+ randomDeviceName = '/dev/random';
33+var
34+ /// reading buffer
35+ // same type as system.randSeed
36+ randomNumber: cardinal;
37+ /// file handle
38+ randomReader: file of cardinal;
39+begin
40+ assign(randomReader, randomDeviceName);
41+ {$push}
42+ // turn off run-time error generation
43+ {$IOChecks off}
44+ reset(randomReader);
45+
46+ if IOResult() = 0 then
47+ begin
48+ // will possibly cause the error
49+ // EInOutError: Read past end of file
50+ // if /dev/random is depleted
51+ read(randomReader, randomNumber);
52+
53+ if IOResult() = 0 then
54+ begin
55+ system.randSeed := randomNumber;
56+ end
57+ else
58+ begin
59+ // do not call oneself => fully qualified identifier
60+ system.randomize;
61+ end;
62+
63+ close(randomReader);
64+ end
65+ {$pop}
66+ else
67+ begin
68+ // do not call oneself => fully qualified identifier
69+ system.randomize;
70+ end;
71+end;
72+{$else}
73+{$hint program does not use randomize based on /dev/random}
74+{$endif}
75+```
76+
77+When using [[gmp]], the same applies.
78+
79+```delphi
80+program gmpRandomDemo(input, output, stderr);
81+
82+// objFPC mode for try..finally-construct
83+{$mode objFPC}
84+{$typedAddress on}
85+
86+uses
87+ // familiarize with C types
88+ cTypes,
89+ // familiarize with exception classes
90+ sysUtils,
91+ // use GNU multiple precision arithmetic library
92+ gmp;
93+
94+const
95+ /// file name for random(4) device
96+ randomFileName = '/dev/random';
97+
98+var
99+ /// reading buffer
100+ randomNumber: CULong;
101+ /// file handle for random number source
102+ randomReader: file of CULong;
103+ /// keeps GMP random number generator state
104+ prngState: randState_T;
105+ /// some arbitrary number
106+ i: MPZ_T;
107+begin
108+ MP_randInit_MT(prngState);
109+ assign(randomReader, randomFileName);
110+ try
111+ reset(randomReader);
112+ try
113+ try
114+ read(randomReader, randomNumber);
115+ except on eInOutError do
116+ begin
117+ randomize;
118+ randomNumber := random(high(int64));
119+ end;
120+ end;
121+ finally
122+ close(randomReader);
123+ end;
124+ MP_randSeed_UI(prngState, randomNumber);
125+
126+ MPZ_init(i);
127+ try
128+ MPZ_uRandomB(i, prngState, 256);
129+ MP_printF('%Zd' + lineEnding, @i);
130+ finally
131+ MPZ_clear(i);
132+ end;
133+ finally
134+ MP_randClear(prngState);
135+ end;
136+end.
137+```
138+
139+### multiple values
140+
141+Multiple random values can be read by utilizing [`system.blockRead`](https://www.freepascal.org/docs-html/rtl/system/blockread.html):
142+
143+```delphi
144+program multipleRandomValuesDemo(input, output, stdErr);
145+
146+// include objpas unit
147+{$mode objFPC}
148+
149+uses
150+ // familiarize with exception classes
151+ sysUtils;
152+
153+const
154+ /// file name for urandom(4) device
155+ randomDeviceName = '/dev/urandom';
156+
157+type
158+ /// base type for numbers in this program
159+ number = dWord;
160+
161+var
162+ /// file handle for random number source
163+ randomFile: file of number;
164+ /// an array of numbers
165+ population: packed array[0..5] of number;
166+ /// temporary iterator variable
167+ i: number;
168+
169+begin
170+ assignFile(randomFile, randomDeviceName);
171+ try
172+ reset(randomFile);
173+ try
174+ blockRead(randomFile, population, length(population));
175+ except on eInOutError do
176+ exitCode := 1;
177+ end;
178+ finally
179+ closeFile(randomFile);
180+ end;
181+
182+ for i in population do
183+ begin
184+ writeLn(i:10);
185+ end;
186+end.
187+```
188+
189+## see also
190+
191+- [`/dev/random` on Wikipedia, the free online encyclopedia](https://en.wikipedia.org/wiki//dev/random)
192+- [[Generating Random Numbers|generating random numbers]], alternative algorithms
193+- [“random state seeding” in GMP’s documentation](https://gmplib.org/manual/Random-State-Seeding.html#Random-State-Seeding)
194+
195+---
196+*From the Free Pascal wiki, page "Dev random", as it stood on 2022-09-28 after a change by Kai Burghardt, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
197+Category: Code

Back to history