mirror of
https://strlcat.eu/rys/tfnoisegen.git
synced 2024-11-13 07:09:46 +01:00
Threefish cipher based raw PRN/noise generator.
This commit is contained in:
commit
76b80ded3a
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
_*
|
||||
*.swp
|
||||
*.o
|
||||
*.out
|
||||
*.key
|
||||
*.diff
|
||||
*.patch
|
||||
tags
|
||||
libtf.a
|
||||
tfrand
|
27
Makefile
Normal file
27
Makefile
Normal file
@ -0,0 +1,27 @@
|
||||
PROGS = tfrand
|
||||
PROGSRCS = $(PROGS:=.c)
|
||||
PROGOBJS = $(PROGSRCS:.c=.o)
|
||||
SRCS = $(filter-out $(PROGSRCS), $(wildcard *.c))
|
||||
HDRS = $(wildcard *.h)
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
|
||||
ifneq (,$(DEBUG))
|
||||
override CFLAGS+=-Wall -O0 -g
|
||||
else
|
||||
override CFLAGS+=-O3
|
||||
endif
|
||||
|
||||
default: $(OBJS) libtf.a tfrand
|
||||
all: $(OBJS) libtf.a $(PROGS)
|
||||
|
||||
%.o: %.c $(HDRS)
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
libtf.a: $(OBJS)
|
||||
$(AR) cru $@ $^
|
||||
|
||||
$(PROGS): %: %.o libtf.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
|
||||
|
||||
clean:
|
||||
rm -f libtf.a $(OBJS) $(PROGOBJS) $(SUPPOBJS) $(PROGS)
|
43
README
Normal file
43
README
Normal file
@ -0,0 +1,43 @@
|
||||
Threefish cipher based raw PRN/noise generator.
|
||||
|
||||
PURPOSE
|
||||
This PRNG is shortened, 32 bit integer version of Threefish-256 block cipher.
|
||||
It is technically a 128 bit block cipher with 256 bit key.
|
||||
|
||||
It's purpose is to generate fillers fast, for use in file or disk shredders.
|
||||
It is not meant to be secure, i.e. collision/bias free, but it is good at
|
||||
generating random noise equal to average output of /dev/urandom, yet much faster.
|
||||
|
||||
Typical performance on Athlon 5000+, x86-32 is about 170M/sec.
|
||||
|
||||
Included tfrand program generates random noise to stdout.
|
||||
|
||||
USAGE
|
||||
Build example:
|
||||
|
||||
make tfrand
|
||||
|
||||
Test it:
|
||||
|
||||
./tfrand >rng.out
|
||||
|
||||
Measure performance (install tfcrypt first):
|
||||
|
||||
./tfrand | tfcrypt -V.5 -P - /dev/null
|
||||
|
||||
Use libtf.a library in your code, see headers for function references:
|
||||
tfe.h: STREAM reference.
|
||||
tfprng.h: PRNG reference.
|
||||
|
||||
WARNING
|
||||
Do NOT use it as cipher! It's just a random block generator.
|
||||
You have been warned.
|
||||
|
||||
ORIGIN
|
||||
This code is derived from tfcipher library.
|
||||
|
||||
LICENSE
|
||||
Public domain -- free to reuse and adapt.
|
||||
|
||||
AUTHOR
|
||||
Andrey Rys <rys@lynxlynx.ru>, 17Mar2019.
|
50
tfcore.h
Normal file
50
tfcore.h
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef _THREEFISH_CIPHER_CORE_HEADER
|
||||
#define _THREEFISH_CIPHER_CORE_HEADER
|
||||
|
||||
#ifndef _THREEFISH_CIPHER_DEFINITIONS_HEADER
|
||||
#error Threefish definitions header is required! Include tfdef.h first.
|
||||
#endif
|
||||
|
||||
#define ROL(x, s, max) ((x << s) | (x >> (-s & (max-1))))
|
||||
#define ROR(x, s, max) ((x >> s) | (x << (-s & (max-1))))
|
||||
|
||||
#define KE_MIX(x, y, k1, k2, sl) \
|
||||
do { \
|
||||
x += k1; \
|
||||
y += x; \
|
||||
y += k2; \
|
||||
x = ROL(x, sl, TF_UNIT_BITS); \
|
||||
x ^= y; \
|
||||
} while (0)
|
||||
|
||||
#define BE_MIX(x, y, sl) \
|
||||
do { \
|
||||
x += y; \
|
||||
y = ROL(y, sl, TF_UNIT_BITS); \
|
||||
y ^= x; \
|
||||
} while (0)
|
||||
|
||||
#define KD_MIX(x, y, k1, k2, sr) \
|
||||
do { \
|
||||
x ^= y; \
|
||||
x = ROR(x, sr, TF_UNIT_BITS); \
|
||||
y -= x; \
|
||||
y -= k2; \
|
||||
x -= k1; \
|
||||
} while (0)
|
||||
|
||||
#define BD_MIX(x, y, sr) \
|
||||
do { \
|
||||
y ^= x; \
|
||||
y = ROR(y, sr, TF_UNIT_BITS); \
|
||||
x -= y; \
|
||||
} while (0)
|
||||
|
||||
enum tf_rotations {
|
||||
TFS_KS01 = 7, TFS_KS02 = 25, TFS_KS03 = 19, TFS_KS04 = 7,
|
||||
TFS_BS01 = 5, TFS_BS02 = 27, TFS_BS03 = 26, TFS_BS04 = 6,
|
||||
TFS_BS05 = 14, TFS_BS06 = 11, TFS_BS07 = 24, TFS_BS08 = 18,
|
||||
TFS_BS09 = 9, TFS_BS10 = 24, TFS_BS11 = 6, TFS_BS12 = 7,
|
||||
};
|
||||
|
||||
#endif
|
34
tfdef.h
Normal file
34
tfdef.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef _THREEFISH_CIPHER_DEFINITIONS_HEADER
|
||||
#define _THREEFISH_CIPHER_DEFINITIONS_HEADER
|
||||
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#endif
|
||||
|
||||
#ifndef _BSD_SOURCE
|
||||
#define _BSD_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define TF_UNIT_TYPE uint32_t
|
||||
|
||||
#define TF_NR_BLOCK_BITS 128
|
||||
#define TF_NR_KEY_BITS 256
|
||||
#define TF_NR_BLOCK_UNITS 4
|
||||
#define TF_NR_KEY_UNITS 8
|
||||
|
||||
#define TF_BYTE_TYPE uint8_t
|
||||
#define TF_SIZE_UNIT (sizeof(TF_UNIT_TYPE))
|
||||
#define TF_BLOCK_SIZE (TF_SIZE_UNIT * TF_NR_BLOCK_UNITS)
|
||||
#define TF_KEY_SIZE (TF_SIZE_UNIT * TF_NR_KEY_UNITS)
|
||||
|
||||
#define TF_TO_BITS(x) ((x) * 8)
|
||||
#define TF_FROM_BITS(x) ((x) / 8)
|
||||
#define TF_MAX_BITS TF_NR_BLOCK_BITS
|
||||
#define TF_UNIT_BITS (TF_SIZE_UNIT * 8)
|
||||
|
||||
void tf_encrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K);
|
||||
|
||||
#endif
|
57
tfe.c
Normal file
57
tfe.c
Normal file
@ -0,0 +1,57 @@
|
||||
#include <string.h>
|
||||
#include "tfdef.h"
|
||||
#include "tfe.h"
|
||||
|
||||
void tfe_init_iv(struct tfe_stream *tfe, const void *key, const void *iv)
|
||||
{
|
||||
memset(tfe, 0, sizeof(struct tfe_stream));
|
||||
memcpy(tfe->key, key, TF_KEY_SIZE);
|
||||
if (iv) memcpy(tfe->iv, iv, TF_BLOCK_SIZE);
|
||||
tfe->carry_bytes = 0;
|
||||
}
|
||||
|
||||
void tfe_init(struct tfe_stream *tfe, const void *key)
|
||||
{
|
||||
tfe_init_iv(tfe, key, NULL);
|
||||
}
|
||||
|
||||
void tfe_emit(void *dst, size_t szdst, struct tfe_stream *tfe)
|
||||
{
|
||||
TF_BYTE_TYPE *udst = dst;
|
||||
size_t sz = szdst;
|
||||
|
||||
if (!dst && szdst == 0) {
|
||||
memset(tfe, 0, sizeof(struct tfe_stream));
|
||||
return;
|
||||
}
|
||||
|
||||
if (tfe->carry_bytes > 0) {
|
||||
if (tfe->carry_bytes > szdst) {
|
||||
memcpy(udst, tfe->carry_block, szdst);
|
||||
memmove(tfe->carry_block, tfe->carry_block+szdst, tfe->carry_bytes-szdst);
|
||||
tfe->carry_bytes -= szdst;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(udst, tfe->carry_block, tfe->carry_bytes);
|
||||
udst += tfe->carry_bytes;
|
||||
sz -= tfe->carry_bytes;
|
||||
tfe->carry_bytes = 0;
|
||||
}
|
||||
|
||||
if (sz >= TF_BLOCK_SIZE) {
|
||||
do {
|
||||
tf_encrypt_rawblk(tfe->iv, tfe->iv, tfe->key);
|
||||
memcpy(udst, tfe->iv, TF_BLOCK_SIZE);
|
||||
udst += TF_BLOCK_SIZE;
|
||||
} while ((sz -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
if (sz) {
|
||||
tf_encrypt_rawblk(tfe->iv, tfe->iv, tfe->key);
|
||||
memcpy(udst, tfe->iv, sz);
|
||||
udst = (TF_BYTE_TYPE *)tfe->iv;
|
||||
tfe->carry_bytes = TF_BLOCK_SIZE-sz;
|
||||
memcpy(tfe->carry_block, udst+sz, tfe->carry_bytes);
|
||||
}
|
||||
}
|
17
tfe.h
Normal file
17
tfe.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef _TF_STREAM_CIPHER_DEFS
|
||||
#define _TF_STREAM_CIPHER_DEFS
|
||||
|
||||
#include "tfdef.h"
|
||||
|
||||
struct tfe_stream {
|
||||
TF_UNIT_TYPE key[TF_NR_KEY_UNITS];
|
||||
TF_UNIT_TYPE iv[TF_NR_BLOCK_UNITS];
|
||||
TF_BYTE_TYPE carry_block[TF_BLOCK_SIZE];
|
||||
size_t carry_bytes;
|
||||
};
|
||||
|
||||
void tfe_init(struct tfe_stream *tfe, const void *key);
|
||||
void tfe_init_iv(struct tfe_stream *tfe, const void *key, const void *iv);
|
||||
void tfe_emit(void *dst, size_t szdst, struct tfe_stream *tfe);
|
||||
|
||||
#endif
|
51
tfenc.c
Normal file
51
tfenc.c
Normal file
@ -0,0 +1,51 @@
|
||||
#include "tfdef.h"
|
||||
#include "tfcore.h"
|
||||
|
||||
#define PROCESS_BLOCKP(x,k1,k2,k3,k4,k5,k6) \
|
||||
do { \
|
||||
KE_MIX(Y, X, k1 + k2, k3, TFS_KS01); \
|
||||
KE_MIX(T, Z, k4 + x, k5 + k6, TFS_KS02); \
|
||||
\
|
||||
BE_MIX(X, T, TFS_BS01); BE_MIX(Z, Y, TFS_BS02); \
|
||||
BE_MIX(X, Y, TFS_BS03); BE_MIX(Z, T, TFS_BS04); \
|
||||
BE_MIX(X, T, TFS_BS05); BE_MIX(Z, Y, TFS_BS06); \
|
||||
} while (0)
|
||||
|
||||
#define PROCESS_BLOCKN(x,k1,k2,k3,k4,k5,k6) \
|
||||
do { \
|
||||
KE_MIX(Y, X, k1 + k2, k3, TFS_KS03); \
|
||||
KE_MIX(T, Z, k4 + x, k5 + k6, TFS_KS04); \
|
||||
\
|
||||
BE_MIX(X, T, TFS_BS07); BE_MIX(Z, Y, TFS_BS08); \
|
||||
BE_MIX(X, Y, TFS_BS09); BE_MIX(Z, T, TFS_BS10); \
|
||||
BE_MIX(X, T, TFS_BS11); BE_MIX(Z, Y, TFS_BS12); \
|
||||
} while (0)
|
||||
|
||||
void tf_encrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K)
|
||||
{
|
||||
TF_UNIT_TYPE X, Y, Z, T;
|
||||
TF_UNIT_TYPE K0, K1, K2, K3;
|
||||
TF_UNIT_TYPE K4, T0, T1, T2;
|
||||
|
||||
X = I[0]; Y = I[1]; Z = I[2]; T = I[3];
|
||||
|
||||
K0 = K[0]; K1 = K[1]; K2 = K[2]; K3 = K[3];
|
||||
K4 = K[4]; T0 = K[5]; T1 = K[6]; T2 = K[7];
|
||||
|
||||
PROCESS_BLOCKP( 1,K1,T0,K0,K3,K2,T1);
|
||||
PROCESS_BLOCKN( 2,K2,T1,K1,K4,K3,T2);
|
||||
PROCESS_BLOCKP( 3,K3,T2,K2,K0,K4,T0);
|
||||
PROCESS_BLOCKN( 4,K4,T0,K3,K1,K0,T1);
|
||||
|
||||
PROCESS_BLOCKP( 5,K0,T1,K4,K2,K1,T2);
|
||||
PROCESS_BLOCKN( 6,K1,T2,K0,K3,K2,T0);
|
||||
PROCESS_BLOCKP( 7,K2,T0,K1,K4,K3,T1);
|
||||
PROCESS_BLOCKN( 8,K3,T1,K2,K0,K4,T2);
|
||||
|
||||
PROCESS_BLOCKP( 9,K4,T2,K3,K1,K0,T0);
|
||||
PROCESS_BLOCKN(10,K0,T0,K4,K2,K1,T1);
|
||||
PROCESS_BLOCKP(11,K1,T1,K0,K3,K2,T2);
|
||||
PROCESS_BLOCKN(12,K2,T2,K1,K4,K3,T0);
|
||||
|
||||
O[0] = X + K3; O[1] = Y + K4 + T0; O[2] = Z + K0 + T1; O[3] = T + K1 + 18;
|
||||
}
|
94
tfprng.c
Normal file
94
tfprng.c
Normal file
@ -0,0 +1,94 @@
|
||||
#include <string.h>
|
||||
#include "tfe.h"
|
||||
#include "tfprng.h"
|
||||
|
||||
struct tf_prng_data {
|
||||
struct tfe_stream tfe;
|
||||
short init;
|
||||
};
|
||||
|
||||
struct tf_prng_data tf_prng_sdata;
|
||||
|
||||
size_t tf_prng_datasize(void)
|
||||
{
|
||||
return sizeof(struct tf_prng_data);
|
||||
}
|
||||
|
||||
void tf_prng_seedkey_r(void *sdata, const void *skey)
|
||||
{
|
||||
TF_UNIT_TYPE k[TF_NR_KEY_UNITS];
|
||||
struct tf_prng_data *rprng = sdata;
|
||||
|
||||
memset(rprng, 0, tf_prng_datasize());
|
||||
if (!skey) return;
|
||||
|
||||
memcpy(k, skey, TF_KEY_SIZE);
|
||||
tfe_init(&rprng->tfe, k);
|
||||
rprng->init = 1;
|
||||
|
||||
memset(k, 0, TF_KEY_SIZE);
|
||||
}
|
||||
|
||||
void tf_prng_seedkey(const void *skey)
|
||||
{
|
||||
tf_prng_seedkey_r(&tf_prng_sdata, skey);
|
||||
}
|
||||
|
||||
void tf_prng_genrandom_r(void *sdata, void *result, size_t need)
|
||||
{
|
||||
struct tf_prng_data *rprng = sdata;
|
||||
memset(result, 0, need);
|
||||
tfe_emit(result, need, &rprng->tfe);
|
||||
}
|
||||
|
||||
void tf_prng_genrandom(void *result, size_t need)
|
||||
{
|
||||
tf_prng_genrandom_r(&tf_prng_sdata, result, need);
|
||||
}
|
||||
|
||||
void tf_prng_seed_r(void *sdata, TF_UNIT_TYPE seed)
|
||||
{
|
||||
TF_UNIT_TYPE k[TF_NR_KEY_UNITS];
|
||||
struct tf_prng_data *rprng = sdata;
|
||||
size_t x;
|
||||
|
||||
memset(rprng, 0, tf_prng_datasize());
|
||||
for (x = 0; x < TF_NR_KEY_UNITS; x++) k[x] = seed;
|
||||
tfe_init(&rprng->tfe, k);
|
||||
rprng->init = 1;
|
||||
|
||||
memset(k, 0, TF_KEY_SIZE);
|
||||
}
|
||||
|
||||
void tf_prng_seed(TF_UNIT_TYPE seed)
|
||||
{
|
||||
tf_prng_seed_r(&tf_prng_sdata, seed);
|
||||
}
|
||||
|
||||
TF_UNIT_TYPE tf_prng_random_r(void *sdata)
|
||||
{
|
||||
struct tf_prng_data *rprng = sdata;
|
||||
TF_UNIT_TYPE r;
|
||||
|
||||
if (!rprng->init) return 0;
|
||||
|
||||
tfe_emit(&r, sizeof(r), &rprng->tfe);
|
||||
return r;
|
||||
}
|
||||
|
||||
TF_UNIT_TYPE tf_prng_random(void)
|
||||
{
|
||||
return tf_prng_random_r(&tf_prng_sdata);
|
||||
}
|
||||
|
||||
TF_UNIT_TYPE tf_prng_range_r(void *sdata, TF_UNIT_TYPE s, TF_UNIT_TYPE d)
|
||||
{
|
||||
TF_UNIT_TYPE c = tf_prng_random_r(sdata);
|
||||
if (d <= s) return s;
|
||||
return s + c / ((TF_UNIT_TYPE)~0 / (d - s + 1) + 1);
|
||||
}
|
||||
|
||||
TF_UNIT_TYPE tf_prng_range(TF_UNIT_TYPE s, TF_UNIT_TYPE d)
|
||||
{
|
||||
return tf_prng_range_r(&tf_prng_sdata, s, d);
|
||||
}
|
22
tfprng.h
Normal file
22
tfprng.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef _TF_PRNG_DEFINITIONS_HEADER
|
||||
#define _TF_PRNG_DEFINITIONS_HEADER
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "tfdef.h"
|
||||
|
||||
#define TF_PRNG_KEY_SIZE TF_KEY_SIZE
|
||||
#define TF_PRNG_SIZE_UNIT TF_SIZE_UNIT
|
||||
|
||||
size_t tf_prng_datasize(void);
|
||||
void tf_prng_seedkey_r(void *sdata, const void *skey);
|
||||
void tf_prng_seedkey(const void *skey);
|
||||
void tf_prng_genrandom_r(void *sdata, void *result, size_t need);
|
||||
void tf_prng_genrandom(void *result, size_t need);
|
||||
void tf_prng_seed_r(void *sdata, TF_UNIT_TYPE seed);
|
||||
void tf_prng_seed(TF_UNIT_TYPE seed);
|
||||
TF_UNIT_TYPE tf_prng_random_r(void *sdata);
|
||||
TF_UNIT_TYPE tf_prng_random(void);
|
||||
TF_UNIT_TYPE tf_prng_range_r(void *sdata, TF_UNIT_TYPE s, TF_UNIT_TYPE d);
|
||||
TF_UNIT_TYPE tf_prng_range(TF_UNIT_TYPE s, TF_UNIT_TYPE d);
|
||||
|
||||
#endif
|
31
tfrand.c
Normal file
31
tfrand.c
Normal file
@ -0,0 +1,31 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "tfdef.h"
|
||||
#include "tfprng.h"
|
||||
|
||||
#define DATASIZE 65536
|
||||
|
||||
static char data[DATASIZE];
|
||||
static char key[TF_KEY_SIZE];
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd != -1) {
|
||||
read(fd, key, sizeof(key));
|
||||
close(fd);
|
||||
}
|
||||
|
||||
tf_prng_seedkey(key);
|
||||
while (1) {
|
||||
tf_prng_genrandom(data, DATASIZE);
|
||||
if (write(1, data, DATASIZE) == -1) return 1;
|
||||
}
|
||||
tf_prng_seedkey(NULL);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user