{"id":964,"date":"2020-07-12T21:54:30","date_gmt":"2020-07-12T19:54:30","guid":{"rendered":"https:\/\/moijari.com\/?p=964"},"modified":"2020-08-23T00:41:18","modified_gmt":"2020-08-22T22:41:18","slug":"fort-v0-4-uusi-versio","status":"publish","type":"post","link":"https:\/\/moijari.com\/?p=964","title":{"rendered":"FORT v0.4 uusi versio"},"content":{"rendered":"\n<p>Fortin edellisest\u00e4 versiosta (<a rel=\"noreferrer noopener\" target=\"_blank\" href=\"https:\/\/moijari.com\/?p=634\">https:\/\/moijari.com\/?p=634<\/a>) on kulunut jo jonkin verran aikaa ja uudessa versiossa on muutoksia, joten ajattelin postata uuden version. Oikeastaan varsinaisessa koodissa ei ole paljon muutoksia, ainoastaan nuo lohkon alun (FORT_INTERNAL_EVENTS_START) ja lopun (FORT_INTERNAL_EVENTS_END) makrot. Funktioiden esittelyt ovat muuttuneet siten, ett\u00e4 t\u00e4m\u00e4n tiedoston (fort.c) sis\u00e4isiin apufunktioihin on lis\u00e4tty static sana, joka est\u00e4\u00e4 funktioiden k\u00e4yt\u00f6n fort.c tiedoston ulkopuolella. Lis\u00e4ksi globaaleissa muuttujissa on static sana, jos ei ole toivottavaa ett\u00e4 niit\u00e4 k\u00e4ytet\u00e4\u00e4n fort.c:n ulkopuolelta.<\/p>\n\n\n\n<p>Jos haluat lis\u00e4tietoa Fortunasta, t\u00e4ss\u00e4 on wikipediasivu <a href=\"https:\/\/en.wikipedia.org\/wiki\/Fortuna_(PRNG)\">https:\/\/en.wikipedia.org\/wiki\/Fortuna_(PRNG)<\/a>.<\/p>\n\n\n\n<p>Edit: tehty korjauksia ja muutoksia julkaisun j\u00e4lkeisten viikkojen aikana:<\/p>\n\n\n\n<p>Poistettu fort_add_random_event_time():sta toistuva toinen merkki. N\u00e4in tapahtuma tehd\u00e4\u00e4n vain alimmista kahdeksasta bitist\u00e4, joissa on eniten satunnaisuutta ja seuraavat kahdeksan bitti\u00e4, joissa satunnaisuutta ei ole ohitetaan. Toinen merkki l\u00e4hetet\u00e4\u00e4n puskuriin vain jos se poikkeaa edellisest\u00e4 toisesta merkist\u00e4. Poistosta etuna saadaan se ett\u00e4 puskurien ker\u00e4ttyjen merkkien m\u00e4\u00e4r\u00e4 kuvaa tarkemmin todella satunnaisia merkkej\u00e4, ja t\u00e4ll\u00e4 lis\u00e4t\u00e4\u00e4n satunnaisuutta satunnaistapahtumien datan pituuteen.<\/p>\n\n\n\n<p>Lis\u00e4tty fort_reseed() koodiin aikavy\u00f6hykkeen vaihto. Jos ajon aikana aikavy\u00f6hyke vaihtuu, suoritetaan save ja report koodit. N\u00e4in saadaan raporttien v\u00e4lit laskettua oikein heti uuden aikavy\u00f6hykkeen alusta. Ennen vaihtoa uuden aikavy\u00f6hykkeen ensimm\u00e4inen katko tuli edellisen aikavy\u00f6hykkeen mukaan, jolloin katko ei ollut selke\u00e4. Nyt raportissa n\u00e4kyy aikavy\u00f6hykkeen vaihto rivi vaihdon kellonajalla ja heti seuraava katko on laskettu oikein huomioiden uusi aikavy\u00f6hyke.<\/p>\n\n\n\n<p>Fort_init:iin on lis\u00e4tty mahdollisuus k\u00e4ytt\u00e4\u00e4 \/dev\/random ja \/dev\/urandom tiedostoja fort:in avainnukseen.<\/p>\n\n\n\n<p>Fort_reseed():iin on lis\u00e4tty automaattinen tallennus 10 minuutin v\u00e4lein. Tallennus tapahtuu fort_reseed:iss\u00e4, jos reseedi\u00e4 ei suoriteta tallennusta ei tapahdu. Tallennuksen yhteydess\u00e4 tulostetaan tiedostoon fortpools.deb raporttia puskureiden sis\u00e4lt\u00e4mist\u00e4 merkkim\u00e4\u00e4rist\u00e4. Raportin m\u00e4\u00e4r\u00e4 lyhennet\u00e4\u00e4n lukukelpoiseksi (4 merkki\u00e4) rutiinilla readable_length_decimal().<\/p>\n\n\n\n<p>Satunnaistapahtuman lis\u00e4ykseen on lis\u00e4tty 5 ja 6 moodit. My\u00f6s puskurien m\u00e4\u00e4r\u00e4\u00e4 voi kasvattaa 64:een (FORT_64_POOLS).<\/p>\n\n\n\n<p>Erotettu satunnaisgeneraattorin tilan tallennus ja puskurien ker\u00e4tyt merkit raportti toisistaan. N\u00e4in niiden v\u00e4liset ajat voidaan valita erikseen.<\/p>\n\n\n\n<p>Lis\u00e4tty puskurien ker\u00e4tyt merkit raporttiin bin\u00e4\u00e4rimoodi, jossa katkokohta on 1000 (decimal) sijasta 1024(binary). Moodi valitaan muuttujalla FORT_DUMP_POOLS_BIN. Bin\u00e4\u00e4ritulosteesta on malli postin lopussa.<\/p>\n\n\n\n<p>Jos haluat tehd\u00e4 esittelytiedoston fort:in toiminnoista t\u00e4ss\u00e4 mahdollinen fort.h tiedosto p\u00e4\u00e4funktioista.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>typedef unsigned long long IUTIME;\n\nvoid fort_add_random_event(int *pool, int source, int mode, int len, unsigned char *buf);\nvoid fort_add_random_event_timer_start(IUTIME *micros);\nvoid fort_add_random_event_timer_do(int *pool, int source, int mode, IUTIME *micros);\nvoid fort_add_random_event_time(int *pool, int source, int mode);\nvoid fort_add_random_event_split(int *pool, int source, int mode, int len, unsigned char *buf, int size);\nvoid fort_rekey(unsigned char *buf);\nvoid fort_pseudo_random_data(int len, unsigned char *buf);\nvoid fort_reseed(int len, unsigned char *buf);\nvoid fort_random_data(int len, unsigned char *buf);\nint fort_random_data_byte();\nvoid fort_clear();\nint fort_random_data_byte_limit(int limit);\nvoid fort_random_data_buffer(int size, unsigned char *buffer);\nvoid fort_save();\nvoid fort_restore();\nvoid dump_pools(char *header);<\/code><\/pre>\n\n\n\n<p>Seuraavassa fort ohjelman k\u00e4ytt\u00e4m\u00e4t aliohjelmat, inccvar() ja clearcvar() 16 merkkisen laskurin k\u00e4sittelyyn. Gettenths():ll\u00e4 fort_random_data() hakee sekunnin kymmenesosat, perustoiminnassa avainnus voidaan tehd\u00e4 pienimmill\u00e4\u00e4n kymmenesosa sekunnin p\u00e4\u00e4st\u00e4 edellisest\u00e4 avainnuksesta. Getmicroseconds() taas on aikaan liittyvien satunnaistapahtumia tekevien rutiinien k\u00e4yt\u00f6ss\u00e4. Getseconds():illa haetaan sekunnit seuraavan automaattisen fort_save():n ajoitusta varten. Varsinainen ajoitettu save koodi on fort_reseed() funktiossa.<\/p>\n\n\n\n<p>Huomaa, ett\u00e4 n\u00e4iden rutiinien m\u00e4\u00e4rittelyyn on lis\u00e4tty static sana, joka tarkoittaa sit\u00e4 ett\u00e4 rutiinia voidaan kutsua vain t\u00e4st\u00e4 tiedostosta (fort.c). Samoin aiemmin globaaleihin muuttujiin, kuten seuraava cvar[] on lis\u00e4tty static sana ja n\u00e4in sen pit\u00e4isi olla k\u00e4sitelt\u00e4viss\u00e4 vain t\u00e4m\u00e4n tiedoston rutiineilla.<\/p>\n\n\n\n<p>Jos haluat k\u00e4ytt\u00e4\u00e4 forttia ilman ressua, voit lis\u00e4t\u00e4 pikku-a:n seuraavaan RESSU sanaan. Tarvitset kuitenkin SHA256:n (<a rel=\"noreferrer noopener\" target=\"_blank\" href=\"https:\/\/moijari.com\/?p=752\">https:\/\/moijari.com\/?p=752<\/a>) tiivisteiden laskentaan. Jos poistat ressun lis\u00e4ksi sis\u00e4iset tapahtumat, FORT_USE_RANDOM m\u00e4\u00e4ritykset ja save():n luoman fort.rnd tiedoston, on main() rutiinin tulostama salasana-merkkijono aina sama.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define RESSU 2\n#define DEBUG 2\n#define FORT_INTERNAL_EVENTS 2\nstatic unsigned int fort_internal_events = 1;\nstatic unsigned int fort_internal_event_mode = 1;\nstatic unsigned int fort_reseed_always = 1;\nstatic unsigned int fort_fill_pool_when_reseeding = 1;\n#define FORT_USE_URANDOM 2\n#define aFORT_USE_RANDOM 2\n\n#define aFORT_64_POOLS 2\n\n#ifdef FORT_64_POOLS\n#define FORT_POOLS 64\ntypedef unsigned long FORT_COUNTER;\n#else\n#define FORT_POOLS 32\ntypedef unsigned int FORT_COUNTER;\n#endif\n\nstatic unsigned char cvar&#91;16];\n\nstatic void inccvar()\n{\n  int c = 0;\n\n  \/* 16 bytes, LSB first *\/\n  while(++cvar&#91;c] == 0 &amp;&amp; c &lt; sizeof(cvar)-1)\n    c++;\n}\n\nstatic void clearcvar()\n{\n  int c;\n\n  for(c=0; c &lt; sizeof(cvar); c++)\n    cvar&#91;c] = 0;\n}\n\nstatic IUTIME gettenths()\n{\n  struct timeval tv;\n\n  gettimeofday(&amp;tv, NULL);\n\n  return((IUTIME)tv.tv_sec*10 +\n      (int)tv.tv_usec\/100000);\n}\n\nstatic IUTIME getmicroseconds()\n{\n  struct timeval tv;\n\n  gettimeofday(&amp;tv, NULL);\n\n  return((IUTIME)tv.tv_sec*1000000 +\n      tv.tv_usec);\n}\n\nstatic IUTIME getseconds()\n{\n  struct timeval tv;\n\n  gettimeofday(&amp;tv, NULL);\n\n  return((IUTIME)tv.tv_sec);\n}<\/code><\/pre>\n\n\n\n<p>N\u00e4m\u00e4 ovat edellisest\u00e4 postista (<a rel=\"noreferrer noopener\" target=\"_blank\" href=\"https:\/\/moijari.com\/?p=937\">https:\/\/moijari.com\/?p=937<\/a>) tuttuja satunnaistapahtumien muodostusrutiineja, joita k\u00e4ytet\u00e4\u00e4n haluttujen lohkojen alussa ja lopussa. Huomaa taas static sanat pool ja pool2 muuttujissa, Static sanalla muuttujan arvo saadaan s\u00e4ilym\u00e4\u00e4n funktion kutsukertojen v\u00e4lill\u00e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#ifdef FORT_INTERNAL_EVENTS\n#define FORT_INTERNAL_EVENTS_START(source) \\\n  IUTIME micros; \\\n  static int \\\n    pool=0, pool2=0; \\\n  if(fort_internal_events) { \\\n    fort_add_random_event_time(&amp;pool, \\\n    source, fort_internal_event_mode); \\\n    fort_add_random_event_timer_start(&amp;micros); \\\n  }\n#else\n#define FORT_INTERNAL_EVENTS_START(source)\n#endif\n\n#ifdef FORT_INTERNAL_EVENTS\n#define FORT_INTERNAL_EVENTS_END(source) \\\n  if(fort_internal_events) \\\n    fort_add_random_event_timer_do(&amp;pool2, \\\n      source, fort_internal_event_mode, \\\n      &amp;micros);\n#else\n#define FORT_INTERNAL_EVENTS_END(source)\n#endif\n<\/code><\/pre>\n\n\n\n<p>Seuraavassa satunnaistapahtumien luomiseen k\u00e4ytetyt kutsut: fort_add_random_event on p\u00e4\u00e4rutiini ja muut k\u00e4ytt\u00e4v\u00e4t sit\u00e4 varsinaisen tapahtuman tekemiseen.<\/p>\n\n\n\n<p>Luomisen yhteydess\u00e4 tapahtuvaan seuraavan satunnaistapahtumapuskurin valintaan on kaksi uutta toimintoa.  1 on perusvaihtoehto, jossa puskurin numeroa kasvatetaan aina yhdell\u00e4. 2 on vaihtoehto, joka pyrkii t\u00e4ytt\u00e4m\u00e4\u00e4n viimeksi k\u00e4ytetyt puskurit ensin. 3 ei tee puskurille mit\u00e4\u00e4n, kutsuja voi p\u00e4\u00e4tt\u00e4\u00e4 seuraavan puskurin itse. 4 valitsee satunnaisen puskurin seuraavaksi puskuriksi. 5 toimii siten ett\u00e4 jos k\u00e4sitell\u00e4\u00e4n puskuria 0 t\u00e4ytet\u00e4\u00e4n puskuri minimiin, muuten vaihdetaan seuraavaan puskuriin. 6 t\u00e4ytt\u00e4\u00e4 kohdalle osuvan vajaan puskurin minimiin ja jatkaa sitten seuraavaan puskuriin. N\u00e4ist\u00e4 5 ja 6 ovat uusia. Jos verrataan niit\u00e4 kakkoseen ne t\u00e4ytt\u00e4v\u00e4t enemm\u00e4n suuria puskureita,<\/p>\n\n\n\n<p>Fort_add_random_event_timer_start() ja fort_add_random_event_timer_do() tekev\u00e4t funktion tai lohkon suorittamisen kestosta ajan millisekunteina . Fort_add_random_event_time() tekee kellonajasta ajan millisekunteina. Molemmat l\u00e4hett\u00e4v\u00e4t fort_add_random_event() rutiinilla satunnaistapahtuman puskureihin. <\/p>\n\n\n\n<p>Fort_add_random_event_split() jakaa pidemm\u00e4n tapahtuman useampaan puskuriin.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>struct fort_pool {\n  unsigned long length;\n  HashCtx pool;\n};\nstatic struct fort_pool fort_pools&#91;FORT_POOLS];\n\n#define FORT_MIN_POOL_SIZE 64\n\n#ifdef DEBUG\nstatic int event_id = 0;\nstatic char fort_events_file&#91;128] =\n    \"fortevents.deb\";\n#endif\n\nvoid fort_add_random_event(int *pool, int source, int mode, int len, unsigned char *buf)\n{\n  while(len>1 &amp;&amp; buf&#91;len-1]==0)\n    len--;\n\n  HashUpdate(&amp;fort_pools&#91;*pool].pool, buf, len);\n  fort_pools&#91;*pool].length+=len;\n\n#ifdef DEBUG\n  if(event_id &lt; 65536) {\n    FILE *fp1;\n    if((fp1=fopen(fort_events_file, \"a\"))!=NULL) {\n      fprintf(fp1,\"id=%d\", event_id);\n      fprintf(fp1,\", source=%02d\", source);\n      fprintf(fp1,\", pool=%02d\", *pool);\n      fprintf(fp1,\", mode=%d\", mode);\n      fprintf(fp1,\", len=%d\", len);\n      fprintf(fp1,\", data=\");\n      for(int c=0;c&lt;len;c++)\n        fprintf(fp1,\"%02x\", buf&#91;c]);\n      fprintf(fp1,\"\\n\");\n      fflush(fp1);\n      fclose(fp1);\n      event_id++;\n    }\n  }\n#endif\n\n  switch(mode) {\n\n  case 1:\n    (*pool) = ((*pool)+1) % FORT_POOLS;\n    break;\n\n  case 2:\n    if((*pool) >= FORT_POOLS-1 ||\n        fort_pools&#91;*pool].length &lt;\n        fort_pools&#91;*pool+1].length)\n      (*pool) = 0;\n    else\n      (*pool) = ((*pool)+1) % FORT_POOLS;\n    break;\n\n  case 3:\n    break; \/\/ caller decides next pool                                                                                                                                                                                                                          \n\n  case 4:\n#ifdef RESSU\n    (*pool) = ressu_genbyte_limit(FORT_POOLS);\n#else\n    (*pool) = ((*pool)+1) % FORT_POOLS;\n#endif\n    break;\n\n  case 5:\n    if((*pool)==0 &amp;&amp; fort_pools&#91;*pool].length &lt;\n        FORT_MIN_POOL_SIZE)\n      (*pool) = 0;\n    else\n      (*pool) = ((*pool)+1) % FORT_POOLS;\n    break;\n\n  case 6:\n    if(fort_pools&#91;*pool].length >=\n        FORT_MIN_POOL_SIZE)\n      (*pool) = ((*pool)+1) % FORT_POOLS;\n    break;\n  }\n}\n\nvoid fort_add_random_event_timer_start(IUTIME *micros)\n{\n  *micros = getmicroseconds();\n}\n\nvoid fort_add_random_event_timer_do(int *pool, int source, int mode, IUTIME *micros)\n{\n  unsigned char temp&#91;2];\n  IUTIME t;\n\n  t = getmicroseconds()-*micros;\n  temp&#91;0] = t &amp; 0xff;\n  temp&#91;1] = (t>>8) &amp; 0xff;\n\n  fort_add_random_event(pool, source, mode,\n               sizeof(temp), temp);\n}\n\nvoid fort_add_random_event_time(int *pool, int source, int mode)\n{\n  int len;\n  unsigned char temp&#91;2];\n  IUTIME t;\n  static int prev_second_byte = -1;\n\n  t = getmicroseconds();\n  temp&#91;0] = t &amp; 0xff;\n  temp&#91;1] = (t>>8) &amp; 0xff;\n  len=2;\n\n  if(prev_second_byte == temp&#91;1]) {\n    len--;\n  } else {\n    prev_second_byte = temp&#91;1];\n  }\n\n#ifdef RESSUEVENT\n  ressu_genbuffer(len, temp);\n#endif\n\n  fort_add_random_event(pool, source, mode,\n\t       len, temp);\n}\n\nvoid fort_add_random_event_split(int *pool, int source, int mode, int len, unsigned char *buf, int size)\n{\n  int n;\n\n  while(len != 0) {\n    n = (size&lt;len)? size:len;\n    fort_add_random_event(pool, source,\n        mode, n, buf);\n    buf += n;\n    len -= n;\n  }\n}<\/code><\/pre>\n\n\n\n<p>Seuraavassa ensimm\u00e4iset satunnaisuutta ker\u00e4\u00e4v\u00e4t tapahtumat. N\u00e4ill\u00e4 muodostetaan SHA256 tiiviste halutusta merkkijonosta. Init funktio t\u00e4ytt\u00e4\u00e4 vain SHA256 yhteysalueen state[] ja count kent\u00e4t, ja sen tuottama kesto tapahtuma on yleens\u00e4 nolla. Update funktio tallettaa lyhyet alle 64 merkkiset merkkijonot yhteysalueen buffer muuttujaan ja siin\u00e4kin usein kestotapahtuma on l\u00e4hell\u00e4 nollaa. Kun puskuri t\u00e4yttyy, ajetaan transform ja se vie hiukan pidemm\u00e4n ajan (katso <a rel=\"noreferrer noopener\" target=\"_blank\" href=\"https:\/\/moijari.com\/?p=752\">https:\/\/moijari.com\/?p=752<\/a>). Final on samantapainen kun update, se ajaa lopuksi transformin ja siit\u00e4 tulee pidempi\u00e4 kestoja.<\/p>\n\n\n\n<p>Suoritusaikatapahtumissa n\u00e4iss\u00e4 kaikissa on satunnainen kellonaika (ainakin alimmat 8 bitti\u00e4), suoritusaikahan on mikrosekunteina.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>static void hash_init(HashCtx *hash)\n{\n  FORT_INTERNAL_EVENTS_START(10)\n\n  HashInit(hash);\n\n  FORT_INTERNAL_EVENTS_END(11)\n}\n\nstatic void hash_update(HashCtx *hash, unsigned char *data, int len)\n{\n  FORT_INTERNAL_EVENTS_START(12)\n\n  HashUpdate(hash, data, len);\n\n  FORT_INTERNAL_EVENTS_END(13)\n}\n\nstatic void hash_final(unsigned char digest&#91;HashLen], HashCtx *hash)\n{\n  FORT_INTERNAL_EVENTS_START(14)\n\n  HashFinal(digest, hash);\n\n  FORT_INTERNAL_EVENTS_END(15)\n}<\/code><\/pre>\n\n\n\n<p>Seuraavana fort_pseudo_random_data() funktio ja sen apufunktio fort_rekey(). Fort_rekey() funktiolla palautetaan k\u00e4ytt\u00e4j\u00e4n antamaan muistialueeseen (t\u00e4ss\u00e4 buf) satunnaisbittisarja. Fort_pseudo_random_data() k\u00e4ytt\u00e4\u00e4 rekeyt\u00e4 satunnaisbittien tekemiseen ja fort_key avaimen p\u00e4ivitt\u00e4miseen.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>static unsigned char fort_key&#91;HashLen];\n\nvoid fort_rekey(unsigned char *buf)\n{\n  HashCtx hash;\n\n  FORT_INTERNAL_EVENTS_START(16)\n\n  hash_init(&amp;hash);\n  hash_update(&amp;hash, fort_key, sizeof(fort_key));\n  hash_update(&amp;hash, (unsigned char *)&amp;cvar,\n    sizeof(cvar));\n  hash_final(buf, &amp;hash);\n  inccvar();\n\n  \/\/ Forget hash\n  memset(&amp;hash, 0, sizeof(hash));\n\n  FORT_INTERNAL_EVENTS_END(17)\n}\n\n#define FORT_PSEUDO_LIMIT 1048576\n\nvoid fort_pseudo_random_data(int len, \n    unsigned char *buf)\n{\n  unsigned char tmp&#91;HashLen];\n  unsigned int n, blockbytes;\n\n  FORT_INTERNAL_EVENTS_START(18)\n\n  blockbytes = 0;\n\n  while(len != 0) {\n    FORT_INTERNAL_EVENTS_START(19)\n\n    fort_rekey(tmp);\n    n = (len&lt;HashLen) ? len : HashLen;\n    memcpy(buf, tmp, n);\n    buf += n;\n    len -= n;\n    blockbytes += n;\n\n    \/\/ rekey every 1048576 bytes if data left\n    if(blockbytes >= FORT_PSEUDO_LIMIT &amp;&amp;\n        len > 0) {                                                                                                              \n      fort_rekey(fort_key);\n      blockbytes = 0;\n    }\n\n    FORT_INTERNAL_EVENTS_END(20)\n  }\n\n  fort_rekey(fort_key);\n\n  \/\/ Forget last bytes\n  memset(tmp, 0, sizeof(tmp));\n\n  FORT_INTERNAL_EVENTS_END(21)\n}<\/code><\/pre>\n\n\n\n<p>Fort_reseed laskee yhteistiivisteen edellisest\u00e4 fort_key:st\u00e4, cvar laskurista ja k\u00e4ytt\u00e4j\u00e4n antamasta merkkijonosta ja muodostaa niist\u00e4 uuden fort_key avaimen. Pohjana on t\u00e4ss\u00e4 edellinen fort_key avain, eli &#8220;uusi&#8221; satunnaisuus lis\u00e4t\u00e4\u00e4n edelliseen.<\/p>\n\n\n\n<p>Lis\u00e4ksi fort_reseed tekee fort_save():n aina kymmenen minuutin v\u00e4lein (FORT_SECONDS_BETWEEN_SAVES). Save tehd\u00e4\u00e4n vasta kun ohjelma suorittaa seuraavan kerran fort_reseed():i\u00e4.<\/p>\n\n\n\n<p>Reseed() kirjoittaa my\u00f6s raportin puskurien sis\u00e4lt\u00e4m\u00e4st\u00e4 merkkim\u00e4\u00e4r\u00e4st\u00e4 tiedostoon fortpools.rnd. My\u00f6hemp\u00e4n\u00e4 on mallituloste.<\/p>\n\n\n\n<p>Voit valita sek\u00e4 talletuksien ett\u00e4 raporttien v\u00e4lisen ajan sekunteina. Talletuksien v\u00e4li valitaan FORT_SECONDS_BETWEEN_SAVES muuttujalla ja raporttien v\u00e4li valitaan FORT_SECONDS_BETWEEN_POOLS_REPORTS:ll\u00e4. V\u00e4li kerrotaan sekunteina. &#8220;Takuulla&#8221; toimivista vaihtoehdoista on lista koodin kommentissa. Voit toki valita ajat miten haluat, mutta n\u00e4m\u00e4 tasatunteihin tai vuorokausiin perustuvat ajat ovat helpompia ymm\u00e4rt\u00e4\u00e4.<\/p>\n\n\n\n<p>Fort_random_data() tekee avainnuksen tarvittaessa uudestaan m\u00e4\u00e4ritellen fort_key:n (kutsumalla fort_reseed():i\u00e4). Muodostettavaan avaimeen k\u00e4ytet\u00e4\u00e4n fort_pools[] puskureihin talletettujen satunnaismerkkien tiivisteit\u00e4. Mahdollisen avainnuksen j\u00e4lkeen fort_random_data kutsuu fort_pseudo_random_data() rutiinia, joka palauttaa varsinaiset satunnaisbitit kutsujalle.<\/p>\n\n\n\n<p>Fort_random_data() funktiossa suurimmat erot suoritusaika tapahtumissa johtuvat siit\u00e4 ett\u00e4 ressu_genbuffer() palauttaa suurimman osan tapahtumista puskuristaan ja lopuille t\u00e4ytet\u00e4\u00e4n puskuri uudestaan, joka vie aikaa.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ choose one of                                                                                                                                                                       \n\/\/     60 (1 minute)                                                                                                                                                                   \n\/\/     300 (5 minutes)                                                                                                                                                                 \n\/\/     600 (10 minutes)                                                                                                                                                                \n\/\/     900 (15 minutes)                                                                                                                                                                \n\/\/     1200 (20 minutes)                                                                                                                                                               \n\/\/     1800 (30 minutes)                                                                                                                                                               \n\/\/     3600 (hour)                                                                                                                                                                     \n\/\/     7200 (2 hours)                                                                                                                                                                  \n\/\/     10800 (3 hours)                                                                                                                                                                 \n\/\/     14400 (4 hours)                                                                                                                                                                 \n\/\/     21600 (6 hours)                                                                                                                                                                 \n\/\/     28800 (8 hours)                                                                                                                                                                 \n\/\/     43200 (12 hours                                                                                                                                                                 \n\/\/     86400 (24 hours)                                                                                                                                                                \n\/\/ to get readable report..                                                                                                                                                            \n\n#define FORT_SECONDS_BETWEEN_SAVES 600\nstatic IUTIME fort_next_save = 0;\n\n#ifdef DEBUG\n#define FORT_SECONDS_BETWEEN_POOLS_REPORTS 3600\nstatic IUTIME fort_next_pools_report = 0;\n#define TIMEFORMAT \"%Z%Y%m%d%H%M%S\"\n#endif\n\nvoid dump_pools(char *header);\n\nstatic char current_timezone&#91;10];\n\nvoid fort_reseed(int len, unsigned char *buf)\n{\n  HashCtx hash;\n\n  FORT_INTERNAL_EVENTS_START(22)\n\n  hash_init(&amp;hash);\n  hash_update(&amp;hash, fort_key, sizeof(fort_key));\n  hash_update(&amp;hash, (unsigned char *)&amp;cvar,\n      sizeof(cvar));\n  hash_update(&amp;hash, buf, len);\n  hash_final(fort_key, &amp;hash);\n  inccvar();\n\n  memset(&amp;hash, 0, sizeof(hash));\n\n  if(fort_next_save != 0 ||\n     fort_next_pools_report != 0) {\n    IUTIME seconds;\n    seconds = getseconds();\n\n    char timezone&#91;10];\n    strftime(timezone, sizeof(timezone), \"%Z\",\n             localtime((time_t *)&amp;seconds) );\n    if(strcmp(current_timezone,timezone)) {\n      fort_next_save=1;\n      fort_next_pools_report=1;\n      strcpy(current_timezone,timezone);\n    }\n\n    if(fort_next_save != 0 &amp;&amp;\n       seconds >= fort_next_save) {\n\n      IUTIME diff=\n        timegm(localtime((time_t *)&amp;seconds))-\n          seconds;\n\n      fort_next_save = seconds -\n        ((seconds+diff) %\n         FORT_SECONDS_BETWEEN_SAVES) +\n        FORT_SECONDS_BETWEEN_SAVES;\n\n      fort_save();\n    }\n\n#ifdef DEBUG\n\n    if(fort_next_pools_report != 0 &amp;&amp;\n       seconds >= fort_next_pools_report) {\n\n      IUTIME diff=\n        timegm(localtime((time_t *)&amp;seconds))-\n          seconds;\n\n      char timebuf&#91;128];\n      strftime(timebuf, sizeof(timebuf), TIMEFORMAT,\n               localtime((time_t *)&amp;seconds));\n\n      fort_next_pools_report = seconds -\n        ((seconds+diff) %\n         FORT_SECONDS_BETWEEN_POOLS_REPORTS) +\n        FORT_SECONDS_BETWEEN_POOLS_REPORTS;\n\n      dump_pools(timebuf);\n    }\n#endif\n  }\n\n  FORT_INTERNAL_EVENTS_END(23)\n}\n\nstatic FORT_COUNTER fort_reseed_count = 0;\nstatic IUTIME fort_next_reseed = 0;\n\nvoid fort_random_data(int len, unsigned char *buf)\n{\n  int c;\n  IUTIME tenths;\n  HashCtx hash;\n  unsigned char buffer&#91;HashLen];\n\n  FORT_INTERNAL_EVENTS_START(24)\n\n  tenths=gettenths();\n\n  if( (fort_reseed_always == 1) ||\n      (fort_next_reseed == 0) ||\n      (fort_next_reseed &lt;= tenths &amp;&amp;\n      fort_pools&#91;0].length >=\n      FORT_MIN_POOL_SIZE) ) {\n\n    \/\/ next tenth of a second\n    fort_next_reseed = tenths + 1;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         \n    fort_reseed_count++;\n\n    hash_init(&amp;hash);\n    c=0;\n\n    while(c &lt; FORT_POOLS &amp;&amp; (fort_reseed_count\n        % (1&lt;&lt;c)) == 0) {\n\n      FORT_INTERNAL_EVENTS_START(25)\n\n      if(fort_fill_pool_when_reseeding==1 &amp;&amp;\n          fort_pools&#91;c].length &lt;\n          FORT_MIN_POOL_SIZE) {\n\n        unsigned char temp&#91;64];\n        int len = FORT_MIN_POOL_SIZE -\n            fort_pools&#91;c].length;\n        int n;\n\n        while(len != 0) {\n\n          FORT_INTERNAL_EVENTS_START(26)\n\n          n = (len &lt; sizeof(temp)) ? len :\n              sizeof(temp);\n          fort_pseudo_random_data(n, temp);\n#ifdef RESSU\n          ressu_genbuffer(n, temp);\n#endif\n          int pooltemp = c;\n          fort_add_random_event(&amp;pooltemp,\n              27, fort_internal_event_mode,\n              n, temp);\n          len-=n;\n\n          FORT_INTERNAL_EVENTS_END(28)\n        }\n        memset(temp, 0, sizeof(temp));\n      }\n      hash_final(buffer, &amp;fort_pools&#91;c].pool);\n      hash_update(&amp;hash, buffer, sizeof(buffer));\n      fort_pools&#91;c].length = 0;\n      HashInit(&amp;fort_pools&#91;c].pool);\n      \/\/ save earlier pool to new one\n      hash_update(&amp;fort_pools&#91;c].pool,\n          buffer, sizeof(buffer));                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       \n      c++;\n\n      FORT_INTERNAL_EVENTS_END(29)\n    }\n    hash_update(&amp;hash, (unsigned char *)\n        &amp;cvar, sizeof(cvar));\n    hash_final(buffer, &amp;hash);\n    fort_reseed(sizeof(buffer), buffer);\n    \/\/ Forget hash context\n    memset(&amp;hash, 0, sizeof(hash));\n    \/\/ Forget reseed key\n    memset(buffer, 0, sizeof(buffer));\n    inccvar();\n  }\n  fort_pseudo_random_data(len, buf);\n\n  FORT_INTERNAL_EVENTS_END(30)\n}<\/code><\/pre>\n\n\n\n<p>Seuraavana fortin aliohjelmia: alun muuttujat muodostavat puskurin joka t\u00e4ytet\u00e4\u00e4n uudestaan sen tyhjentyess\u00e4. Fort_random_data_byte() t\u00e4ytt\u00e4\u00e4 puskurin uudestaan sen tyhjentyess\u00e4 ja palauttaa seuraavan k\u00e4ytt\u00e4m\u00e4tt\u00f6m\u00e4n merkin. Fort_clear():illa voidaan tyhjent\u00e4\u00e4 puskuri, jolloin seuraavalla esimerkiksi fort_random_data_byte():ll\u00e4 se t\u00e4ytet\u00e4\u00e4n uudestaan. Fort_clear():ia voi k\u00e4ytt\u00e4\u00e4 kriittisten satunnaislukujen haun alussa ja lopussa, jolloin bitit ovat muistissa &#8220;n\u00e4kyviss\u00e4&#8221; vain minimiajan. Fort_random_data_byte_limit() palauttaa parametrin\u00e4 annettua rajaa (limit) pienemm\u00e4n satunnaisluvun. Fort_random_data_buffer() palauttaa puskurillisen satunnaisbittej\u00e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define FORTCNT 128\n\nstatic unsigned int fort_cnt = FORTCNT;\nstatic unsigned char fort_bytes&#91;FORTCNT];\nstatic int fort_byte = 999999999;\n\nint fort_random_data_byte()\n{\n  if(fort_byte >= fort_cnt) {\n    fort_random_data(fort_cnt, fort_bytes);\n    fort_byte = 0;\n  }\n  return(fort_bytes&#91;fort_byte++]);\n}\n\nvoid fort_clear()\n{\n  memset(fort_bytes, 0, fort_cnt);\n  fort_byte = 999999998;\n}\n\nint fort_random_data_byte_limit(int limit)\n{\n  int c;\n\n  while((c = fort_random_data_byte())>=\n      (256\/limit)*limit);\n  \/* while((c = fort_random_data_byte())>\n      (256\/limit)*limit); little bug *\/\n  return(c % limit);\n}\n\nvoid fort_random_data_buffer(int size,\n    unsigned char *buffer)\n{\n  int c;\n\n  for(c=0; c&lt;size; c++)\n    buffer&#91;c] ^= fort_random_data_byte();\n}<\/code><\/pre>\n\n\n\n<p>Fort_save() ja fort_restore() tallettavat ja lukevat takaisin fort generaattorin tilan. Fort_save tallettaa jonon fort_pseudo_random_data():lla luettuja merkkej\u00e4 fort.rnd tiedostoon. Fort_restore() lukee edellisell\u00e4 talletuksella kirjoitetut merkit ja tekee niill\u00e4 fort_reseed():in. Jos fort_restore() ei onnistu avaamaan tiedostoa, se generoi merkit fort_reseed():ille k\u00e4ytt\u00e4en ressu_genbuffer():ia.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define FORT_SAVE_SIZE 1024\nchar fort_random_file&#91;128] = \"fort.rnd\";\n\nvoid fort_save()\n{\n  FILE *fp1;\n  unsigned char buffer&#91;FORT_SAVE_SIZE];\n\n  if((fp1 = fopen(fort_random_file, \"w\"))\n      != NULL) {\n    fort_pseudo_random_data(sizeof(buffer), buffer);\n    fwrite(buffer, 1, sizeof(buffer), fp1);\n    memset(buffer, 0, sizeof(buffer));\n    fclose(fp1);\n  }\n}\n\nvoid fort_restore()\n{\n  int d;\n  FILE *fp1;\n  unsigned char buffer&#91;FORT_SAVE_SIZE];\n\n  if((fp1 = fopen(fort_random_file, \"rb\"))\n      != NULL) {\n    d = fread(buffer, 1, sizeof(buffer), fp1);\n    fclose(fp1);\n  } else {\n    fort_pseudo_random_data(sizeof(buffer), buffer);\n#ifdef RESSU\n    ressu_genbuffer(sizeof(buffer), buffer);\n#endif\n    d = sizeof(buffer);\n  }\n  fort_reseed(d, buffer);\n  memset(buffer, 0, sizeof(buffer));\n\n  fort_save();\n}<\/code><\/pre>\n\n\n\n<p>Seuraavaa fort_init rutiinia kutsutaan ohjelman main rutiinin alussa ressu_init() rutiinin j\u00e4lkeen. Fort_readfile_xor() on \/dev\/random:in ja \/dev\/urandom:in lukemista varten.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#if defined FORT_USE_URANDOM || \\\n    defined FORT_USE_RANDOM\n\nstatic void fort_readfile_xor(int len,\n    unsigned char *buf,\n    unsigned char *filename)\n{\n  int c, n;\n  unsigned char temp&#91;64];\n  FILE *fp1;\n\n  if((fp1 = fopen(filename, \"rb\"))\n      != NULL) {\n    while(len != 0) {\n      n = (len &lt; sizeof(temp)) ?\n          len : sizeof(temp);\n      fread(temp, 1, n, fp1);\n      for(c = 0; c &lt; n; c++)\n        buf&#91;c] ^= temp&#91;c];\n      len -= n;\n      buf += n;\n    }\n    fclose(fp1);\n  }\n}\n\n#endif\n\n#define aFORT_DUMP_POOLS_BIN 2\n\n#ifdef FORT_DUMP_POOLS_BIN\n#define FORT_DUMP_POOLS_HIGH 1023\n#define FORT_DUMP_POOLS_DIVIDER 1024\n#define FORT_DUMP_POOLS_FIELD_WIDTH 6\n#else\n#define FORT_DUMP_POOLS_HIGH 999\n#define FORT_DUMP_POOLS_DIVIDER 1000\n#define FORT_DUMP_POOLS_FIELD_WIDTH 5\n#endif\n\n#define FORT_DUMP_POOLS_WIDTH 32\n\nstatic void readable_length(char *buf,\n    unsigned long length)\n{\n  int c, low;\n\n  \/\/ B = byte\n  \/\/ K = kilo   10^3   2^10\n  \/\/ M = mega   10^6   2^20\n  \/\/ G = giga   10^9   2^30\n  \/\/ T = tera   10^12  2^40\n  \/\/ P = peta   10^15  2^50\n  \/\/ E = exa    10^18  2^60\n  \/\/ Z = zetta  10^21  2^70\n  \/\/ Y = yotta  10^24  2^80\n  char units&#91;] = \"BKMGTPEZY\";\n\n  strcpy(buf,\"***\");\n  low=0;\n\n  for(c=0; length>=low &amp;&amp;\n      c&lt;sizeof(units)-1; c++) {\n    if(length>=low &amp;&amp;\n        length&lt;=FORT_DUMP_POOLS_HIGH) {\n      if(units&#91;c]!='B')\n        sprintf(buf,\"%ld%c\", length, units&#91;c]);\n      else\n        sprintf(buf,\"%ld\", length);\n      break;\n    }\n    length\/=FORT_DUMP_POOLS_DIVIDER;\n    low=1;\n  }\n}\n\nvoid dump_pools(char *header)\n{\n  FILE *fp1;\n  unsigned char readable&#91;10];\n\n  if((fp1 = fopen(\"fortpools.deb\", \"a\"))\n      !=NULL) {\n    fprintf(fp1,\"%-25s\", header);\n    for(int c=0;c&lt;FORT_POOLS;c++) {\n      if(c>0 &amp;&amp; c%FORT_DUMP_POOLS_WIDTH==0)\n        fprintf(fp1,\"\\n%-25s\",\"\");\n      readable_length(readable,\n          fort_pools&#91;c].length);\n      fprintf(fp1,\"%*s\",\n              FORT_DUMP_POOLS_FIELD_WIDTH,\n              readable);\n    }\n    fprintf(fp1, \"\\n\");\n    fclose(fp1);\n  }\n}\n\nvoid fort_init()\n{\n  int c, pooltemp;\n\n  fprintf(stdout,\"Fort v0.491\");\n  fprintf(stdout,\", hash: %s\",\n      HashName);\n  fprintf(stdout,\", pools: %d*%ld\", FORT_POOLS,\n      sizeof(struct fort_pool));\n  fprintf(stdout,\", HashCtx: %ld\",\n      sizeof(HashCtx));\n  fprintf(stdout,\", hashsize: %d\",\n      HashLen);\n  fprintf(stdout,\"\\n\");\n\n  unsigned int save_fort_internal_events;\n  save_fort_internal_events=fort_internal_events;\n  fort_internal_events=1;\n\n  fort_next_save = 0;\n  clearcvar();\n\n  FILE *fp1;\n\n  if((fp1 = fopen(\"fortpools.deb\", \"w\"))!=NULL)\n    fclose(fp1);\n\n  dump_pools(\"Emptying pools report\");\n\n#ifdef RESSU\n  ressu_genbuffer(sizeof(fort_key), fort_key);\n  dump_pools(\"Generate fort key w ressu\");\n#endif\n\n  \/\/ Initialize buffers                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              \n  for(c=0; c&lt;FORT_POOLS; c++) {\n    fort_pools&#91;c].length = 0;\n    HashInit(&amp;fort_pools&#91;c].pool);\n  }\n\n  dump_pools(\"Initialize buffers\");\n\n#ifdef DEBUG\n  \/\/ Empty events file                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               \n  if((fp1 = fopen(fort_events_file, \"w\"))!=NULL)\n    fclose(fp1);\n  event_id = 0;\n\n  dump_pools(\"Emptying events\");\n\n#endif\n\n  unsigned char temp&#91;64];\n\n#ifdef FORT_USE_URANDOM\n  memset(temp, 0, sizeof(temp));\n  fort_readfile_xor(sizeof(temp), temp,\n      \"\/dev\/urandom\");\n  fort_reseed(sizeof(temp), temp);\n\n  dump_pools(\"Randomness from urandom\");\n#endif\n\n#ifdef FORT_USE_RANDOM\n  memset(temp, 0, sizeof(temp));\n  fort_readfile_xor(sizeof(temp), temp,\n      \"\/dev\/random\");\n  fort_reseed(sizeof(temp), temp);\n\n  dump_pools(\"Randomness from random\");\n#endif\n\n  for(c=0; c&lt;FORT_POOLS; c++) {\n    unsigned char buffer&#91;HashLen];\n    fort_pseudo_random_data(sizeof(buffer), buffer);\n#ifdef RESSU\n    ressu_genbuffer(sizeof(buffer), buffer);\n#endif\n    hash_update(&amp;fort_pools&#91;c].pool,\n      buffer, sizeof(buffer));\n  }\n  dump_pools(\"Initialize buffers 2\");\n\n  fort_pseudo_random_data(sizeof(temp), temp);\n#ifdef RESSU\n  ressu_genbuffer(sizeof(temp), temp);\n#endif\n  pooltemp = 0;\n  fort_add_random_event_split(&amp;pooltemp,\n      31, 2, sizeof(temp), temp, 1);\n\n  dump_pools(\"Fill first buffers\");\n\n#ifdef FORT_INTERNAL_EVENTS\n  if(fort_internal_events) {\n    \/\/ Create some internal events                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   \n    for(c=0; c&lt;64; c++)\n      fort_random_data(sizeof(temp), temp);\n  }\n  dump_pools(\"Internal events\");\n#endif\n\n  fort_reseed_count = 0;\n  fort_next_reseed = 0;\n\n  \/\/ Reseed fort_key with new events                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 \n  fort_random_data(sizeof(temp), temp);\n  fort_reseed(sizeof(temp), temp);\n\n  dump_pools(\"Reseed\");\n\n  fort_restore();\n\n  dump_pools(\"Restore\");\n\n  \/\/ Events to random pools                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          \n  fort_pseudo_random_data(sizeof(temp), temp);\n#ifdef RESSU\n  ressu_genbuffer(sizeof(temp), temp);\n#endif\n  pooltemp=0;\n  fort_add_random_event_split(&amp;pooltemp,\n      32, 4, sizeof(temp), temp, 1);\n\n  dump_pools(\"Events to random pools\");\n\n  \/\/ Fill first pool                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 \n  fort_pseudo_random_data(sizeof(temp), temp);\n#ifdef RESSU\n  ressu_genbuffer(sizeof(temp), temp);\n#endif\n  pooltemp=0;\n  fort_add_random_event(&amp;pooltemp,\n      33, 1, sizeof(temp), temp);\n\n  dump_pools(\"Fill 1st pool\");\n\n  \/\/ Forget temp                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     \n  memset(temp,0,sizeof(temp));\n\n  fort_internal_events = save_fort_internal_events;\n\n  fort_reseed_count = 0;\n  fort_next_reseed = 0;\n\n  fort_next_save = 1;\n  fort_next_pools_report = 1;\n}<\/code><\/pre>\n\n\n\n<p>T\u00e4ss\u00e4 tuloste dump_pools():in raportista (fortpools.deb tiedostosta): Raportti on tulostettu 26.7 kello 20:30 (ja 20:40) runsaasti satunnaislukuja tekev\u00e4ll\u00e4 ohjelmalla. Rivien alussa on aikavy\u00f6hyke, vuosi, kuukausi, p\u00e4iv\u00e4, tunnit, minuutit ja sekunnit. Loppurivi koostuu ohjelman puskurien ker\u00e4ttyjen merkkien m\u00e4\u00e4rist\u00e4. T\u00e4ss\u00e4 puskureita on 64. T\u00e4ll\u00e4 raportilla on kaksi rivi\u00e4, joiden v\u00e4li on t\u00e4ss\u00e4 10 minuuttia eli 600 sekuntia (FORT_SECONDS_BETWEEN_POOLS_REPORTS). Yksik\u00f6t ovat tarkemmin funktiossa readable_length(). Ker\u00e4ttyjen m\u00e4\u00e4rien yksik\u00f6t olevat yksik\u00f6t ovat kiloa(K), megaa(M) ja gigaa(G). Luvut ovat desimaaleja eli 1 kilo on 1000 merkki\u00e4, mega on 1000 kiloa ja giga on 1000 megaa. N\u00e4in ne mahtuvat v\u00e4lily\u00f6nteineen viiteen merkkiin, raportti olisi leve\u00e4mpi jos yksik\u00f6t olisivat bin\u00e4\u00e4risi\u00e4 eli 1024 merkki\u00e4 vastaa kiloa, 1024 kiloa vastaa megaa ja 1024 megaa vastaa gigaa. Oikeassa tulosteessa luku vie viisi merkki\u00e4, t\u00e4ss\u00e4 on n\u00e4k\u00f6j\u00e4\u00e4n 1 v\u00e4li + numerot + yksikk\u00f6 (=2-5 merkki\u00e4), eli luvut eiv\u00e4t ole oikeissa sarakkeissa. Rivin alussa olevia puskureita k\u00e4ytet\u00e4\u00e4n useimmin ja rivin lopussa olevia k\u00e4ytet\u00e4\u00e4n harvemmin, t\u00e4ss\u00e4 2G puskureita ei ole viel\u00e4 k\u00e4ytetty. Koska raporttirivi tulostetaan heti avainnuksen j\u00e4lkeen voidaan arvailla ett\u00e4 ensimm\u00e4isell\u00e4 raporttirivill\u00e4 on k\u00e4ytetty \u00e4skett\u00e4in puskuri 0 ja seuraavalla rivill\u00e4 on k\u00e4ytetty puskurit 0, 1 ja 2. Noiden puskurien ker\u00e4tty m\u00e4\u00e4r\u00e4 on nollattu \u00e4skett\u00e4in..<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>EEST20200726203000 3 145 141 136 136 121 121 121 427 426 419 2K 2K 2K 2K 2K 55K 162K 162K 162K 1M 2M 2M 9M 23M 23M 23M 23M 23M 23M 902M 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G\nEEST20200726204000 5 3 0 198 196 196 292 380 380 381 1K 2K 2K 2K 16K 43K 43K 43K 257K 686K 1M 1M 4M 11M 11M 39M 39M 39M 39M 39M 918M 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G 2G<\/code><\/pre>\n\n\n\n<p>T\u00e4ss\u00e4 viel\u00e4 toinen versio pools raportista, jossa on k\u00e4ytetty bin\u00e4\u00e4ri versiota tulosteesta (FORT_DUMP_POOLS_BIN): 1000 ja 1023:n v\u00e4liin osuvat pituudet ovat sen verran harvinaisia ettei t\u00e4h\u00e4nk\u00e4\u00e4n raporttiin osunut kuin yksi sellainen tapaus, 1002K rivin alkupuolella.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>EEST20200802123000 72 74 75 232 232 290 330 412 627 1K 1K 1K 1K 7K 7K 7K 59K 164K 164K 164K 1002K 2M 2M 9M 22M 48M 100M 100M 100M 100M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M 938M<\/code><\/pre>\n\n\n\n<p>Viel\u00e4 pieni p\u00e4\u00e4ohjelma joka tekee fortilla salasanoiksi sopivaa merkkijonoa: ohjelmassa on malli fort_clear():in k\u00e4yt\u00f6st\u00e4, sek\u00e4 satunnaistapahtumien luomisesta. Ensin kuitenkin uudet makrot satunnaistapahtumien lis\u00e4\u00e4miselle asiakasohjelmaan:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define FORT_EVENTS 2\nstatic unsigned int fort_events = 1;\nstatic unsigned int fort_event_mode = 6;\n\n#ifdef FORT_EVENTS\n#define FORT_EVENTS_START(source) \\\n  IUTIME micros; \\\n  static int \\\n    pool=0, pool2=0; \\\n  if(fort_events) { \\\n    fort_add_random_event_time(&amp;pool, \\\n    source, fort_event_mode); \\\n    fort_add_random_event_timer_start(&amp;micros); \\\n  }\n#else\n#define FORT_EVENTS_START(source)\n#endif\n\n#ifdef FORT_EVENTS\n#define FORT_EVENTS_END(source) \\\n  if(fort_events) \\\n    fort_add_random_event_timer_do(&amp;pool2, \\\n\tsource, fort_event_mode, &amp;micros);\n#else\n#define FORT_EVENTS_END(source)\n#endif<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>int main(int argc, char *argv&#91;])\n{\n#ifdef RESSU\n  ressu_init();\n#endif\n  fort_init();\n\n  dump_pools(\"To main\");\n\n  unsigned char chars&#91;] =\n    \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" \\\n    \"abcdefghijklmnopqrstuvwxyz\" \\\n    \"0123456789\";\n\n  fort_clear();\n  for(int c=0; c&lt;1024; c++) {\n    FORT_EVENTS_START(100)\n    \n    if(c>0 &amp;&amp; c%128 == 0)\n      fprintf(stdout, \"\\n\");\n    int byte=fort_random_data_byte_limit(\n        sizeof(chars)-1);\n    fprintf(stdout,\"%c\", chars&#91;byte]);\n\n    FORT_EVENTS_END(101)\n  }\n  fort_clear();\n  fprintf(stdout, \"\\n\");\n  fflush(stdout);\n\n  dump_pools(\"End of main\");\n\n  fort_save();\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Fortin edellisest\u00e4 versiosta (https:\/\/moijari.com\/?p=634) on kulunut jo jonkin verran aikaa ja uudessa versiossa on muutoksia, joten ajattelin postata uuden version. Oikeastaan varsinaisessa koodissa ei ole paljon muutoksia, ainoastaan nuo lohkon alun (FORT_INTERNAL_EVENTS_START) ja lopun (FORT_INTERNAL_EVENTS_END) makrot. Funktioiden esittelyt ovat muuttuneet siten, ett\u00e4 t\u00e4m\u00e4n tiedoston (fort.c) sis\u00e4isiin apufunktioihin on lis\u00e4tty static sana, joka est\u00e4\u00e4 funktioiden k\u00e4yt\u00f6n&hellip; <a class=\"more-link\" href=\"https:\/\/moijari.com\/?p=964\">Continue reading <span class=\"screen-reader-text\">FORT v0.4 uusi versio<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[11],"tags":[],"_links":{"self":[{"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts\/964"}],"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=964"}],"version-history":[{"count":257,"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts\/964\/revisions"}],"predecessor-version":[{"id":1251,"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts\/964\/revisions\/1251"}],"wp:attachment":[{"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=964"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=964"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=964"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}