LibISAAC
1.0.0
A modern reimplementation of the ISAAC CPRNG.
|
#include <stdint.h>
#include <stddef.h>
Go to the source code of this file.
Data Structures | |
struct | isaac_ctx_t |
Context of the ISAAC CPRNG. More... | |
Macros | |
#define | LIBISAAC_VERSION "1.0.0" |
Version of the LibISAAC API using semantic versioning. | |
#define | ISAAC_BITS 64 |
#define | ISAAC_ELEMENTS 256U |
Amount of elements in ISAAC's context arrays. | |
#define | ISAAC_SEED_MAX_BYTES ISAAC_ELEMENTS |
Max bytes supported in the seed. | |
Typedefs | |
typedef uint64_t | isaac_uint_t |
Functions | |
void | isaac_init (isaac_ctx_t *ctx, const uint8_t *seed, uint16_t seed_bytes) |
Initialises the ISAAC CPRNG with a seed. More... | |
void | isaac_stream (isaac_ctx_t *ctx, isaac_uint_t *ints, size_t amount) |
Provides the next pseudo-random integer. More... | |
void | isaac_cleanup (isaac_ctx_t *ctx) |
Safely erases the context. More... | |
void | isaac_to_little_endian (uint8_t *bytes, const isaac_uint_t *values, size_t amount_of_values) |
Utility function, converting an array of 32-bit/64-bit integers into bytes using little endian byte order. More... | |
void | isaac_to_big_endian (uint8_t *bytes, const isaac_uint_t *values, size_t amount_of_values) |
Utility function, converting an array of 32-bit/64-bit integers into bytes using big endian byte order. More... | |
This library offers the tiny and fast ISAAC cryptographically secure pseudo random number generator (CSPRNG), in its 32-bit and 64-bit version wrapped into a modern, ISO C11, documented API, ready for embedded usage.
Use the ISAAC_BITS macro to compile LibISAAC optimised for 32 or 64 bits. The 32 bit is the classic ISAAC; the 64 bit is ISAAC-64. Note that the output differs between the two and the context grows twice in size when using the 64 bit version, but you also get twice the bytes per reshuffling.
Then the usage of ISAAC is easy:
About ISAAC
Quoting from its web page:
ISAAC (Indirection, Shift, Accumulate, Add, and Count) generates 32-bit random numbers. Averaged out, it requires 18.75 machine cycles to generate each 32-bit value. Cycles are guaranteed to be at least 240 values long, and they are 28295 values long on average. The results are uniformly distributed, unbiased, and unpredictable unless you know the seed. [...] ISAAC-64 generates a different sequence than ISAAC, but it uses the same principles. It uses 64-bit arithmetic. It generates a 64-bit result every 19 instructions. All cycles are at least 272 values, and the average cycle length is 216583.
ISAAC and its original source code is created by Bob Jenkins and released into the public domain.
This implementation is based on the original rand.c
and isaac64.c
, which uses 32-bit and 64-bit words respectively.
ISAAC_BITS 64 |
Set it to 32 or 64 to optimise ISAAC for 32 or 64 bit words respectively.
The 32 bit is the classic ISAAC; the 64 bit is ISAAC-64. Note that the output differs between the two and the context grows twice in size when using the 64 bit version, but you also get twice the bytes per reshuffling.
An integer or word used by ISAAC, either a uint32_t or uint64_t.
void isaac_init | ( | isaac_ctx_t * | ctx, |
const uint8_t * | seed, | ||
uint16_t | seed_bytes | ||
) |
Initialises the ISAAC CPRNG with a seed.
The seed is copied value-wise into the ISAAC state, not byte-wise. That means that a uint8_t array {1,2,3,4} is copied into the ctx->result[] isaac_uint_t array as {1,2,3,4,0,...,0}, where each value is a isaac_uint_t value. Looking at the bytes and assuming little Endian byte order, the result is {1,2,3,4} --> {1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,0,...,0}.
The reason behind this choice is to avoid issues with endianness; as ISAAC works on isaac_uint_t values rather than their bytes, setting the isaac_uint_t values and not their bytes, shall produce the same CPRNG stream on architectures with different endianness. An isaac_uint_t* could also be a valid choice as seed input, but seeds are usually cryptographic keys and those are byte arrays, so a developer could be confused on how to insert a uint8_t* seed into a isaac_uint_t*.
Maps to void randinit(randctx *r, word flag)
from the original implementation. Equivalent to a true flag
with a seed provided. The false flag
is not available, as it should not be used for security purposes.
[in,out] | ctx | the ISAAC state to be initialised. Does nothing when NULL. |
[in] | seed | pointer to the seed to use, which is copied into the context.
|
[in] | seed_bytes | amount of bytes in the seed, max ISAAC_SEED_MAX_BYTES.
|
void isaac_stream | ( | isaac_ctx_t * | ctx, |
isaac_uint_t * | ints, | ||
size_t | amount | ||
) |
Provides the next pseudo-random integer.
Because ISAAC works on 32 or 64 bit values, the stream is in integers instead of bytes. To convert them to bytes:
Every ISAAC_ELEMENTS values generated it will automatically reshuffle the ISAAC state to cache ISAAC_ELEMENTS new elements. This means that the first ISAAC_ELEMENTS values after seeding are very cheap (just copying values from the state) and the ISAAC_ELEMENTS+1st value is more expensive and so on.
[in,out] | ctx | the ISAAC state, already initialised. Does nothing when NULL. |
[out] | ints | pseudo-random integers. Does nothing when NULL. |
[in] | amount | quantity of 32-bit/64-bit integers to generate. |
void isaac_cleanup | ( | isaac_ctx_t * | ctx | ) |
Safely erases the context.
Useful to avoid leaking information about the seed or the state after finishing using ISAAC.
There is no need to call this function before using isaac_init(), including when re-initing an existing context.
[in,out] | ctx | the ISAAC state to cleanup. Does nothing when NULL. |
void isaac_to_little_endian | ( | uint8_t * | bytes, |
const isaac_uint_t * | values, | ||
size_t | amount_of_values | ||
) |
Utility function, converting an array of 32-bit/64-bit integers into bytes using little endian byte order.
Useful to convert a stream of 32-bit/64-bit integers to 8-bit values.
[out] | bytes | 8-bit integers. Must be at least amount_of_values*4 bytes long. Does nothing when NULL. |
[in] | values | 32-bit/64-bit integers, as obtained from isaac_stream(). Does nothing when NULL. |
[in] | amount_of_values | quantity of 32-bit/64-bit integers in the values buffer. |
void isaac_to_big_endian | ( | uint8_t * | bytes, |
const isaac_uint_t * | values, | ||
size_t | amount_of_values | ||
) |
Utility function, converting an array of 32-bit/64-bit integers into bytes using big endian byte order.
Useful to convert a stream of 32-bit/64-bit integers to 8-bit values.
[out] | bytes | 8-bit integers. Must be at least amount_of_values*4 bytes long. Does nothing when NULL. |
[in] | values | 32-bit/64-bit integers, as obtained from isaac_stream(). Does nothing when NULL. |
[in] | amount_of_values | quantity of 32-bit/64-bit integers in the values buffer. |