{"id":4003,"date":"2026-08-24T22:09:33","date_gmt":"2026-08-24T20:09:33","guid":{"rendered":"https:\/\/moijari.com\/?p=4003"},"modified":"2026-09-14T14:38:42","modified_gmt":"2026-09-14T12:38:42","slug":"dbs4-new-blend","status":"publish","type":"post","link":"https:\/\/moijari.com\/?p=4003","title":{"rendered":"DBA3: new blend"},"content":{"rendered":"\n<p>Kaikki oikeudet pid\u00e4tet\u00e4\u00e4n \u00a9. 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\u00e4\u00e4n nimesi ja asuinpaikkakuntasi. Kiitokset lahjoituksestasi.<\/p>\n\n\n\n<p>Edellisen artikkelin paras osa oli ressu2: Ohjelma esitt\u00e4\u00e4 satunnaisbittigeneraattorin joka perustuu vaihteluun toistuvassa kellojonon luvussa. T\u00e4ss\u00e4 versiossa kierroksen luuppiin on lis\u00e4tty kellonaika mikrosekunteina ja prosessiin kulunut aika mikrosekunteina. N\u00e4iden avulla saadaan generaattori toiselle tielle, jos jostain syyst\u00e4 kellojono on s\u00e4\u00e4nn\u00f6llinen tai alkuper\u00e4inen luuppi  tuottaa jostain oudosta syyst\u00e4 saman tuloksen.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n#include &lt;memory.h&gt;\n#include &lt;ctype.h&gt;\n\n#include &lt;sys\/time.h&gt;\n#include &lt;time.h&gt;\n\n#define MAIN 2\n\nunsigned char *procname;\nstatic unsigned char *programname = \"Ressu2 version 1.00 \u00a9\";\nstatic unsigned char *copyright = \"Copyright (c) 2013-2026 Jari Kuivaniemi (moijari.com), Helsinki, Finland. Kaikki oikeudet pid\u00e4tet\u00e4\u00e4n!\";\nint my_output = 0;\n\nvoid my_dump(unsigned char *header, int len, unsigned char *buf, int linelen)\n{\n  int c;\n\n  if(my_output) {\n    fprintf(stdout,\"\\n\");\n    my_output = 0;\n  }\n  for(c = 0; c &lt; len; c++) {\n    if(c % linelen == 0) {\n      if(c &gt; 0)\n\tfprintf(stdout,\"\\n\");\n      fprintf(stdout,\"%-10s\", header);\n    }\n    fprintf(stdout,\" %02x\", buf&#91;c]);\n  }\n  fprintf(stdout,\"\\n\");\n  fflush(stdout);\n}\n\n#define aDEBUG8 2\n\n#define aUSE_URANDOM 2\n#define USE_RESSU2 2\n#define USE_PSEUDORESSU2 2\n#define USE_RESSU2TWIST 2\n\n#if defined USE_RESSU2 || defined USE_PSEUDORESSU2 || defined USE_RESSU2TWIST\n\nstatic unsigned long long my_ressu_useconds()\n{\n  struct timeval tv;\n  gettimeofday(&amp;tv, NULL);\n  return((unsigned long long) tv.tv_usec + 1000000ULL * (unsigned long long) tv.tv_sec);\n}\n\nstatic unsigned char my_ressu_lowusec() \/* JariK 2013 *\/\n{\n  struct timeval tv;\n  gettimeofday(&amp;tv, NULL);\n  return(tv.tv_usec &amp; 0xff);\n}\n\nstatic int randomness = 0;\n\n#define RESSU_ROTATELEFT8(byte, bits) ( ((byte) &gt;&gt; (8 - (bits))) | ((byte) &lt;&lt; (bits)) )\n\nstatic void my_ressu2_round(int size, unsigned char *buffer) \/\/ ressu JariK 2013, 2025\n{\n  int c, d, byte;\n  unsigned char e;\n  static int f = 0, prevbyte = -1;\n  unsigned long long usec;\n  \n  for(c = 0; c &lt; 8; c++) { \/\/ eight bits per byte\n    for(d = 0; d &lt; size; d++) { \/\/ rotate + xor\n      e = buffer&#91;d];\n      e = RESSU_ROTATELEFT8(e, 1);  \/\/ rotate byte left 1 bits\n      byte = my_ressu_lowusec();\n      buffer&#91;d] = e ^ byte;\n      if(prevbyte != byte) {\n\tprevbyte = byte;\n\trandomness++;\n      }\n    }\n    for(d = 0; d &lt; size; d++) { \/\/ swap\n      f = (f + 16 + buffer&#91;d] + 2) % size;\n      e = buffer&#91;d];\n      buffer&#91;d] = buffer&#91;f];\n      buffer&#91;f] = e;\n    }\n    \n    \/\/ more randomness from clocks\n    usec = clock();\n    while(usec &gt; 0) {\n      f = (f + usec) % size;\n      usec \/= size;\n    }\n    usec = my_ressu_useconds();\n    while(usec &gt; 0) {\n      f = (f + usec) % size;\n      usec \/= size;\n    }\n  } \/\/ end of for(c = 0; c &lt; 8; c++\n}\n\n#include \"newressu.h\"\n\n#define RESSU2_BYTES 2048 \/\/ now 2048\n#define RESSU2_RANDOMNESS_NEEDED 2048 \/\/ now 2048 \n#define RESSU2_CLOCKS_NEEDED 20480 \/\/ now 20480\n#define RESSU2_MINIMUM_ROUNDS 5 \/\/ now 5\n\nvoid my_ressu2_bytes(int size, unsigned char *buffer) \/\/ Ressu2 v1.1 JariK 2013, 2025, 2026\n{\n  int c, d, clocksused;\n  static int ressu_pos = 0, initneeded = 1;\n  static unsigned char ressu&#91;RESSU2_BYTES];\n  \n  for(c = 0; c &lt; size; c++) {\n    if(ressu_pos == 0) {\n      if(initneeded) {\n\tmemset(&amp;ressu, 0, sizeof(ressu));\n\tinitneeded = 0;\n      }\n      randomness = 0;\n      clocksused = 0;\n      \/\/memset(&amp;ressu, 0, sizeof(ressu));\n      \n      for(d = 0; d &lt; RESSU2_MINIMUM_ROUNDS ||\n\t    randomness &lt; RESSU2_RANDOMNESS_NEEDED ||\n\t    clocksused &lt; RESSU2_CLOCKS_NEEDED\n\t    ; d++) {\n\tmy_ressu2_round(sizeof(ressu), ressu);\n\tclocksused += (sizeof(ressu) * 8);\n      }\n      \n#ifdef DEBUG8\n      my_dump(\"myressu2g\", sizeof(ressu), ressu, 32);      \n#endif\n    } \/\/ end of if(ressu_pos == 0\n    buffer&#91;c] ^= ressu&#91;ressu_pos];\n    ressu_pos = (ressu_pos + 1) % sizeof(ressu);\n  } \/\/ end of for(c = 0; c &lt; size; c++\n#ifdef DEBUG8\n  my_dump(\"myressu2\", size, buffer, 32);\n#endif\n}\n\n#endif \/\/ end of #if defined USE_RESSU2 || defined USE_PSEUDORESSU2 || defined USE_RESSU2TWIST\n\n#if defined USE_PSEUDORESSU2 || defined USE_RESSU2TWIST\n\nunsigned char cvar&#91;16];\nint cvarsize = 0;\n\nvoid inccvar()\n{\n  int c;\n\n  \/* 16 bytes, LSB first *\/\n  for(c = 0; ++cvar&#91;c] == 0 &amp;&amp; c &lt; sizeof(cvar) - 1; c++);\n\n  if(cvarsize &lt; c)\n    cvarsize = c;\n\n#ifdef DEBUG20\n  ressu_dump(\"cvar\", cvarsize + 1, cvar, 32);\n#endif\n}\n\nvoid clearcvar()\n{\n  int c;\n\n  cvarsize = 0;\n  \n  for(c = 0; c &lt; sizeof(cvar); c++)\n    cvar&#91;c] = 0;\n\n  for(c = 0; c &lt; sizeof(cvar); c++)\n    if(cvar&#91;c] != 0)\n      cvarsize = c;\n}\n\n#include \"sha256.h\"\n\n#define PSEUDORESSU2_BYTES 32*1024 \/\/ bytes between topups\n#define PSEUDORESSU2_TOPUP_BYTES 32*1024 \/\/ bytes between topups\n#define PSEUDORESSU2_TOPUP_SIZE 32 \/\/ topup size in bytes (32 bytes, 256 bits)\n#define PSEUDORESSU2_TOPUP_TWICE 2 \/\/ off by default\n\nstatic unsigned char pseudoressu2_key&#91;HashLen]; \/\/ 32 bytes, 256 bits\n\nstatic void my_pseudoressu2_internalbytes(unsigned char *digest)\n{\n  HashCtx hash;\n\n  HashInit(&amp;hash);\n  HashUpdate(&amp;hash, pseudoressu2_key, sizeof(pseudoressu2_key)); \/\/ add old randomness to hash\n  HashUpdate(&amp;hash, (unsigned char *) &amp;cvar, cvarsize + 1);\n  inccvar();\n  HashFinal(digest, &amp;hash);\n  memset(&amp;hash, 0, sizeof(hash)); \/\/ forget hash\n}\n\nstatic void my_pseudoressu2_addrandomness(int size, unsigned char *buffer)\n{\n  unsigned long long usec;\n  HashCtx hash;\n\n  HashInit(&amp;hash);\n  HashUpdate(&amp;hash, pseudoressu2_key, sizeof(pseudoressu2_key)); \/\/ add old randomness to hash\n  HashUpdate(&amp;hash, (unsigned char *) &amp;cvar, cvarsize + 1);\n  inccvar();\n  usec = my_ressu_useconds(); \/\/ add timestamp to hash\n  HashUpdate(&amp;hash, (unsigned char *)&amp;usec, sizeof(usec));\n  usec = clock(); \/\/ add processor time to hash (for randomness)\n  HashUpdate(&amp;hash, (unsigned char *)&amp;usec, sizeof(usec));\n  HashUpdate(&amp;hash, buffer, size); \/\/ add given randomness to hash\n  HashFinal(pseudoressu2_key, &amp;hash); \/\/ save as new key\n  memset(&amp;hash, 0, sizeof(hash)); \/\/ forget hash\n}\n\nstatic void my_pseudoressu2_topup()\n{\n  unsigned char topup&#91;PSEUDORESSU2_TOPUP_SIZE]; \/\/ 32 bytes, 256 bits\n\n  memset(&amp;topup, 0, sizeof(topup)); \/\/ forget topup\n  my_ressu2_bytes(sizeof(topup), topup);\n#ifdef DEBUG8\n  my_dump(\"topup\", sizeof(topup), topup, 32);\n#endif\n  my_pseudoressu2_addrandomness(sizeof(topup), topup);\n\n  memset(&amp;topup, 0, sizeof(topup)); \/\/ forget topup\n}\n\nvoid my_pseudoressu2_bytes(int size, unsigned char *buffer) \/\/ JariK 2022, 2025\n{\n  int c;\n  static int pseudoressu_pos = 0, topup_counter = 0, initneeded = 1;\n  static unsigned char pseudoressu&#91;HashLen]; \/\/ 32 bytes, 256 bits\n\n  for(c = 0; c &lt; size; c++) {\n    if(pseudoressu_pos == 0) {\n      if(topup_counter == 0) {\n\tif(initneeded) {\n\t  my_ressu2_bytes(sizeof(pseudoressu2_key), pseudoressu2_key); \/\/ get first key\n#ifdef DEBUG8\n\t  my_dump(\"first key\", sizeof(pseudoressu2_key), pseudoressu2_key, 32);\n#endif\n\t  initneeded = 0;\n\t} \/\/ end of if(initneeded\n\t\n\tmy_pseudoressu2_topup(); \/\/ add randomness to key, first block also\n#ifdef PSEUDORESSU2_TOPUP_TWICE\n\tmy_pseudoressu2_topup(); \/\/ add randomness to key, first block also\n#endif\n\ttopup_counter = PSEUDORESSU2_TOPUP_BYTES;\n      } \/\/ end of if(topup_counter == 0\n      \n      my_pseudoressu2_internalbytes(pseudoressu); \/\/ get random bits using the key\n#ifdef DEBUG8\n      my_dump(\"next data\", sizeof(pseudoressu), pseudoressu, 32);\n#endif\n      topup_counter -= sizeof(pseudoressu);\n    } \/\/ end of if(pseudoressu_pos == 0\n\n    buffer&#91;c] ^= pseudoressu&#91;pseudoressu_pos];\n    pseudoressu_pos = (pseudoressu_pos + 1) % sizeof(pseudoressu);\n  } \/\/ end of for(c = 0; c &lt; size; c++\n  \n  my_pseudoressu2_internalbytes(pseudoressu2_key); \/\/ replace key with new random one\n#ifdef DEBUG8\n  my_dump(\"new key\", sizeof(pseudoressu2_key), pseudoressu2_key, 32);\n#endif\n#ifdef DEBUG8\n  my_dump(\"pseudoressu\", size, buffer, 32);\n#endif\n}\n\n#endif \/\/ end of #if defined USE_PSEUDORESSU2 || defined USE_RESSU2TWIST\n\n#ifdef USE_RESSU2TWIST\n\nvoid my_ressu2twist_bytes(int size, unsigned char *buffer) \/\/ JariK 2023, 2025\n{\n  \/\/urandom_bytes(size, buffer);\n  my_ressu2_bytes(size, buffer);\n  my_pseudoressu2_bytes(size, buffer);\n#ifdef DEBUG8\n  my_dump(\"ressu2twist\", size, buffer, 32);\n#endif\n}\n\n#endif \/\/ end of #ifdef USE_RESSU2TWIST\n\n#ifdef USE_URANDOM\n\nvoid my_readfile_xor(int size, unsigned char *buffer, unsigned char *filename)\n{\n  int c, n, filebuffer_pos = 0;\n  unsigned char filebuffer&#91;64];\n  FILE *fp1;\n\n  if((fp1 = fopen(filename, \"rb\")) == NULL) {\n    fprintf(stderr,\"%s: fopen(): cannot open file %s\\n\",\n\t    procname, filename);\n    exit(1);\n  }\n\n  for(c = 0; c &lt; size; c++) {\n    if(filebuffer_pos == 0) {\n      n = (size - c &lt; sizeof(filebuffer)) ? size - c : sizeof(filebuffer);\n      if(fread(filebuffer, 1, n, fp1) &lt; n) {\n\tfprintf(stderr,\"%s: fread(): cannot read file %s\\n\",\n\t\tprocname, filename);\n\texit(1);\n      }\n#ifdef DEBUG8\n      my_dump(\"file\", n, filebuffer, 32);\n#endif\n    } \/\/ end of if(file_pos == 0\n    buffer&#91;c] ^= filebuffer&#91;filebuffer_pos];\n    filebuffer_pos = (filebuffer_pos + 1) % sizeof(filebuffer);\n  } \/\/ end of for(c = 0; c &lt; size; c++\n\n  fclose(fp1);\n\n  memset(filebuffer, 0, sizeof(filebuffer)); \/\/ forget file\n}\n\nstatic unsigned char urandomfilename&#91;128] = \"\/dev\/urandom\";\n\nvoid my_urandom_bytes(int size, unsigned char *buffer)\n{\n  my_readfile_xor(size, buffer, urandomfilename);\n#ifdef DEBUG8\n  my_dump(\"urandom\", size, buffer, 32);\n#endif\n}\n\n#endif \/\/ end of #ifdef USE_URANDOM\n\nvoid my_random_bytes(int size, unsigned char *buffer)\n{\n#ifdef USE_URANDOM\n  my_urandom_bytes(size, buffer);\n#endif\n  \/\/ressu_round(size, buffer);\n  \/\/ressu_genbytes(size, buffer);\n  \/\/pseudoressu_bytes(size, buffer);\n  \/\/ressutwist_bytes(size, buffer);\n  \/\/my_ressu2_round(size, buffer);\n#ifdef USE_PSEUDORESSU2\n  my_pseudoressu2_bytes(size, buffer);\n#endif\n#ifdef USE_RESSU2TWIST\n  my_ressu2twist_bytes(size, buffer);\n#endif\n#ifdef USE_RESSU2\n  my_ressu2_bytes(size, buffer);\n#endif\n}\n\n#define GENT_SIZE 128\n\nstatic unsigned char gent&#91;GENT_SIZE];\nstatic unsigned int gent_pos = 0;\n\nint my_random_byte()\n{\n  unsigned char ch;\n  static int initneeded = 1;\n\n  if(gent_pos == 0) {\n    if(initneeded) {\n      memset(&amp;gent, 0, sizeof(gent));\n      initneeded = 0;\n    }\n    my_random_bytes(sizeof(gent), gent);\n  }\n  ch = gent&#91;gent_pos];\n  gent_pos = (gent_pos + 1) % sizeof(gent);\n\n  return(ch);\n}\n\nunsigned long my_random_genlimit(unsigned long limit)\n{\n  int c;\n  unsigned long word;\n  static unsigned long lastlimit = 0, highlimit;\n  static int bytes;\n  \n  if(lastlimit != limit) { \/\/ if limit changes, calculate new highlimit and bytes\n    lastlimit = limit;\n    if(limit &lt;= 0x100) {\n      \/\/ highest multiplier of limit that fits to needed bytes\n      highlimit = (0x100 \/ limit) * limit;\n      \/\/ number of bytes needed\n      bytes = 1;\n    } else if(limit &lt;= 0x10000) {\n      highlimit = (0x10000 \/ limit) * limit;\n      bytes = 2;\n    } else if(limit &lt;= 0x1000000) {\n      highlimit = (0x1000000 \/ limit) * limit;\n      bytes = 3;\n    } else if(limit &lt;= 0x100000000) {\n      highlimit = (0x100000000 \/ limit) * limit;\n      bytes = 4;\n    } else if(limit &lt;= 0x10000000000) {\n      highlimit = (0x10000000000 \/ limit) * limit;\n      bytes = 5;\n    } else if(limit &lt;= 0x1000000000000) {\n      highlimit = (0x1000000000000 \/ limit) * limit;\n      bytes = 6;\n    } else if(limit &lt;= 0x100000000000000) {\n      highlimit = (0x100000000000000 \/ limit) * limit;\n      bytes = 7;\n    } else { \/\/ if(limit &lt;= 0xffffffffffffffff) {\n      highlimit = (0xffffffffffffffff \/ limit) * limit;      \n      bytes = 8;\n    }\n  } \/\/ if(lastlimit != limit)\n\n  for(;;) {\n    word = 0;\n    for(c = 0; c &lt; bytes; c++)\n      word = word &lt;&lt; 8 | my_random_byte();\n    if(word &lt; highlimit)\n      break;\n  }\n\n  word %= limit;\n  \n  return(word);\n}\n\nvoid ressu2_version()\n{\n  fprintf(stderr, \"%s\", programname); \/\/ touch these outside #ifdef MAIN\n  fprintf(stderr, \", %s\", copyright);\n}\n\n#include &lt;sys\/ioctl.h&gt; \/\/ for TIOCGWINSZ\n\n#ifdef MAIN\n\nint main(int argc, char *argv&#91;])\n{\n  int c, d;\n\n  procname = argv&#91;0];\n\n  \/\/\n  \/\/ look thru command line parameters\n  \/\/\n\n  for(c = 1; c &lt; argc; c++) {\n    if(!strcmp(\"--copyright\", argv&#91;c]) ||\n       !strcmp(\"--version\", argv&#91;c])) {\n      ressu2_version();\n#ifdef SHA256\n      fprintf(stderr,\"\\nsha256(\");\n      for(int c = 0; c &lt; HashLen; c++) {\n\tfprintf(stderr, \"%02x\", programfiledigest&#91;c]);\n      }\n#endif \/\/ end of #ifdef SHA256\n\n    }\n  }\n\n  for(c = 0; c &lt; 10; c++) {\n    fprintf(stdout, \"%05x\", c);\n    my_output = 1;\n    for(d = 0; d &lt; 32; d++) {\n      fprintf(stdout, \" \");\n      fprintf(stdout, \"%02llx\", (unsigned long long) my_random_genlimit(0x100));\n    }\n    fprintf(stdout,\"\\n\");\n  }\n}\n#endif \/\/ end of #ifdef MAIN<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Kaikki oikeudet pid\u00e4tet\u00e4\u00e4n \u00a9. 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\u00e4\u00e4n nimesi ja asuinpaikkakuntasi. Kiitokset lahjoituksestasi. Edellisen artikkelin paras osa oli ressu2: Ohjelma esitt\u00e4\u00e4 satunnaisbittigeneraattorin joka perustuu vaihteluun toistuvassa kellojonon luvussa.&hellip; <a class=\"more-link\" href=\"https:\/\/moijari.com\/?p=4003\">Continue reading <span class=\"screen-reader-text\">DBA3: new blend<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts\/4003"}],"collection":[{"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4003"}],"version-history":[{"count":4,"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts\/4003\/revisions"}],"predecessor-version":[{"id":4009,"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts\/4003\/revisions\/4009"}],"wp:attachment":[{"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4003"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4003"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4003"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}