# Dev random

Jump to: navigation, search

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.

1. {$ifdef UNIX} 2. (** 3.  initializes PRNG with data read from /dev/random 4.   5.  Randomize initializes the pseudo-random number generator 6.  by storing a value read from /dev/random to system.randSeed. 7.  If reading fails, system.randomize will be used instead. 8. *) 9. procedure randomize; 10. const 11.  /// file name for random(4) device 12.  randomDeviceName = '/dev/random'; 13. var 14.  /// reading buffer 15.  // same type as system.randSeed 16.  randomNumber: cardinal; 17.  /// file handle 18.  randomReader: file of cardinal; 19. begin 20.  assign(randomReader, randomDeviceName); 21.  {$push}
22. 	// turn off run-time error generation
23. 	{$IOChecks off} 24.  reset(randomReader); 25.   26.  if IOResult() = 0 then 27.  begin 28.  // will possibly cause the error 29.  // EInOutError: Read past end of file 30.  // if /dev/random is depleted 31.  read(randomReader, randomNumber); 32.   33.  if IOResult() = 0 then 34.  begin 35.  system.randSeed := randomNumber; 36.  end 37.  else 38.  begin 39.  // do not call one-self => fully qualified identfier 40.  system.randomize; 41.  end; 42.   43.  close(randomReader); 44.  end 45.  {$pop}
46. 	else
47. 	begin
48. 		// do not call one-self => fully qualified identfier
49. 		system.randomize;
50. 	end;
51. end;
52. {$else} 53. {$hint program does not use randomize based on /dev/random}
54. {$endif} When using gmp, the same applies. 1. program gmpRandomDemo(input, output, stderr); 2.   3. // objFPC mode for try..finally-construct 4. {$mode objFPC}
5. {$typedAddress on} 6.   7. uses 8.  // familiarze with C types 9.  cTypes, 10.  // familiarize with exception classes 11.  sysUtils, 12.  // use GNU multiple precision arithmetic library 13.  gmp; 14.   15. const 16.  /// file name for random(4) device 17.  randomFileName = '/dev/random'; 18.   19. var 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; 28. begin 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; 57. end. ### multiple values Multiple random values can be read by utilizing system.blockRead: 1. program multipleRandomValuesDemo(input, output, stderr); 2.   3. // include objpas unit 4. {$mode objFPC}
5. 
6. uses
7. 	// familiarize with exception classes
8. 	sysUtils;
9. 
10. const
11. 	/// file name for urandom(4) device
12. 	randomDeviceName = '/dev/urandom';
13. 
14. type
15. 	/// base type for numbers in this program
16. 	number = dWord;
17. 
18. var
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. 
26. begin
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;
43. end.