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)
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
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 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.
dma
Whether 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.
hd
HDRBG 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.
hd
HDRBG object to use. IfNULL
, 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 ofhd
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 forr_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. 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.
hd
HDRBG object to use. IfNULL
, 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.
- 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.
hd
HDRBG object to use. IfNULL
, the internal HDRBG object will be used.left
Left end of the interval.right
Right 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.
hd
HDRBG 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.
hd
HDRBG object to use. IfNULL
, 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. 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_bytes
Array of bytes representing the big-endian data to display.m_length
Number of bytes to display.