3 August 2026

A (hopefully not horribly unsafe) CSPRNG based on 3-round Feistel networks with the nonlinear kernel function of scalar multiplication map in GF(256) and a kernel schedule based on the bespoke kernel and FY-shuffle, as seen in the 4th iteration kcrypt.

#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define Fi(n,a...) for (int i = 0; i < n; i++) { a; }
typedef uint8_t gf;  typedef struct { gf k1[32], k2[64]; } bk;
static gf LOG[256], EXP[510];
static void gentab(void) {
  int b = 1;  Fi(255, LOG[EXP[i] = EXP[i + 255] = b] = i,
                      b = b * 2 ^ b / 128 * 285)
}
static void block(gf out[64], gf in[64], uint32_t iv, bk * key) {
  gf rk[3][32], id[32], tmp[32];  gf * s = memcpy(id, key->k1, 32);
  Fi(4, id[i] ^= iv >> i * 8)
  for (int q = 0; q < 3; s = rk[q++])
    Fi(32, rk[q][i] = EXP[
      (s[i + 1 & 31] ^ key->k2[i + q * 17 & 63] ^ q)
      + LOG[s[i] ^ key->k2[i + 32 + q * 17 & 63]]])
  gf * l = memcpy(out, in, 64), * r = out + 32,
     * next = tmp, * old;
  for (int x = 0, j, t; x < 3;
       old = l, l = r, r = next, next = old, x++) {
    gf p[32];  Fi(32, p[i] = i)
    for (int i = 32; --i;)
      t = p[i], p[i] = p[j = key->k2[i + x * 21 & 63] % -~i], p[j] = t;
    Fi(32, next[i] = l[i] ^ EXP[rk[x][i] + LOG[
      r[p[i]] ^ r[p[i + 1 & 31]] ^ key->k2[i + 32 + x * 11 & 63]]])
  }
}
int main(void) {
  gentab();  struct { bk key; uint32_t iv; } seed;
  int random = open("/dev/urandom", O_RDONLY);
  if (random < 0) goto err;
  gf * p = (gf *) &seed;
  for (size_t left = sizeof seed; left;) {
    ssize_t n = read(random, p, left);
    if (n > 0) p += n, left -= (size_t)n;
    else if (n < 0 && errno == EINTR) continue;
    else goto err;
  }
  if (close(random) < 0)
    { err: perror("/dev/urandom");  return 1; }
  gf a[2][64] = {{[63] = 63}};
  for (int q = 0;; a[q ^= 1][63] ^= 63) {
    block(p = a[q ^ 1], a[q], seed.iv++, &seed.key);
    for (size_t left = 64; left;) {
      ssize_t n = write(STDOUT_FILENO, p, left);
      if (n > 0) p += n, left -= (size_t)n;
      else if (n < 0 && errno == EINTR) continue;
      else {
        if (errno == EPIPE) return 0;
        perror("stdout");  return 1;
      }
    }
  }
}
< back to journal