| 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/urandomis 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
hdargument 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)andhdrbg_rand(foo)are both valid invocations ofhdrbg_rand—the former generates a pseudorandom number using the internal HDRBG object, and the latter does so usingfoo.
- If it is
- Whenever a function has a Python API, there is no option to specify the
hdargument. 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 hdrbgand thenhelp(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.
- The Python API functions are given names similar to those below. Nevertheless, you can see a summary by entering
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. |
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.
dmaWhether to use dynamic memory allocation. Iftrue, an HDRBG object will be allocated dynamically and initialised. Iffalse, 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.
hdHDRBG object to reinitialise. IfNULL, the internal HDRBG object will be reinitialised.- →
- On success:
hd. - On failure:
NULL.
- On success:
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.
hdHDRBG object to use. IfNULL, the internal HDRBG object will be used.prediction_resistanceWhether prediction resistance is desired (i.e. whether the HDRBG object should be reinitialised before generating the bytes). Prediction resistance makes the next state ofhdunpredictable even if its current state were to somehow become known.r_bytesArray to store the generated bytes in. (It must have sufficient space forr_lengthelements.)r_lengthNumber 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.
hdHDRBG object to use. IfNULL, 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.
hdHDRBG object to use. IfNULL, the internal HDRBG object will be used.modulusRight end of the interval. Must be positive.- →
- On success: uniform pseudorandom integer in the range 0 (inclusive) to
modulus(exclusive). - On failure: 264 − 1.
- On success: uniform pseudorandom integer in the range 0 (inclusive) to
| 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.
hdHDRBG object to use. IfNULL, the internal HDRBG object will be used.leftLeft end of the interval.rightRight end of the interval. Must be greater thanleft.- →
- On success: uniform pseudorandom integer in the range
left(inclusive) toright(exclusive). - On failure: −1.
- On success: uniform pseudorandom integer in the range
| 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.
hdHDRBG object to use. IfNULL, 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.
hdHDRBG object to use. IfNULL, the internal HDRBG object will be used.countNumber 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.
hdHDRBG object to zero and destroy. IfNULL, 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_bytesArray of bytes representing the big-endian data to display.m_lengthNumber of bytes to display.