Skip to content

Latest commit

 

History

History

doc

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

Technical Information

Property Value
Security Strength 256 bits
Hash SHA-256
Prediction Resistance Yes
Additional Input No
Personalisation String No
  • In C, a byte need not be 8 bits wide. However, this implementation uses the term 'byte' to refer to an 8-bit number. Hence, fixed-width integer types are used liberally.
  • SHA-256 has been implemented from scratch, because I wanted this package to have no dependencies.
    • However, if OpenSSL development libraries are found, its SHA-256 implementation is used if the C compiler provides 8-bit bytes.
  • /dev/urandom is read to obtain entropy for seeding and reseeding.
    • It is assumed to always provide sufficient entropy.
  • Nonces are generated by appending a monotonically increasing sequence number to the timestamp.
    • If the compiler supports standard atomics, the sequence number is an atomic integer—whence, in a process with multiple threads, no two threads will generate the same nonce.
    • Otherwise, two threads might end up with the same nonce because of a data race. (Two threads in different processes which load the library at the same time will also generate the same nonce, because the sequence number is initialised to 0.) Which shouldn't be a problem, because their entropy inputs will be different with high probability.
  • The hd argument of any function (where applicable) denotes the HDRBG object to use.
    • If it is NULL, the internal HDRBG object is used.
    • For instance, hdrbg_rand(NULL) and hdrbg_rand(foo) are both valid invocations of hdrbg_rand—the former generates a pseudorandom number using the internal HDRBG object, and the latter does so using foo.
  • Whenever a function has a Python API, there is no option to specify the hd argument. In other words, all Python functions use the internal HDRBG object. The CPython implementation has a global interpreter lock, and (looking at the Python bytecode disassembly) a C function call corresponds to a single Python bytecode instruction. Hence, there are no race conditions to worry about, and the provided functions are thread-safe.
    • The Python API functions are given names similar to those below. Nevertheless, you can see a summary by entering import hdrbg and then help(hdrbg) at the Python REPL.
    • It is possible for a Python integer to not be exactly representable as a C integer. To mitigate this, appropriate range checks are automatically done on all Python integers.

Types

struct hdrbg_t;

The type of an HDRBG object. It is implemented as an opaque struct.


enum hdrbg_err_t;

The type of the error indicator. It can take the following values.

Value Description
HDRBG_ERR_NONE No error.
HDRBG_ERR_OUT_OF_MEMORY Dynamic memory allocation failed.
HDRBG_ERR_NO_ENTROPY No entropy could be obtained from /dev/urandom.
HDRBG_ERR_INSUFFICIENT_ENTROPY Insufficient entropy was obtained from /dev/urandom.
HDRBG_ERR_INVALID_REQUEST_FILL The r_length argument of a call to hdrbg_fill was greater than 65536.
HDRBG_ERR_INVALID_REQUEST_UINT The modulus argument of a call to hdrbg_uint was 0.
HDRBG_ERR_INVALID_REQUEST_SPAN The right argument of a call to hdrbg_span was less than or equal to left.

Functions

enum hdrbg_err_t hdrbg_err_get(void);

Obtain the error indicator (which is a global variable similar to errno, but cannot be accessed directly). If the compiler supports standard threads, a separate error indicator is maintained for each thread.

Calling this function clears the error indicator. For instance, if it is called twice in succession, the first call may return HDRBG_ERR_OUT_OF_MEMORY, but the second call will return HDRBG_ERR_NONE.

  • → Error indicator.

In theory, each of the below functions can error out, so a call to each of them should be followed by a call to this function to check for errors (and disambiguate the return value). Assume that any error other than the invalid request errors leaves the pseudorandom number generator in an intermediate state, making it cryptographically insecure for further use.

In practice, on a modern system with loads of memory and entropy, the invalid request errors are the only ones which you can realistically expect.


struct hdrbg_t *hdrbg_init(bool dma);

Create and/or initialise (seed) an HDRBG object.

  • dma Whether to use dynamic memory allocation. If true, an HDRBG object will be allocated dynamically and initialised. If false, the internal HDRBG object will be initialised.
    • On success: initialised HDRBG object.
    • On failure: NULL.

If dma is true and this function succeeds, the returned HDRBG object must be destroyed using hdrbg_zero to avoid memory leaks.

C Python Equivalent
hdrbg_init(false) import hdrbg

struct hdrbg_t *hdrbg_reinit(struct hdrbg_t *hd);

Reinitialise (reseed) an HDRBG object. If it had not been previously initialised, the behaviour is undefined.

  • hd HDRBG object to reinitialise. If NULL, the internal HDRBG object will be reinitialised.
    • On success: hd.
    • On failure: NULL.

int hdrbg_fill(struct hdrbg_t *hd, bool prediction_resistance, uint8_t *r_bytes, int long unsigned r_length);

Generate cryptographically secure pseudorandom bytes using an HDRBG object. If it had not been previously initialised/reinitialised, the behaviour is undefined.

  • hd HDRBG object to use. If NULL, the internal HDRBG object will be used.
  • prediction_resistance Whether prediction resistance is desired (i.e. whether the HDRBG object should be reinitialised before generating the bytes). Prediction resistance makes the next state of hd unpredictable even if its current state were to somehow become known.
  • r_bytes Array to store the generated bytes in. (It must have sufficient space for r_length elements.)
  • r_length Number of bytes to generate. At most 65536.
    • On success: 0.
    • On failure: −1.

Calling this function will change the state of the HDRBG object. (Even if r_length is 0.)

C Python Equivalent
hdrbg_fill(NULL, false, r_bytes, r_length) hdrbg.fill(r_length)

uint64_t hdrbg_rand(struct hdrbg_t *hd);

Generate a cryptographically secure pseudorandom number using an HDRBG object. If it had not been previously initialised/reinitialised, the behaviour is undefined. This function internally uses hdrbg_fill without prediction resistance.

  • hd HDRBG object to use. If NULL, the internal HDRBG object will be used.
    • On success: uniform pseudorandom integer in the range 0 (inclusive) to 264 − 1 (inclusive).
    • On failure: 264 − 1.
C Python Equivalent
hdrbg_rand(NULL) hdrbg.rand()

uint64_t hdrbg_uint(struct hdrbg_t *hd, uint64_t modulus);

Generate a cryptographically secure pseudorandom residue using an HDRBG object. If it had not been previously initialised/reinitialised, the behaviour is undefined. This function internally uses hdrbg_fill without prediction resistance.

  • hd HDRBG object to use. If NULL, the internal HDRBG object will be used.
  • modulus Right end of the interval. Must be positive.
    • On success: uniform pseudorandom integer in the range 0 (inclusive) to modulus (exclusive).
    • On failure: 264 − 1.
C Python Equivalent
hdrbg_uint(NULL, modulus) hdrbg.uint(modulus)

int64_t hdrbg_span(struct hdrbg_t *hd, int64_t left, int64_t right);

Generate a cryptographically secure pseudorandom residue offset using an HDRBG object. If it had not been previously initialised/reinitialised, the behaviour is undefined. This function internally uses hdrbg_fill without prediction resistance.

  • hd HDRBG object to use. If NULL, the internal HDRBG object will be used.
  • left Left end of the interval.
  • right Right end of the interval. Must be greater than left.
    • On success: uniform pseudorandom integer in the range left (inclusive) to right (exclusive).
    • On failure: −1.
C Python Equivalent
hdrbg_span(NULL, left, right) hdrbg.span(left, right)

double long hdrbg_real(struct hdrbg_t *hd);

Generate a cryptographically secure pseudorandom fraction using an HDRBG object. If it had not been previously initialised/reinitialised, the behaviour is undefined. This function internally uses hdrbg_fill without prediction resistance.

  • hd HDRBG object to use. If NULL, the internal HDRBG object will be used.
    • On success: uniform pseudorandom real in the range 0 (inclusive) to 1 (inclusive).
    • On failure: −1.
C Python Equivalent
hdrbg_real(NULL) hdrbg.real()

int hdrbg_drop(struct hdrbg_t *hd, int long long count);

Advance the state of an HDRBG object. Equivalent to running hdrbg_fill(hd, false, NULL, 0) count times and discarding the results.

  • hd HDRBG object to use. If NULL, the internal HDRBG object will be used.
  • count Number times to advance the state. If not positive, this function has no effect.
    • On success: 0.
    • On failure: −1.
C Python Equivalent
hdrbg_drop(NULL, count) hdrbg.drop(count)

void hdrbg_zero(struct hdrbg_t *hd);

Zero (clear) and/or destroy an HDRBG object, making it unsuitable for further use.

  • hd HDRBG object to zero and destroy. If NULL, the internal HDRBG object will be zeroed.
C Python Equivalent
hdrbg_zero(NULL) Closing the Python interpreter

void hdrbg_dump(uint8_t const *m_bytes, size_t m_length);

Display the given data in hexadecimal form.

  • m_bytes Array of bytes representing the big-endian data to display.
  • m_length Number of bytes to display.