Sign in Join
Wiki copytemporary

Dev random

Deutsch · English · Français

/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.

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.

pascal
{$ifdef UNIX}
(**
    initializes PRNG with data read from /dev/random
    
    Randomize initializes the pseudo-random number generator
    by storing a value read from /dev/random to system.randSeed.
    If reading fails, system.randomize will be used instead.
*)
procedure randomize;
const
    /// file name for random(4) device
    randomDeviceName = '/dev/random';
var
    /// reading buffer
    // same type as system.randSeed
    randomNumber: cardinal;
    /// file handle
    randomReader: file of cardinal;
begin
    assign(randomReader, randomDeviceName);
    {$push}
    // turn off run-time error generation
    {$IOChecks off}
    reset(randomReader);
    
    if IOResult() = 0 then
    begin
        // will possibly cause the error
        //   EInOutError: Read past end of file
        // if /dev/random is depleted
        read(randomReader, randomNumber);
        
        if IOResult() = 0 then
        begin
            system.randSeed := randomNumber;
        end
        else
        begin
            // do not call oneself => fully qualified identifier
            system.randomize;
        end;
        
        close(randomReader);
    end
    {$pop}
    else
    begin
        // do not call oneself => fully qualified identifier
        system.randomize;
    end;
end;
{$else}
{$hint program does not use randomize based on /dev/random}
{$endif}

When using gmp, the same applies.

delphi
program gmpRandomDemo(input, output, stderr);

// objFPC mode for try..finally-construct
{$mode objFPC}
{$typedAddress on}

uses
    // familiarize with C types
    cTypes,
    // familiarize with exception classes
    sysUtils,
    // use GNU multiple precision arithmetic library
    gmp;

const
    /// file name for random(4) device
    randomFileName = '/dev/random';

var
    /// reading buffer
    randomNumber: CULong;
    /// file handle for random number source
    randomReader: file of CULong;
    /// keeps GMP random number generator state
    prngState: randState_T;
    /// some arbitrary number
    i: MPZ_T;
begin
    MP_randInit_MT(prngState);
    assign(randomReader, randomFileName);
    try
        reset(randomReader);
        try
            try
                read(randomReader, randomNumber);
            except on eInOutError do
            begin
                randomize;
                randomNumber := random(high(int64));
            end;
            end;
        finally
            close(randomReader);
        end;
        MP_randSeed_UI(prngState, randomNumber);
        
        MPZ_init(i);
        try
            MPZ_uRandomB(i, prngState, 256);
            MP_printF('%Zd' + lineEnding, @i);
        finally
            MPZ_clear(i);
        end;
    finally 
        MP_randClear(prngState);
    end;
end.

multiple values

Multiple random values can be read by utilizing system.blockRead:

delphi
program multipleRandomValuesDemo(input, output, stdErr);

// include objpas unit
{$mode objFPC}

uses
    // familiarize with exception classes
    sysUtils;

const
    /// file name for urandom(4) device
    randomDeviceName = '/dev/urandom';

type
    /// base type for numbers in this program
    number = dWord;

var
    /// file handle for random number source
    randomFile: file of number;
    /// an array of numbers
    population: packed array[0..5] of number;
    /// temporary iterator variable
    i: number;

begin
    assignFile(randomFile, randomDeviceName);
    try
        reset(randomFile);
        try
            blockRead(randomFile, population, length(population));
        except on eInOutError do
            exitCode := 1;
        end;
    finally
        closeFile(randomFile);
    end;
    
    for i in population do
    begin
        writeLn(i:10);
    end;
end.

see also


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.

Revision 1, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.