Skip to content

Instantly share code, notes, and snippets.

@opsec-ee
Last active September 14, 2025 05:35
Show Gist options
  • Select an option

  • Save opsec-ee/623fb12bdb9a31cc011d5c13668e0a8d to your computer and use it in GitHub Desktop.

Select an option

Save opsec-ee/623fb12bdb9a31cc011d5c13668e0a8d to your computer and use it in GitHub Desktop.
/**
* ISAAC CSPRNG High-Performance Implementation v2.0.0
*
* Based on Bob Jenkins' ISAAC algorithm (1993) - Public Domain
*
* Version: 2.0.0 - H.Overman <opsec.ee@pm.me>
* Date: 2025-01-13
* License: Public Domain (following original ISAAC license)
*/
#define _GNU_SOURCE
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/* ============================================================================
* VERSION INFORMATION
* ============================================================================
*/
#define ISAAC_VERSION_MAJOR 2U
#define ISAAC_VERSION_MINOR 0U
#define ISAAC_VERSION_PATCH 0U
#define ISAAC_VERSION_STRING "2.0.0"
/* ============================================================================
* COMPILER OPTIMIZATION HINTS
* ============================================================================
*/
#ifdef __GNUC__
#define LIKELY(x) __builtin_expect(!!(x), 1)
#define UNLIKELY(x) __builtin_expect(!!(x), 0)
#define FORCE_INLINE __attribute__((always_inline)) inline
#define RESTRICT __restrict__
#define CACHE_ALIGN __attribute__((aligned(CACHE_LINE_SIZE)))
#define PREFETCH_READ(addr) __builtin_prefetch(addr, 0, 3)
#define PREFETCH_WRITE(addr) __builtin_prefetch(addr, 1, 3)
#define UNUSED __attribute__((unused))
#define PACKED __attribute__((packed))
#else
#define LIKELY(x) (x)
#define UNLIKELY(x) (x)
#define FORCE_INLINE inline
#define RESTRICT
#define CACHE_ALIGN
#define PREFETCH_READ(addr) ((void)0)
#define PREFETCH_WRITE(addr) ((void)0)
#define UNUSED
#define PACKED
#endif
/* ============================================================================
* SYSTEM CONSTANTS - No Magic Numbers (OPT-000: TS-001)
* ============================================================================
*/
#define CACHE_LINE_SIZE 64U
#define BITS_PER_BYTE 8U
#define HEX_CHARS_PER_BYTE 2U
#define UINT32_BYTES 4U
/* ============================================================================
* ISAAC ALGORITHM CONSTANTS
* ============================================================================
*/
#define ISAAC_STATE_SIZE 256U
#define ISAAC_RESULT_SIZE 256U
#define ISAAC_GOLDEN_RATIO 0x9E3779B9U
#define ISAAC_LOG_SIZE 8U
#define ISAAC_MASK 0xFFU
/* ASCII printable range */
#define ISAAC_ASCII_START 32U
#define ISAAC_ASCII_RANGE 95U
#define ISAAC_ASCII_END 126U
/* Unrolling factors */
#define ISAAC_UNROLL_FACTOR 4U
#define ISAAC_MIX_UNROLL 8U
#define ISAAC_PREFETCH_DIST 32U
/* Shift constants */
#define ISAAC_SHIFT1 13U
#define ISAAC_SHIFT2 6U
#define ISAAC_SHIFT3 2U
#define ISAAC_SHIFT4 16U
#define ISAAC_INDEX_SHIFT 2U
#define ISAAC_RESULT_SHIFT 10U
/* Buffer sizes */
#define MAX_MESSAGE_SIZE 8192U
#define HEX_BUFFER_SIZE ((MAX_MESSAGE_SIZE * HEX_CHARS_PER_BYTE) + 1U)
/* FUTURE USE: B-tree Integration Constants */
#define BTREE_PAGE_SIZE 4096U
#define BTREE_KEY_SIZE 32U
#define BTREE_MAC_SIZE 16U
#define BTREE_NONCE_SIZE 16U
/* ============================================================================
* TYPE DEFINITIONS (OPT-000: NC-002)
* ============================================================================
*/
/**
* @brief Error codes for ISAAC operations
*/
typedef enum isaac_error {
ISAAC_SUCCESS = 0,
ISAAC_ERROR_NULL_PARAM = -1,
ISAAC_ERROR_INVALID_SIZE = -2,
ISAAC_ERROR_INVALID_HEX = -3,
ISAAC_ERROR_OVERFLOW = -4,
ISAAC_ERROR_NOMEM = -5
} isaac_error_e;
/**
* @brief ISAAC CSPRNG state structure
* @note Cache-aligned for optimal performance (OPT-041)
*/
typedef struct isaac_state {
uint32_t mem[ISAAC_STATE_SIZE] CACHE_ALIGN; /**< [in,out] Internal state */
uint32_t rnd[ISAAC_RESULT_SIZE] CACHE_ALIGN; /**< [out] Results array */
uint32_t cnt; /**< [in,out] Result counter */
uint32_t acc; /**< [in,out] Accumulator */
uint32_t bux; /**< [in,out] Secondary acc */
uint32_t ctr; /**< [in,out] Counter */
/* FUTURE USE: B-tree Integration Fields */
/* uint64_t total_bytes_generated; */ /**< Statistics tracking */
/* uint32_t reseed_counter; */ /**< Auto-reseed tracking */
/* uint8_t btree_node_id[BTREE_KEY_SIZE]; */ /**< Node-specific seed */
} isaac_state_t;
/**
* @brief Performance measurement structure
*/
#ifdef __x86_64__
typedef struct perf_counter {
uint64_t start_cycles;
uint64_t total_cycles;
uint32_t call_count;
uint32_t padding;
} perf_counter_t;
#else
typedef struct perf_counter {
uint64_t start_ns;
uint64_t total_ns;
uint32_t call_count;
uint32_t padding;
} perf_counter_t;
#endif
/* FUTURE USE: B-tree Cryptographic Context
typedef struct btree_crypto {
isaac_state_t key_gen; // Key generation
isaac_state_t encrypt; // Data encryption
isaac_state_t mac_gen; // MAC generation
uint8_t master_key[32]; // Master key
uint8_t current_nonce[16]; // Current nonce
} btree_crypto_t;
*/
/* ============================================================================
* GLOBAL STATE (OPT-000: ID-003)
* ============================================================================
*/
/* OPT-033: Global State Management */
static isaac_state_t g_isaac CACHE_ALIGN = {0};
/* OPT-012: Pre-allocated buffers */
static char g_hex_buffer[HEX_BUFFER_SIZE] CACHE_ALIGN = {0};
static char g_message_buffer[MAX_MESSAGE_SIZE] CACHE_ALIGN = {0};
/* Performance counters */
static perf_counter_t g_gen_counter = {0};
static perf_counter_t g_encrypt_counter = {0};
static perf_counter_t g_decrypt_counter = {0};
/* OPT-003: Lookup table for hex conversion */
static const char HEX_CHARS[16] = "0123456789ABCDEF";
/* Hex decode table (-1 for invalid) */
static const int8_t HEX_DECODE[256] = {
['0'] = 0, ['1'] = 1, ['2'] = 2, ['3'] = 3, ['4'] = 4, ['5'] = 5,
['6'] = 6, ['7'] = 7, ['8'] = 8, ['9'] = 9, ['A'] = 10, ['B'] = 11,
['C'] = 12, ['D'] = 13, ['E'] = 14, ['F'] = 15, ['a'] = 10, ['b'] = 11,
['c'] = 12, ['d'] = 13, ['e'] = 14, ['f'] = 15};
/* ============================================================================
* PERFORMANCE TIMING (PERF-002)
* ============================================================================
*/
#ifdef __x86_64__
/**
* @brief Read x86-64 timestamp counter
* @return Current CPU cycle count
*/
static FORCE_INLINE uint64_t rdtsc(void)
{
uint32_t low = 0U;
uint32_t high = 0U;
__asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
return ((uint64_t)high << 32U) | (uint64_t)low;
}
static FORCE_INLINE void perf_start(perf_counter_t *RESTRICT ctr)
{
ctr->start_cycles = rdtsc();
}
static FORCE_INLINE uint64_t perf_end(perf_counter_t *RESTRICT ctr)
{
const uint64_t end_cycles = rdtsc();
const uint64_t elapsed = end_cycles - ctr->start_cycles;
ctr->total_cycles += elapsed;
ctr->call_count++;
return elapsed;
}
#else
static FORCE_INLINE void perf_start(perf_counter_t *RESTRICT ctr)
{
struct timespec tms = {0};
(void)clock_gettime(CLOCK_MONOTONIC, &tms);
ctr->start_ns =
(uint64_t)tms.tv_sec * 1000000000ULL + (uint64_t)tms.tv_nsec;
}
static FORCE_INLINE uint64_t perf_end(perf_counter_t *RESTRICT ctr)
{
struct timespec tms = {0};
(void)clock_gettime(CLOCK_MONOTONIC, &tms);
const uint64_t end_ns =
(uint64_t)tms.tv_sec * 1000000000ULL + (uint64_t)tms.tv_nsec;
const uint64_t elapsed = end_ns - ctr->start_ns;
ctr->total_ns += elapsed;
ctr->call_count++;
return elapsed;
}
#endif
/* ============================================================================
* CORE ISAAC ALGORITHM (OPT-049)
* ============================================================================
*/
/**
* @brief Generate next batch of random values
* @param[in,out] ctx ISAAC state context
* @note Preserves exact ISAAC algorithm behavior
*/
static FORCE_INLINE void isaac_generate(isaac_state_t *RESTRICT ctx)
{
perf_start(&g_gen_counter);
register uint32_t *RESTRICT mem = ctx->mem;
register uint32_t *RESTRICT rnd = ctx->rnd;
register uint32_t acc = ctx->acc;
register uint32_t bux = ctx->bux + (++ctx->ctr);
register uint32_t tmp = 0U;
register uint32_t out = 0U;
/* Conservative prefetching (OPT-048) */
PREFETCH_READ(&mem[16]);
PREFETCH_WRITE(&rnd[16]);
/* First half: 4-way unrolled (0-127) */
for (uint32_t idx = 0U; idx < 128U; idx += ISAAC_UNROLL_FACTOR) {
/* Pattern 0: idx % 4 == 0 */
tmp = mem[idx];
acc = (acc ^ (acc << ISAAC_SHIFT1)) + mem[idx + 128U];
mem[idx] = out =
mem[(tmp >> ISAAC_INDEX_SHIFT) & ISAAC_MASK] + acc + bux;
rnd[idx] = bux = mem[(out >> ISAAC_RESULT_SHIFT) & ISAAC_MASK] + tmp;
/* Pattern 1: idx % 4 == 1 */
tmp = mem[idx + 1U];
acc = (acc ^ (acc >> ISAAC_SHIFT2)) + mem[idx + 129U];
mem[idx + 1U] = out =
mem[(tmp >> ISAAC_INDEX_SHIFT) & ISAAC_MASK] + acc + bux;
rnd[idx + 1U] = bux =
mem[(out >> ISAAC_RESULT_SHIFT) & ISAAC_MASK] + tmp;
/* Pattern 2: idx % 4 == 2 */
tmp = mem[idx + 2U];
acc = (acc ^ (acc << ISAAC_SHIFT3)) + mem[idx + 130U];
mem[idx + 2U] = out =
mem[(tmp >> ISAAC_INDEX_SHIFT) & ISAAC_MASK] + acc + bux;
rnd[idx + 2U] = bux =
mem[(out >> ISAAC_RESULT_SHIFT) & ISAAC_MASK] + tmp;
/* Pattern 3: idx % 4 == 3 */
tmp = mem[idx + 3U];
acc = (acc ^ (acc >> ISAAC_SHIFT4)) + mem[idx + 131U];
mem[idx + 3U] = out =
mem[(tmp >> ISAAC_INDEX_SHIFT) & ISAAC_MASK] + acc + bux;
rnd[idx + 3U] = bux =
mem[(out >> ISAAC_RESULT_SHIFT) & ISAAC_MASK] + tmp;
/* Prefetch next cache lines */
if ((idx & (ISAAC_PREFETCH_DIST - 1U)) == 0U) {
PREFETCH_READ(&mem[idx + ISAAC_PREFETCH_DIST]);
PREFETCH_WRITE(&rnd[idx + ISAAC_PREFETCH_DIST]);
}
}
/* Second half: 4-way unrolled (128-255) */
for (uint32_t idx = 128U; idx < 256U; idx += ISAAC_UNROLL_FACTOR) {
tmp = mem[idx];
acc = (acc ^ (acc << ISAAC_SHIFT1)) + mem[idx - 128U];
mem[idx] = out =
mem[(tmp >> ISAAC_INDEX_SHIFT) & ISAAC_MASK] + acc + bux;
rnd[idx] = bux = mem[(out >> ISAAC_RESULT_SHIFT) & ISAAC_MASK] + tmp;
tmp = mem[idx + 1U];
acc = (acc ^ (acc >> ISAAC_SHIFT2)) + mem[idx - 127U];
mem[idx + 1U] = out =
mem[(tmp >> ISAAC_INDEX_SHIFT) & ISAAC_MASK] + acc + bux;
rnd[idx + 1U] = bux =
mem[(out >> ISAAC_RESULT_SHIFT) & ISAAC_MASK] + tmp;
tmp = mem[idx + 2U];
acc = (acc ^ (acc << ISAAC_SHIFT3)) + mem[idx - 126U];
mem[idx + 2U] = out =
mem[(tmp >> ISAAC_INDEX_SHIFT) & ISAAC_MASK] + acc + bux;
rnd[idx + 2U] = bux =
mem[(out >> ISAAC_RESULT_SHIFT) & ISAAC_MASK] + tmp;
tmp = mem[idx + 3U];
acc = (acc ^ (acc >> ISAAC_SHIFT4)) + mem[idx - 125U];
mem[idx + 3U] = out =
mem[(tmp >> ISAAC_INDEX_SHIFT) & ISAAC_MASK] + acc + bux;
rnd[idx + 3U] = bux =
mem[(out >> ISAAC_RESULT_SHIFT) & ISAAC_MASK] + tmp;
}
ctx->acc = acc;
ctx->bux = bux;
ctx->cnt = 0U;
perf_end(&g_gen_counter);
}
/**
* @brief Get next random 32-bit value
* @param[in,out] ctx ISAAC state context
* @return Random 32-bit value
*/
static FORCE_INLINE uint32_t isaac_random(isaac_state_t *RESTRICT ctx)
{
if (UNLIKELY(ctx->cnt >= ISAAC_RESULT_SIZE)) {
isaac_generate(ctx);
}
return ctx->rnd[ctx->cnt++];
}
/**
* @brief Get random ASCII printable character
* @param[in,out] ctx ISAAC state context
* @return Random printable ASCII character
*/
static FORCE_INLINE char isaac_random_ascii(isaac_state_t *RESTRICT ctx)
{
return (char)((isaac_random(ctx) % ISAAC_ASCII_RANGE) + ISAAC_ASCII_START);
}
/* ============================================================================
* INITIALIZATION (OPT-000: FD-004 - Reduced Complexity)
* ============================================================================
*/
/**
* @brief Mixing macro with proper parenthesization (OPT-000: SA-005)
*/
#define MIX(a, b, c, d, e, f, g, h) \
do { \
(a) ^= (b) << 11U; \
(d) += (a); \
(b) += (c); \
(b) ^= (c) >> 2U; \
(e) += (b); \
(c) += (d); \
(c) ^= (d) << 8U; \
(f) += (c); \
(d) += (e); \
(d) ^= (e) >> 16U; \
(g) += (d); \
(e) += (f); \
(e) ^= (f) << 10U; \
(h) += (e); \
(f) += (g); \
(f) ^= (g) >> 4U; \
(a) += (f); \
(g) += (h); \
(g) ^= (h) << 8U; \
(b) += (g); \
(h) += (a); \
(h) ^= (a) >> 9U; \
(c) += (h); \
(a) += (b); \
} while (0)
/**
* @brief Initialize mix array with golden ratio
* @param[out] mix Array to initialize
*/
static void isaac_init_mix(uint32_t mix[ISAAC_MIX_UNROLL])
{
for (uint32_t idx = 0U; idx < ISAAC_MIX_UNROLL; idx++) {
mix[idx] = ISAAC_GOLDEN_RATIO;
}
/* Initial scramble */
for (uint32_t round = 0U; round < 4U; round++) {
MIX(mix[0], mix[1], mix[2], mix[3], mix[4], mix[5], mix[6], mix[7]);
}
}
/**
* @brief Mix seed into state memory
* @param[in,out] ctx ISAAC context
* @param[in,out] mix Working mix array
*/
static void isaac_mix_seed(isaac_state_t *RESTRICT ctx,
uint32_t mix[ISAAC_MIX_UNROLL])
{
/* First pass: mix seed into state */
for (uint32_t idx = 0U; idx < ISAAC_STATE_SIZE; idx += ISAAC_MIX_UNROLL) {
for (uint32_t jdx = 0U; jdx < ISAAC_MIX_UNROLL; jdx++) {
mix[jdx] += ctx->rnd[idx + jdx];
}
MIX(mix[0], mix[1], mix[2], mix[3], mix[4], mix[5], mix[6], mix[7]);
for (uint32_t jdx = 0U; jdx < ISAAC_MIX_UNROLL; jdx++) {
ctx->mem[idx + jdx] = mix[jdx];
}
}
/* Second pass: mix state into itself */
for (uint32_t idx = 0U; idx < ISAAC_STATE_SIZE; idx += ISAAC_MIX_UNROLL) {
for (uint32_t jdx = 0U; jdx < ISAAC_MIX_UNROLL; jdx++) {
mix[jdx] += ctx->mem[idx + jdx];
}
MIX(mix[0], mix[1], mix[2], mix[3], mix[4], mix[5], mix[6], mix[7]);
for (uint32_t jdx = 0U; jdx < ISAAC_MIX_UNROLL; jdx++) {
ctx->mem[idx + jdx] = mix[jdx];
}
}
}
/**
* @brief Mix without seed (scramble only)
* @param[in,out] ctx ISAAC context
* @param[in,out] mix Working mix array
*/
static void isaac_mix_noseed(isaac_state_t *RESTRICT ctx,
uint32_t mix[ISAAC_MIX_UNROLL])
{
for (uint32_t idx = 0U; idx < ISAAC_STATE_SIZE; idx += ISAAC_MIX_UNROLL) {
MIX(mix[0], mix[1], mix[2], mix[3], mix[4], mix[5], mix[6], mix[7]);
for (uint32_t jdx = 0U; jdx < ISAAC_MIX_UNROLL; jdx++) {
ctx->mem[idx + jdx] = mix[jdx];
}
}
}
/**
* @brief Initialize ISAAC with optional seed
* @param[in,out] ctx ISAAC state to initialize
* @param[in] use_seed Whether to use seed data from rnd array
*/
static void isaac_init(isaac_state_t *RESTRICT ctx, bool use_seed)
{
uint32_t mix[ISAAC_MIX_UNROLL] = {0};
isaac_init_mix(mix);
if (use_seed) {
isaac_mix_seed(ctx, mix);
} else {
isaac_mix_noseed(ctx, mix);
}
/* Initialize counters */
ctx->acc = 0U;
ctx->bux = 0U;
ctx->ctr = 0U;
ctx->cnt = ISAAC_RESULT_SIZE;
/* Generate first batch */
isaac_generate(ctx);
}
/**
* @brief Seed ISAAC with string key
* @param[out] ctx ISAAC state to seed
* @param[in] key Seed string
* @param[in] len Length of seed (0 for strlen)
* @return ISAAC_SUCCESS or error code
*/
static isaac_error_e isaac_seed(isaac_state_t *RESTRICT ctx,
const char *RESTRICT key, size_t len)
{
if (!ctx || !key) {
return ISAAC_ERROR_NULL_PARAM;
}
const size_t key_len = (len > 0U) ? len : strlen(key);
/* Clear state arrays */
memset(ctx->mem, 0, sizeof(ctx->mem));
memset(ctx->rnd, 0, sizeof(ctx->rnd));
/* Inject key into seed array */
for (size_t idx = 0U; idx < ISAAC_STATE_SIZE; idx++) {
if (idx < key_len) {
ctx->rnd[idx] = (uint32_t)(unsigned char)key[idx];
} else {
ctx->rnd[idx] = 0U;
}
}
isaac_init(ctx, true);
return ISAAC_SUCCESS;
}
/* ============================================================================
* SECURE OPERATIONS
* ============================================================================
*/
/**
* @brief Secure memory wipe (OPT-000: SC-001)
* @param[out] ptr Memory to wipe
* @param[in] len Number of bytes
*/
static void secure_wipe(void *ptr, size_t len)
{
volatile uint8_t *vptr = (volatile uint8_t *)ptr;
for (size_t idx = 0U; idx < len; idx++) {
vptr[idx] = 0U;
}
}
/**
* @brief Clone ISAAC state
* @param[out] dst Destination state
* @param[in] src Source state
* @return ISAAC_SUCCESS or error code
*/
static isaac_error_e isaac_clone(isaac_state_t *RESTRICT dst,
const isaac_state_t *RESTRICT src)
{
if (!dst || !src) {
return ISAAC_ERROR_NULL_PARAM;
}
memcpy(dst, src, sizeof(isaac_state_t));
return ISAAC_SUCCESS;
}
/* ============================================================================
* HEX CONVERSION (OPT-003)
* ============================================================================
*/
/**
* @brief Convert byte to hex characters
* @param[in] byte Byte to convert
* @param[out] hex Output buffer (min 2 chars)
* @return true on success
*/
static FORCE_INLINE bool byte_to_hex(uint8_t byte, char *RESTRICT hex)
{
hex[0] = HEX_CHARS[byte >> 4U];
hex[1] = HEX_CHARS[byte & 0x0FU];
return true;
}
/**
* @brief Convert hex characters to byte (optimized)
* @param[in] hex Input hex chars (2 chars)
* @param[out] byte Output byte
* @return true on success
*/
static FORCE_INLINE bool hex_to_byte(const char *RESTRICT hex,
uint8_t *RESTRICT byte)
{
const unsigned char h0 = (unsigned char)hex[0];
const unsigned char h1 = (unsigned char)hex[1];
const int8_t val0 = HEX_DECODE[h0];
const int8_t val1 = HEX_DECODE[h1];
if (val0 < 0 || val1 < 0) {
return false;
}
*byte = (uint8_t)((val0 << 4U) | val1);
return true;
}
/* ============================================================================
* CIPHER OPERATIONS
* ============================================================================
*/
/**
* @brief Caesar cipher for MOD95
* @param[in] chr Character to shift
* @param[in] shift Shift amount
* @param[in] encrypt true=encrypt, false=decrypt
* @return Shifted character
*/
static FORCE_INLINE char caesar_shift(char chr, char shift, bool encrypt)
{
uint32_t pos = (uint32_t)((unsigned char)chr - ISAAC_ASCII_START);
uint32_t shift_amount = (uint32_t)(unsigned char)shift;
if (!encrypt) {
shift_amount = ISAAC_ASCII_RANGE - shift_amount;
}
pos = (pos + shift_amount) % ISAAC_ASCII_RANGE;
return (char)(ISAAC_ASCII_START + pos);
}
/**
* @brief XOR cipher encryption
* @param[in,out] ctx ISAAC state
* @param[out] output Hex output buffer
* @param[in] input Input plaintext
* @param[in] length Input length
* @return ISAAC_SUCCESS or error code
*/
static isaac_error_e isaac_xor_encrypt(isaac_state_t *RESTRICT ctx,
char *RESTRICT output,
const char *RESTRICT input,
size_t length)
{
if (!ctx || !output || !input) {
return ISAAC_ERROR_NULL_PARAM;
}
perf_start(&g_encrypt_counter);
for (size_t idx = 0U; idx < length; idx++) {
const char key = isaac_random_ascii(ctx);
const uint8_t res = (uint8_t)input[idx] ^ (uint8_t)key;
(void)byte_to_hex(res, &output[idx * HEX_CHARS_PER_BYTE]);
}
output[length * HEX_CHARS_PER_BYTE] = '\0';
perf_end(&g_encrypt_counter);
return ISAAC_SUCCESS;
}
/**
* @brief XOR cipher decryption
* @param[in,out] ctx ISAAC state
* @param[out] output Plaintext output
* @param[in] input Hex input
* @param[in] length Output length
* @return ISAAC_SUCCESS or error code
*/
static isaac_error_e isaac_xor_decrypt(isaac_state_t *RESTRICT ctx,
char *RESTRICT output,
const char *RESTRICT input,
size_t length)
{
if (!ctx || !output || !input) {
return ISAAC_ERROR_NULL_PARAM;
}
perf_start(&g_decrypt_counter);
for (size_t idx = 0U; idx < length; idx++) {
const char key = isaac_random_ascii(ctx);
uint8_t enc = 0U;
if (!hex_to_byte(&input[idx * HEX_CHARS_PER_BYTE], &enc)) {
perf_end(&g_decrypt_counter);
return ISAAC_ERROR_INVALID_HEX;
}
output[idx] = (char)(enc ^ (uint8_t)key);
}
output[length] = '\0';
perf_end(&g_decrypt_counter);
return ISAAC_SUCCESS;
}
/**
* @brief MOD95 cipher encryption
* @param[in,out] ctx ISAAC state
* @param[out] output Hex output buffer
* @param[in] input Input plaintext
* @param[in] length Input length
* @return ISAAC_SUCCESS or error code
*/
static isaac_error_e isaac_mod_encrypt(isaac_state_t *RESTRICT ctx,
char *RESTRICT output,
const char *RESTRICT input,
size_t length)
{
if (!ctx || !output || !input) {
return ISAAC_ERROR_NULL_PARAM;
}
for (size_t idx = 0U; idx < length; idx++) {
const char shift = isaac_random_ascii(ctx);
const char enc = caesar_shift(input[idx], shift, true);
(void)byte_to_hex((uint8_t)enc, &output[idx * HEX_CHARS_PER_BYTE]);
}
output[length * HEX_CHARS_PER_BYTE] = '\0';
return ISAAC_SUCCESS;
}
/**
* @brief MOD95 cipher decryption
* @param[in,out] ctx ISAAC state
* @param[out] output Plaintext output
* @param[in] input Hex input
* @param[in] length Output length
* @return ISAAC_SUCCESS or error code
*/
static isaac_error_e isaac_mod_decrypt(isaac_state_t *RESTRICT ctx,
char *RESTRICT output,
const char *RESTRICT input,
size_t length)
{
if (!ctx || !output || !input) {
return ISAAC_ERROR_NULL_PARAM;
}
for (size_t idx = 0U; idx < length; idx++) {
const char shift = isaac_random_ascii(ctx);
uint8_t enc = 0U;
if (!hex_to_byte(&input[idx * HEX_CHARS_PER_BYTE], &enc)) {
return ISAAC_ERROR_INVALID_HEX;
}
output[idx] = caesar_shift((char)enc, shift, false);
}
output[length] = '\0';
return ISAAC_SUCCESS;
}
/* ============================================================================
* FUTURE USE: B-TREE DATABASE INTEGRATION
* ============================================================================
*/
/* FUTURE USE: Generate unique B-tree node ID
static isaac_error_e isaac_btree_node_id(isaac_state_t* RESTRICT ctx,
uint8_t* RESTRICT node_id,
size_t id_size) {
if (!ctx || !node_id || id_size == 0U) {
return ISAAC_ERROR_NULL_PARAM;
}
for (size_t idx = 0U; idx < id_size; idx += UINT32_BYTES) {
const uint32_t rnd = isaac_random(ctx);
const size_t chunk = (id_size - idx < UINT32_BYTES) ?
(id_size - idx) : UINT32_BYTES;
memcpy(&node_id[idx], &rnd, chunk);
}
return ISAAC_SUCCESS;
}
*/
/* FUTURE USE: Stream cipher for B-tree pages
static isaac_error_e isaac_btree_encrypt_page(isaac_state_t* RESTRICT ctx,
uint8_t* RESTRICT page,
size_t page_size) {
if (!ctx || !page || page_size == 0U) {
return ISAAC_ERROR_NULL_PARAM;
}
for (size_t idx = 0U; idx < page_size; idx += UINT32_BYTES) {
const uint32_t key = isaac_random(ctx);
const size_t chunk = (page_size - idx < UINT32_BYTES) ?
(page_size - idx) : UINT32_BYTES;
for (size_t jdx = 0U; jdx < chunk; jdx++) {
page[idx + jdx] ^= (uint8_t)(key >> (jdx * BITS_PER_BYTE));
}
}
return ISAAC_SUCCESS;
}
*/
/* FUTURE USE: Generate MAC for B-tree node
static isaac_error_e isaac_btree_mac(isaac_state_t* RESTRICT ctx,
const uint8_t* RESTRICT data,
size_t data_size,
uint8_t* RESTRICT mac,
size_t mac_size) {
if (!ctx || !data || !mac || mac_size < 16U) {
return ISAAC_ERROR_NULL_PARAM;
}
uint32_t hash[4] = {0};
for (size_t idx = 0U; idx < data_size; idx++) {
const uint32_t key = isaac_random(ctx);
hash[0] ^= data[idx] * key;
hash[1] += data[idx] + key;
hash[2] = ((hash[2] << 1U) | (hash[2] >> 31U)) ^ key;
hash[3] = ((hash[3] >> 1U) | (hash[3] << 31U)) + key;
}
// Mix final hash
for (uint32_t round = 0U; round < 4U; round++) {
hash[0] += isaac_random(ctx);
hash[1] ^= hash[0];
hash[2] += hash[1];
hash[3] ^= hash[2];
}
memcpy(mac, hash, (mac_size < 16U) ? mac_size : 16U);
return ISAAC_SUCCESS;
}
*/
/* FUTURE USE: Key derivation for B-tree levels
static isaac_error_e isaac_btree_derive_key(isaac_state_t* RESTRICT ctx,
const uint8_t* RESTRICT parent_key,
size_t parent_size,
uint32_t child_index,
uint8_t* RESTRICT child_key,
size_t child_size) {
if (!ctx || !parent_key || !child_key) {
return ISAAC_ERROR_NULL_PARAM;
}
// Reseed with parent key and child index
isaac_state_t temp = {0};
memcpy(temp.rnd, parent_key,
(parent_size < sizeof(temp.rnd)) ? parent_size : sizeof(temp.rnd));
temp.rnd[0] ^= child_index;
isaac_init(&temp, true);
// Generate child key
for (size_t idx = 0U; idx < child_size; idx += UINT32_BYTES) {
const uint32_t key = isaac_random(&temp);
const size_t chunk = (child_size - idx < UINT32_BYTES) ?
(child_size - idx) : UINT32_BYTES;
memcpy(&child_key[idx], &key, chunk);
}
secure_wipe(&temp, sizeof(temp));
return ISAAC_SUCCESS;
}
*/
/* ============================================================================
* BENCHMARKING
* ============================================================================
*/
/**
* @brief Benchmark ISAAC performance
*/
static void benchmark_performance(void)
{
const uint32_t gen_iterations = 1000000U;
const uint32_t enc_iterations = 1000U;
const char *test_msg =
"Performance test message for encryption benchmarking";
const size_t msg_len = strlen(test_msg);
/* Reset counters */
g_gen_counter = (perf_counter_t){0};
g_encrypt_counter = (perf_counter_t){0};
g_decrypt_counter = (perf_counter_t){0};
/* Benchmark generation */
for (uint32_t idx = 0U; idx < gen_iterations; idx++) {
(void)isaac_random(&g_isaac);
}
/* Benchmark encryption */
for (uint32_t idx = 0U; idx < enc_iterations; idx++) {
(void)isaac_seed(&g_isaac, "benchmark_key", 0U);
(void)isaac_xor_encrypt(&g_isaac, g_hex_buffer, test_msg, msg_len);
}
printf("=== ISAAC Performance Benchmarks ===\n");
#ifdef __x86_64__
if (g_gen_counter.call_count > 0U) {
printf("Random generation: %lu cycles/call\n",
g_gen_counter.total_cycles / g_gen_counter.call_count);
}
if (g_encrypt_counter.call_count > 0U) {
printf("XOR encryption: %lu cycles/byte\n",
g_encrypt_counter.total_cycles / (enc_iterations * msg_len));
}
#else
if (g_gen_counter.call_count > 0U) {
printf("Random generation: %lu ns/call\n",
g_gen_counter.total_ns / g_gen_counter.call_count);
}
if (g_encrypt_counter.call_count > 0U) {
printf("XOR encryption: %lu ns/byte\n",
g_encrypt_counter.total_ns / (enc_iterations * msg_len));
}
#endif
}
/* ============================================================================
* UTILITY FUNCTIONS
* ============================================================================
*/
/**
* @brief Print version information
*/
static void print_version(void)
{
printf("ISAAC CSPRNG Implementation v%s\n", ISAAC_VERSION_STRING);
printf("================================================\n");
printf("Based on Bob Jenkins' ISAAC (1993) - Public Domain\n");
printf("Coding standards: OPT-000 v2.0 compliant\n\n");
}
/**
* @brief Get error string
* @param[in] err Error code
* @return Error description string
*/
static const char *isaac_error_string(isaac_error_e err)
{
switch (err) {
case ISAAC_SUCCESS:
return "Success";
case ISAAC_ERROR_NULL_PARAM:
return "Null parameter";
case ISAAC_ERROR_INVALID_SIZE:
return "Invalid size";
case ISAAC_ERROR_INVALID_HEX:
return "Invalid hex string";
case ISAAC_ERROR_OVERFLOW:
return "Integer overflow";
case ISAAC_ERROR_NOMEM:
return "Out of memory";
default:
return "Unknown error";
}
}
/* ============================================================================
* MAIN ENTRY POINT
* ============================================================================
*/
/**
* @brief Program entry with test vectors
* @return EXIT_SUCCESS or EXIT_FAILURE
*/
int main(void)
{
/* Stack variables (largest to smallest) */
char hex_buffer[HEX_BUFFER_SIZE] = {0};
char msg_buffer[MAX_MESSAGE_SIZE] = {0};
isaac_state_t test_state = {0};
isaac_error_e err = ISAAC_SUCCESS;
/* Test configuration */
const char *const message = "a Top Secret secret";
const char *const key = "this is my secret key";
const size_t msg_len = strlen(message);
/* Expected test vectors */
const char *const expected_xor = "1C0636190B1260233B35125F1E1D0E2F4C5422";
/* Validation */
if (msg_len >= MAX_MESSAGE_SIZE) {
fprintf(stderr, "Error: Message too large (%zu >= %u)\n", msg_len,
MAX_MESSAGE_SIZE);
return EXIT_FAILURE;
}
print_version();
printf("Test Configuration:\n");
printf(" Message: %s\n", message);
printf(" Key : %s\n\n", key);
/* XOR Cipher Test */
printf("=== XOR (Vernam) Cipher ===\n");
err = isaac_seed(&test_state, key, 0U);
if (err != ISAAC_SUCCESS) {
fprintf(stderr, "Seed failed: %s\n", isaac_error_string(err));
return EXIT_FAILURE;
}
err = isaac_xor_encrypt(&test_state, hex_buffer, message, msg_len);
if (err != ISAAC_SUCCESS) {
fprintf(stderr, "XOR encryption failed: %s\n", isaac_error_string(err));
return EXIT_FAILURE;
}
printf("Encrypted: %s\n", hex_buffer);
err = isaac_seed(&test_state, key, 0U);
if (err != ISAAC_SUCCESS) {
fprintf(stderr, "Reseed failed: %s\n", isaac_error_string(err));
return EXIT_FAILURE;
}
err = isaac_xor_decrypt(&test_state, msg_buffer, hex_buffer, msg_len);
if (err != ISAAC_SUCCESS) {
fprintf(stderr, "XOR decryption failed: %s\n", isaac_error_string(err));
return EXIT_FAILURE;
}
printf("Decrypted: %s\n\n", msg_buffer);
/* MOD95 Cipher Test */
printf("=== MOD95 (Vigenère) Cipher ===\n");
err = isaac_seed(&test_state, key, 0U);
if (err != ISAAC_SUCCESS) {
fprintf(stderr, "Seed failed: %s\n", isaac_error_string(err));
return EXIT_FAILURE;
}
err = isaac_mod_encrypt(&test_state, hex_buffer, message, msg_len);
if (err != ISAAC_SUCCESS) {
fprintf(stderr, "MOD encryption failed: %s\n", isaac_error_string(err));
return EXIT_FAILURE;
}
printf("Encrypted: %s\n", hex_buffer);
err = isaac_seed(&test_state, key, 0U);
if (err != ISAAC_SUCCESS) {
fprintf(stderr, "Reseed failed: %s\n", isaac_error_string(err));
return EXIT_FAILURE;
}
err = isaac_mod_decrypt(&test_state, msg_buffer, hex_buffer, msg_len);
if (err != ISAAC_SUCCESS) {
fprintf(stderr, "MOD decryption failed: %s\n", isaac_error_string(err));
return EXIT_FAILURE;
}
printf("Decrypted: %s\n\n", msg_buffer);
/* Verification */
printf("=== Test Vector Verification ===\n");
(void)isaac_seed(&test_state, key, 0U);
(void)isaac_xor_encrypt(&test_state, hex_buffer, message, msg_len);
const bool xor_match = (strcmp(hex_buffer, expected_xor) == 0);
const bool mod_match = (strcmp(msg_buffer, message) == 0);
printf("XOR cipher match: %s\n", xor_match ? "✓ PASS" : "✗ FAIL");
printf("MOD cipher match: %s\n", mod_match ? "✓ PASS" : "✗ FAIL");
printf("\n");
/* Performance benchmarks */
benchmark_performance();
/* Secure cleanup */
secure_wipe(&test_state, sizeof(test_state));
secure_wipe(hex_buffer, sizeof(hex_buffer));
secure_wipe(msg_buffer, sizeof(msg_buffer));
return (xor_match && mod_match) ? EXIT_SUCCESS : EXIT_FAILURE;
}
@opsec-ee
Copy link
Author

opsec-ee commented Sep 7, 2025

$ gcc -std=c11 -O3 -march=native -flto -funroll-loops -ffast-math -DNDEBUG isaac_optimized.c -o isaac_fast

$ ./isaac_fast

ISAAC CSPRNG High-Performance Implementation v1.1.0
================================================
Based on Bob Jenkins' ISAAC algorithm (1993)
License: Public Domain

Test Vector:
Message: a Top Secret secret
Key    : this is my secret key

=== XOR (Vernam) Cipher ===
XOR    : 1C0636190B1260233B35125F1E1D0E2F4C5422
XOR dcr: a Top Secret secret

=== MOD 95 (Vigenère) Cipher ===
MOD    : 204657272D52274C5C5A7D405E23715051376B
MOD dcr: a Top Secret secret

=== Verification Results ===
XOR cipher matches reference: ✓ PASS
MOD cipher functionally correct: ✓ PASS

=== ISAAC Benchmarks ===
Random generation: 2903 cycles/call
Encryption: 11 cycles/byte

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment