Kaikki oikeudet pidätetään ©. Jos haluat tukea projektia (osallistua palvelinkustannuksiin, tarjota koodausvissyn tai tulevaisuudessa maksaa palkkaa), laita muutaman euron lahjoituksesi Danske Bank tilille FI15 8312 0710 7275 83 (SWIFT:DABAFIHH), maksun saaja Jari Kuivaniemi. Kirjoita viestikenttään nimesi ja asuinpaikkakuntasi. Kiitokset lahjoituksestasi.
Edellisen artikkellin paras osa oli ressu2:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <ctype.h>
#include <sys/time.h>
#include <time.h>
#define MAIN 2
unsigned char *procname;
static unsigned char *programname = "Ressu2 version 1.00 ©";
static unsigned char *copyright = "Copyright (c) 2013-2026 Jari Kuivaniemi (moijari.com), Helsinki, Finland. Kaikki oikeudet pidätetään!";
int my_output = 0;
void my_dump(unsigned char *header, int len, unsigned char *buf, int linelen)
{
int c;
if(my_output) {
fprintf(stdout,"\n");
my_output = 0;
}
for(c = 0; c < len; c++) {
if(c % linelen == 0) {
if(c > 0)
fprintf(stdout,"\n");
fprintf(stdout,"%-10s", header);
}
fprintf(stdout," %02x", buf[c]);
}
fprintf(stdout,"\n");
fflush(stdout);
}
#define aDEBUG8 2
#define aUSE_URANDOM 2
#define USE_RESSU2 2
#define USE_PSEUDORESSU2 2
#define USE_RESSU2TWIST 2
#if defined USE_RESSU2 || defined USE_PSEUDORESSU2 || defined USE_RESSU2TWIST
static unsigned long long my_ressu_useconds()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return((unsigned long long) tv.tv_usec + 1000000ULL * (unsigned long long) tv.tv_sec);
}
static unsigned char my_ressu_lowusec() /* JariK 2013 */
{
struct timeval tv;
gettimeofday(&tv, NULL);
return(tv.tv_usec & 0xff);
}
static int randomness = 0;
#define RESSU_ROTATELEFT8(byte, bits) ( ((byte) >> (8 - (bits))) | ((byte) << (bits)) )
static void my_ressu2_round(int size, unsigned char *buffer) // ressu JariK 2013, 2025
{
int c, d, byte;
unsigned char e;
static int f = 0, prevbyte = -1;
unsigned long long usec;
for(c = 0; c < 8; c++) { // eight bits per byte
for(d = 0; d < size; d++) { // rotate + xor
e = buffer[d];
e = RESSU_ROTATELEFT8(e, 1); // rotate byte left 1 bits
byte = my_ressu_lowusec();
buffer[d] = e ^ byte;
if(prevbyte != byte) {
prevbyte = byte;
randomness++;
}
}
for(d = 0; d < size; d++) { // swap
f = (f + 16 + buffer[d] + 2) % size;
e = buffer[d];
buffer[d] = buffer[f];
buffer[f] = e;
}
// more randomness from clocks
usec = clock();
while(usec > 0) {
f = (f + usec) % size;
usec /= size;
}
usec = my_ressu_useconds();
while(usec > 0) {
f = (f + usec) % size;
usec /= size;
}
} // end of for(c = 0; c < 8; c++
}
#include "newressu.h"
#define RESSU2_BYTES 2048 // now 2048
#define RESSU2_RANDOMNESS_NEEDED 2048 // now 2048
#define RESSU2_CLOCKS_NEEDED 20480 // now 20480
#define RESSU2_MINIMUM_ROUNDS 5 // now 5
void my_ressu2_bytes(int size, unsigned char *buffer) // Ressu2 v1.1 JariK 2013, 2025, 2026
{
int c, d, clocksused;
static int ressu_pos = 0, initneeded = 1;
static unsigned char ressu[RESSU2_BYTES];
for(c = 0; c < size; c++) {
if(ressu_pos == 0) {
if(initneeded) {
memset(&ressu, 0, sizeof(ressu));
initneeded = 0;
}
randomness = 0;
clocksused = 0;
//memset(&ressu, 0, sizeof(ressu));
for(d = 0; d < RESSU2_MINIMUM_ROUNDS ||
randomness < RESSU2_RANDOMNESS_NEEDED ||
clocksused < RESSU2_CLOCKS_NEEDED
; d++) {
my_ressu2_round(sizeof(ressu), ressu);
clocksused += (sizeof(ressu) * 8);
}
#ifdef DEBUG8
my_dump("myressu2g", sizeof(ressu), ressu, 32);
#endif
} // end of if(ressu_pos == 0
buffer[c] ^= ressu[ressu_pos];
ressu_pos = (ressu_pos + 1) % sizeof(ressu);
} // end of for(c = 0; c < size; c++
#ifdef DEBUG8
my_dump("myressu2", size, buffer, 32);
#endif
}
#endif // end of #if defined USE_RESSU2 || defined USE_PSEUDORESSU2 || defined USE_RESSU2TWIST
#if defined USE_PSEUDORESSU2 || defined USE_RESSU2TWIST
unsigned char cvar[16];
int cvarsize = 0;
void inccvar()
{
int c;
/* 16 bytes, LSB first */
for(c = 0; ++cvar[c] == 0 && c < sizeof(cvar) - 1; c++);
if(cvarsize < c)
cvarsize = c;
#ifdef DEBUG20
ressu_dump("cvar", cvarsize + 1, cvar, 32);
#endif
}
void clearcvar()
{
int c;
cvarsize = 0;
for(c = 0; c < sizeof(cvar); c++)
cvar[c] = 0;
for(c = 0; c < sizeof(cvar); c++)
if(cvar[c] != 0)
cvarsize = c;
}
#include "sha256.h"
#define PSEUDORESSU2_BYTES 32*1024 // bytes between topups
#define PSEUDORESSU2_TOPUP_BYTES 32*1024 // bytes between topups
#define PSEUDORESSU2_TOPUP_SIZE 32 // topup size in bytes (32 bytes, 256 bits)
#define PSEUDORESSU2_TOPUP_TWICE 2 // off by default
static unsigned char pseudoressu2_key[HashLen]; // 32 bytes, 256 bits
static void my_pseudoressu2_internalbytes(unsigned char *digest)
{
HashCtx hash;
HashInit(&hash);
HashUpdate(&hash, pseudoressu2_key, sizeof(pseudoressu2_key)); // add old randomness to hash
HashUpdate(&hash, (unsigned char *) &cvar, cvarsize + 1);
inccvar();
HashFinal(digest, &hash);
memset(&hash, 0, sizeof(hash)); // forget hash
}
static void my_pseudoressu2_addrandomness(int size, unsigned char *buffer)
{
unsigned long long usec;
HashCtx hash;
HashInit(&hash);
HashUpdate(&hash, pseudoressu2_key, sizeof(pseudoressu2_key)); // add old randomness to hash
HashUpdate(&hash, (unsigned char *) &cvar, cvarsize + 1);
inccvar();
usec = my_ressu_useconds(); // add timestamp to hash
HashUpdate(&hash, (unsigned char *)&usec, sizeof(usec));
usec = clock(); // add processor time to hash (for randomness)
HashUpdate(&hash, (unsigned char *)&usec, sizeof(usec));
HashUpdate(&hash, buffer, size); // add given randomness to hash
HashFinal(pseudoressu2_key, &hash); // save as new key
memset(&hash, 0, sizeof(hash)); // forget hash
}
static void my_pseudoressu2_topup()
{
unsigned char topup[PSEUDORESSU2_TOPUP_SIZE]; // 32 bytes, 256 bits
memset(&topup, 0, sizeof(topup)); // forget topup
my_ressu2_bytes(sizeof(topup), topup);
#ifdef DEBUG8
my_dump("topup", sizeof(topup), topup, 32);
#endif
my_pseudoressu2_addrandomness(sizeof(topup), topup);
memset(&topup, 0, sizeof(topup)); // forget topup
}
void my_pseudoressu2_bytes(int size, unsigned char *buffer) // JariK 2022, 2025
{
int c;
static int pseudoressu_pos = 0, topup_counter = 0, initneeded = 1;
static unsigned char pseudoressu[HashLen]; // 32 bytes, 256 bits
for(c = 0; c < size; c++) {
if(pseudoressu_pos == 0) {
if(topup_counter == 0) {
if(initneeded) {
my_ressu2_bytes(sizeof(pseudoressu2_key), pseudoressu2_key); // get first key
#ifdef DEBUG8
my_dump("first key", sizeof(pseudoressu2_key), pseudoressu2_key, 32);
#endif
initneeded = 0;
} // end of if(initneeded
my_pseudoressu2_topup(); // add randomness to key, first block also
#ifdef PSEUDORESSU2_TOPUP_TWICE
my_pseudoressu2_topup(); // add randomness to key, first block also
#endif
topup_counter = PSEUDORESSU2_TOPUP_BYTES;
} // end of if(topup_counter == 0
my_pseudoressu2_internalbytes(pseudoressu); // get random bits using the key
#ifdef DEBUG8
my_dump("next data", sizeof(pseudoressu), pseudoressu, 32);
#endif
topup_counter -= sizeof(pseudoressu);
} // end of if(pseudoressu_pos == 0
buffer[c] ^= pseudoressu[pseudoressu_pos];
pseudoressu_pos = (pseudoressu_pos + 1) % sizeof(pseudoressu);
} // end of for(c = 0; c < size; c++
my_pseudoressu2_internalbytes(pseudoressu2_key); // replace key with new random one
#ifdef DEBUG8
my_dump("new key", sizeof(pseudoressu2_key), pseudoressu2_key, 32);
#endif
#ifdef DEBUG8
my_dump("pseudoressu", size, buffer, 32);
#endif
}
#endif // end of #if defined USE_PSEUDORESSU2 || defined USE_RESSU2TWIST
#ifdef USE_RESSU2TWIST
void my_ressu2twist_bytes(int size, unsigned char *buffer) // JariK 2023, 2025
{
//urandom_bytes(size, buffer);
my_ressu2_bytes(size, buffer);
my_pseudoressu2_bytes(size, buffer);
#ifdef DEBUG8
my_dump("ressu2twist", size, buffer, 32);
#endif
}
#endif // end of #ifdef USE_RESSU2TWIST
#ifdef USE_URANDOM
void my_readfile_xor(int size, unsigned char *buffer, unsigned char *filename)
{
int c, n, filebuffer_pos = 0;
unsigned char filebuffer[64];
FILE *fp1;
if((fp1 = fopen(filename, "rb")) == NULL) {
fprintf(stderr,"%s: fopen(): cannot open file %s\n",
procname, filename);
exit(1);
}
for(c = 0; c < size; c++) {
if(filebuffer_pos == 0) {
n = (size - c < sizeof(filebuffer)) ? size - c : sizeof(filebuffer);
if(fread(filebuffer, 1, n, fp1) < n) {
fprintf(stderr,"%s: fread(): cannot read file %s\n",
procname, filename);
exit(1);
}
#ifdef DEBUG8
my_dump("file", n, filebuffer, 32);
#endif
} // end of if(file_pos == 0
buffer[c] ^= filebuffer[filebuffer_pos];
filebuffer_pos = (filebuffer_pos + 1) % sizeof(filebuffer);
} // end of for(c = 0; c < size; c++
fclose(fp1);
memset(filebuffer, 0, sizeof(filebuffer)); // forget file
}
static unsigned char urandomfilename[128] = "/dev/urandom";
void my_urandom_bytes(int size, unsigned char *buffer)
{
my_readfile_xor(size, buffer, urandomfilename);
#ifdef DEBUG8
my_dump("urandom", size, buffer, 32);
#endif
}
#endif // end of #ifdef USE_URANDOM
void my_random_bytes(int size, unsigned char *buffer)
{
#ifdef USE_URANDOM
my_urandom_bytes(size, buffer);
#endif
//ressu_round(size, buffer);
//ressu_genbytes(size, buffer);
//pseudoressu_bytes(size, buffer);
//ressutwist_bytes(size, buffer);
//my_ressu2_round(size, buffer);
#ifdef USE_PSEUDORESSU2
my_pseudoressu2_bytes(size, buffer);
#endif
#ifdef USE_RESSU2TWIST
my_ressu2twist_bytes(size, buffer);
#endif
#ifdef USE_RESSU2
my_ressu2_bytes(size, buffer);
#endif
}
#define GENT_SIZE 128
static unsigned char gent[GENT_SIZE];
static unsigned int gent_pos = 0;
int my_random_byte()
{
unsigned char ch;
static int initneeded = 1;
if(gent_pos == 0) {
if(initneeded) {
memset(&gent, 0, sizeof(gent));
initneeded = 0;
}
my_random_bytes(sizeof(gent), gent);
}
ch = gent[gent_pos];
gent_pos = (gent_pos + 1) % sizeof(gent);
return(ch);
}
unsigned long my_random_genlimit(unsigned long limit)
{
int c;
unsigned long word;
static unsigned long lastlimit = 0, highlimit;
static int bytes;
if(lastlimit != limit) { // if limit changes, calculate new highlimit and bytes
lastlimit = limit;
if(limit <= 0x100) {
// highest multiplier of limit that fits to needed bytes
highlimit = (0x100 / limit) * limit;
// number of bytes needed
bytes = 1;
} else if(limit <= 0x10000) {
highlimit = (0x10000 / limit) * limit;
bytes = 2;
} else if(limit <= 0x1000000) {
highlimit = (0x1000000 / limit) * limit;
bytes = 3;
} else if(limit <= 0x100000000) {
highlimit = (0x100000000 / limit) * limit;
bytes = 4;
} else if(limit <= 0x10000000000) {
highlimit = (0x10000000000 / limit) * limit;
bytes = 5;
} else if(limit <= 0x1000000000000) {
highlimit = (0x1000000000000 / limit) * limit;
bytes = 6;
} else if(limit <= 0x100000000000000) {
highlimit = (0x100000000000000 / limit) * limit;
bytes = 7;
} else { // if(limit <= 0xffffffffffffffff) {
highlimit = (0xffffffffffffffff / limit) * limit;
bytes = 8;
}
} // if(lastlimit != limit)
for(;;) {
word = 0;
for(c = 0; c < bytes; c++)
word = word << 8 | my_random_byte();
if(word < highlimit)
break;
}
word %= limit;
return(word);
}
void ressu2_version()
{
fprintf(stderr, "%s", programname); // touch these outside #ifdef MAIN
fprintf(stderr, ", %s", copyright);
}
#include <sys/ioctl.h> // for TIOCGWINSZ
#ifdef MAIN
int main(int argc, char *argv[])
{
int c, d;
procname = argv[0];
//
// look thru command line parameters
//
for(c = 1; c < argc; c++) {
if(!strcmp("--copyright", argv[c]) ||
!strcmp("--version", argv[c])) {
ressu2_version();
#ifdef SHA256
fprintf(stderr,"\nsha256(");
for(int c = 0; c < HashLen; c++) {
fprintf(stderr, "%02x", programfiledigest[c]);
}
#endif // end of #ifdef SHA256
}
}
for(c = 0; c < 10; c++) {
fprintf(stdout, "%05x", c);
my_output = 1;
for(d = 0; d < 32; d++) {
fprintf(stdout, " ");
fprintf(stdout, "%02llx", (unsigned long long) my_random_genlimit(0x100));
}
fprintf(stdout,"\n");
}
}
#endif // end of #ifdef MAIN