{"id":634,"date":"2020-06-06T15:01:17","date_gmt":"2020-06-06T13:01:17","guid":{"rendered":"https:\/\/moijari.com\/?p=634"},"modified":"2020-07-11T14:29:13","modified_gmt":"2020-07-11T12:29:13","slug":"fort-fortunan-kaltainen-satunnaisbittigeneraattori","status":"publish","type":"post","link":"https:\/\/moijari.com\/?p=634","title":{"rendered":"Fort, Fortunan kaltainen satunnaisbittigeneraattori"},"content":{"rendered":"\n<p>Fort:in p\u00e4\u00e4rakenne tallettaa satunnaisbittigeneraattorin l\u00e4hteet (pool), joihin satunnaisuutta lis\u00e4t\u00e4\u00e4n ja joiden pohjalta sit\u00e4 generoidaan. L\u00e4hteit\u00e4 on 32 kappaletta ja niiden muistirakenne sis\u00e4lt\u00e4\u00e4 satunnaismerkkien lukum\u00e4\u00e4r\u00e4n l\u00e4hteess\u00e4 ja hash toiminnon yhteysalueen (HashCtx).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>struct fort_pool {\n  int length;\n  HashCtx pool;\n};\nstruct fort_pool fort_pools&#91;32];<\/code><\/pre>\n\n\n\n<p>Merkkien lukum\u00e4\u00e4r\u00e4\u00e4 ensimm\u00e4isess\u00e4 poolissa (0) k\u00e4ytet\u00e4\u00e4n sen selvitt\u00e4miseksi onko l\u00e4hteiss\u00e4 tarpeeksi satunnaisuutta seuraavaa avainnusta varten. L\u00e4hteen (tai puskurin) HashCtx yhteysalueeseen lis\u00e4t\u00e4\u00e4n uusi ohjelmalle annettu satunnaisuus HashUpdate toiminnolla.<\/p>\n\n\n\n<p>Satunnaisuus lis\u00e4t\u00e4\u00e4n tapahtumilla, joita lis\u00e4\u00e4v\u00e4 p\u00e4\u00e4funktio on fort_add_random_event. Funktio lis\u00e4\u00e4 tapahtuman pool muuttujalla kerrottuun l\u00e4hteeseen, satunnaisuuden ohjelmal\u00e4hde kerrotaan source muuttujalla, seuraavan puskurin numeron laskentatapa kerrotaan muuttujalla mode ja satunnaismerkkien m\u00e4\u00e4r\u00e4 merkkein\u00e4 on kent\u00e4ss\u00e4 len ja varsinaiset satunnaismerkit ovat buf osoitteen osoittamassa puskurissa.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>char fort_events_file&#91;128] = \"fortevents.deb\";\nint dump_events=0;\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  if(dump_events&lt;4*1048576) {\n    FILE *fp1;\n    if((fp1=fopen(fort_events_file,\"a\"))!=NULL) {\n      fprintf(fp1,\"id=%d\",dump_events);\n      fprintf(fp1,\", source=%d\",source);\n      fprintf(fp1,\", pool=%d\",*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      dump_events++;\n    }\n  }\n\n  switch(mode) {\n  case 1:\n    (*pool)=((*pool)+1)%32;\n    break;\n  case 2:\n    if((*pool)>=31 || fort_pools&#91;*pool].length &lt;\n      fort_pools&#91;*pool+1].length)\n      (*pool)=0;\n    else\n      (*pool)=((*pool)+1)%32;\n    break;\n  case 3:\n    break; \/\/ caller decides next pool                                                                                    \n  case 4:\n#ifdef RESSU\n    (*pool)=ressu_genbyte_limit(32);\n#endif\n    break;\n  }\n}<\/code><\/pre>\n\n\n\n<p>Funktiossa satunnaisuus lis\u00e4t\u00e4\u00e4n satunnaislukul\u00e4hteeseen HashUpdate funktiolla, lasketaan satunnaismerkkien lukum\u00e4\u00e4r\u00e4\u00e4, tehd\u00e4\u00e4n ensimm\u00e4isist\u00e4 satunnaislukutapahtumista listaa ja mode-kent\u00e4n mukaan lasketaan seuraavan k\u00e4ytett\u00e4v\u00e4n satunnaislukul\u00e4hteen numero.<\/p>\n\n\n\n<p>Ensimm\u00e4iset tapahtumat (4*1048576=4M tapahtumaa) raportoidaan fort_events_file kent\u00e4n sis\u00e4lt\u00e4m\u00e4\u00e4n tiedostoon.<\/p>\n\n\n\n<p>Mode voi saada arvot yhdest\u00e4 nelj\u00e4\u00e4n: <br>        1:s moodilla satunnaislukul\u00e4hdett\u00e4 kasvatetaan aina yhdell\u00e4. Kun p\u00e4\u00e4st\u00e4\u00e4n l\u00e4hteeseen 32 l\u00e4hteiden kierto aloitetaan alusta siirtym\u00e4ll\u00e4 takaisin l\u00e4hteeseen nolla<br>        2:s moodilla t\u00e4ytet\u00e4\u00e4n numeroltaan pienimpi\u00e4 satunnaislukul\u00e4hteist\u00e4 nopeasti, eli t\u00e4ytet\u00e4\u00e4n ne, jotka on viimeisess\u00e4 uudelleen avainnuksessa k\u00e4ytetty<br>        3:s moodi ei tee pool muuttujalle mit\u00e4\u00e4n, kutsujan odotetaan p\u00e4\u00e4ttelev\u00e4n seuraavan satunnaislukul\u00e4hteen<br>        4:s seuraava satunnaislukul\u00e4hde on satunnainen v\u00e4lill\u00e4 0-31.<\/p>\n\n\n\n<p>ressu_genbyte_limit() on aiemmassa postissa. <\/p>\n\n\n\n<p>Fortevents.deb tiedostoon raportoidaan seuraavankaltaisia tietueita: tietueissa on tietueen j\u00e4rjestysnumero ja kenttien arvot add event kutsusta. Tiedostosta voi esimerkiksi grep:ll\u00e4 poimia tietyn l\u00e4hteen rivej\u00e4 ja katsoa niist\u00e4 miten niiden data-arvot vaihtelevat (grep source=23 fortevents.deb), eli sis\u00e4lt\u00e4v\u00e4tk\u00f6 rivit todella ja riitt\u00e4v\u00e4sti satunnaisuutta.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>id=0, source=100, pool=4, mode=3, len=2, data=b4f4\nid=1, source=22, pool=4, mode=2, len=2, data=d6f4\nid=2, source=10, pool=5, mode=2, len=2, data=e9f4\nid=3, source=11, pool=30, mode=2, len=2, data=0000\nid=4, source=23, pool=6, mode=2, len=2, data=0ff5\nid=5, source=14, pool=7, mode=2, len=2, data=16f5\nid=6, source=15, pool=6, mode=2, len=2, data=0200\nid=7, source=12, pool=8, mode=2, len=2, data=26f5\nid=8, source=13, pool=17, mode=2, len=2, data=0000\nid=9, source=10, pool=9, mode=2, len=2, data=33f5\nid=10, source=11, pool=31, mode=2, len=2, data=0000\nid=11, source=12, pool=10, mode=2, len=2, data=41f5\nid=12, source=13, pool=18, mode=2, len=2, data=0000\nid=13, source=26, pool=0, mode=2, len=2, data=4a00\nid=14, source=12, pool=11, mode=2, len=2, data=66f5\nid=15, source=13, pool=19, mode=2, len=2, data=0000<\/code><\/pre>\n\n\n\n<p>N\u00e4m\u00e4 rivit ovat sis\u00e4isist\u00e4 l\u00e4hteist\u00e4 tulevia satunnaisbittej\u00e4, niiss\u00e4 source kent\u00e4n arvo on v\u00e4lill\u00e4 10-27. Sis\u00e4isiss\u00e4 l\u00e4hteiss\u00e4 on kahta eri mallia, ensimm\u00e4isess\u00e4 data on suoritushetken kellonajan mikrosekuntien  16 alinta bitti\u00e4 (fort_add_random_event_time) ja toisessa mallissa satunnaisuus tulee funktion suoritusajan eli keston alimmista 16 bitist\u00e4 (fort_add_random_event_timer_star ja fort_add_random_event_timer_do).<\/p>\n\n\n\n<p>Jos ohjelmasi l\u00e4hett\u00e4\u00e4 riitt\u00e4v\u00e4sti satunnaistapahtumia, voit halutessasi poistaa sis\u00e4iset l\u00e4hteet fort:ista poistamalla #define FORT_INTERNAL_EVENTS m\u00e4\u00e4rityksen. Alkuper\u00e4isen Fortunan kuvauksessa ei ole sis\u00e4isi\u00e4 l\u00e4hteit\u00e4. Ilman ohjelmasi satunnaisuustapahtumia fort tarvitsee joko ressun tai sis\u00e4iset tapahtumat mieluummin molemmat, ett\u00e4 sen tuottamat satunnaisbitit ovat luotettavia.<\/p>\n\n\n\n<p>Satunnaistapahtumien lis\u00e4\u00e4miseen on my\u00f6s seuraavat apufunktiot, joilla voidaan mitata esimerkiksi funktion suoritusaika mikrosekunteina, ja k\u00e4ytt\u00e4\u00e4 siit\u00e4 alimmat 16 bitti\u00e4 satunnaisuusl\u00e4hteen\u00e4:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void fort_add_random_event_timer_start(unsigned long *micros)\n{\n  *micros=getmicroseconds();\n}\n\nvoid fort_add_random_event_timer_do(int *pool, int source, int mode, unsigned long *micros)\n{\n  unsigned char temp&#91;2];\n  unsigned long l;\n\n  l=getmicroseconds()-*micros;\n  temp&#91;0] = l &amp; 0xff;                                                                                                                           \n  temp&#91;1] = l>>8 &amp; 0xff;                                                                                                                                 \n                                                                                                                                                         \n  fort_add_random_event(pool, source, mode,\n               sizeof(temp), temp);                                                                                         \n}<\/code><\/pre>\n\n\n\n<p>T\u00e4ll\u00e4 tehd\u00e4\u00e4n kutsumispisteen kellonajasta 16 bittinen satunnaislukutapahtuma. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void fort_add_random_event_time(int *pool, int source, int mode)\n{\n  unsigned char temp&#91;2];\n  unsigned long l;\n\n  l=getmicroseconds();\n  temp&#91;0] = l &amp; 0xff;\n  temp&#91;1] = l>>8 &amp; 0xff;\n\n#ifdef RESSUEVENT\n  ressu_genbuffer(sizeof(temp),temp);\n#endif\n                                                                                                                                 \n  fort_add_random_event(pool, source, mode,\n               sizeof(temp), temp);\n}\n<\/code><\/pre>\n\n\n\n<p>T\u00e4ll\u00e4 funktiolla jaetaan pidempi satunnaismerkkijono useampaan puskuriin:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void fort_add_random_event_split(int *pool,\n  int source, int mode, int len,\n  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>Edellisten apufunktio:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>unsigned long getmicroseconds()\n{\n  struct timeval tv;\n\n  gettimeofday(&amp;tv, NULL);\n\n  return((unsigned long)tv.tv_sec*1000000 +\n          tv.tv_usec);\n}<\/code><\/pre>\n\n\n\n<p>Seuraava funktio muodostaa uuden fort_key avaimen edellisest\u00e4 fort_key avaimesta, juoksevasta 16 merkkisest\u00e4 numerosarjasta cvar ja tallettaa sen parametrina annettuun puskuriin (buf). Lis\u00e4ksi kasvatetaan cvar numerosarjaa (inccvar). Fort_rekey funktiota k\u00e4ytet\u00e4\u00e4n my\u00f6s satunnaisbittien tekemiseen. Funktion alussa ja lopussa on satunnaistapahtumakutsut tapahtuman muodostukselle kellon ajasta (fort_add_random_event_time) ja funktion suorituksen kestosta (fort_add_random_event_timer_start ja fort_add_random_event_timer_do). time_pool ja rekey_pool muuttujissa talletetaan seuraavan satunnaisuuspuskurin numero kellonaikatapahtumille ja suoritusaikatapahtumille. Micros muuttujan avulla lasketaan funktion suorituksen kesto. Add random funktioiden toinen kentt\u00e4 kertoo l\u00e4hteen eli source kent\u00e4n tapahtumatiedostossa. T\u00e4ss\u00e4 kellonaika tapahtuman source on 16 ja suoritusaika tapahtuman source on 17.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define FORT_INTERNAL_EVENTS 1\nint fort_internal_events=1;\nunsigned int fort_event_mode = 2;\nunsigned char fort_key&#91;HashLen];\nunsigned char cvar&#91;16];\nint time_pool=0;\nint rekey_pool=0;\n\nvoid fort_rekey(char *buf)\n{\n  HashCtx hash;\n#ifdef FORT_INTERNAL_EVENTS\n  unsigned long micros;\n  if(fort_internal_events) {\n    fort_add_random_event_time(&amp;time_pool,\n         16, fort_event_mode);\n    fort_add_random_event_timer_start(&amp;micros);\n  }\n#endif\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#ifdef FORT_INTERNAL_EVENTS\n  if(fort_internal_events)\n    fort_add_random_event_timer_do(&amp;rekey_pool,\n        17, fort_event_mode, &amp;micros);\n#endif\n}\n<\/code><\/pre>\n\n\n\n<p>Edellisen apufunktiot:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>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\nvoid clearcvar()\n{\n  int c;\n\n  for(c=0; c&lt;sizeof(cvar); c++)\n    cvar&#91;c]=0;\n}<\/code><\/pre>\n\n\n\n<p>cvar on 16 merkki\u00e4 pitk\u00e4 muuttuja ja aina sit\u00e4 k\u00e4ytett\u00e4ess\u00e4 siihen lis\u00e4t\u00e4\u00e4n yksi.<\/p>\n\n\n\n<p>Seuraavalla funktiolla muodostetaan kutsujan toimittamaan puskuriin buf len merkki\u00e4 pitk\u00e4 satunnaisbittisarja. Funktion alussa ja lopussa ovat standardit satunnaistapahtumien muodostuskutsut aika ja kesto tapahtumille. T\u00e4m\u00e4n funktion antamia satunnaisbittej\u00e4 p\u00e4\u00e4set katsomaan &gt;grep source=18 fortevents.deb ja &gt;grep source=19 fortevents.deb komennoilla.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define FORT_PSEUDO_LIMIT 1048576\nint pseudo_pool=0;\n\nvoid fort_pseudo_random_data(int len, unsigned char *buf)\n{\n  unsigned char tmp&#91;HashLen];\n  unsigned int n,blockbytes;\n#ifdef FORT_INTERNAL_EVENTS\n  unsigned long micros;\n  if(fort_internal_events) {\n    fort_add_random_event_time(&amp;time_pool,\n        18, fort_event_mode);\n    fort_add_random_event_timer_start(&amp;micros);\n  }\n#endif\n\n  blockbytes=0;\n\n  while(len!=0) {\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     \/\/ 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\n  fort_rekey(fort_key);\n\n  \/* Forget last bytes *\/\n  memset(tmp, 0, sizeof(tmp));\n\n#ifdef FORT_INTERNAL_EVENTS\n  if(fort_internal_events)\n    fort_add_random_event_timer_do(&amp;pseudo_pool,\n        19, fort_event_mode, &amp;micros);\n#endif\n}<\/code><\/pre>\n\n\n\n<p>Ohjelma muodostaa satunnaisbitit kutsumalla fort_rekey funktiota ja kopioimalla sen antamat bitit asiakkaan puskuriin ja toistamalla t\u00e4t\u00e4 kunnes kaikki tarvittavat bitit on luotu. Funktio tekee uuden fort_key:n aina 1048576 merkin j\u00e4lkeen. Se tehd\u00e4\u00e4n my\u00f6s samalla fort_rekey funktiolla. Suorituksen lopuksi uusitaan viel\u00e4 fort_key samalla fort_rekey funktiolla.<\/p>\n\n\n\n<p>Fort reseed funktiolla muodostetaan uusi fort_key avain asiakkaan len pituisesta buf bittijonosta. Avaimeen k\u00e4ytet\u00e4\u00e4n vanhaa fort_key:t\u00e4, cvaria ja asiakkaan bittijonoa. time_pool on m\u00e4\u00e4ritelty aiemmin. Lis\u00e4ksi kasvatetaan cvaria. Fort_reseedill\u00e4 ei voi t\u00e4ss\u00e4 saada aikaiseksi samoja satunnaisbittej\u00e4 uudestaan, kuten alkuper\u00e4isess\u00e4 fortuna dokumentaatiossa. Periaatteessa ominaisuuden voi toteuttaa poistamalla fort_key:n ja cvar:in HashUpdate:t koodista.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int reseed_pool=0;\n\nvoid fort_reseed(int len, unsigned char *buf)\n{\n  HashCtx hash;\n#ifdef FORT_INTERNAL_EVENTS\n  unsigned long micros;\n  if(fort_internal_events) {\n    fort_add_random_event_time(&amp;time_pool,\n        20, fort_event_mode);\n    fort_add_random_event_timer_start(&amp;micros);\n  }\n#endif\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#ifdef FORT_INTERNAL_EVENTS\n  if(fort_internal_events)\n    fort_add_random_event_timer_do(&amp;reseed_pool,\n        21, fort_event_mode, &amp;micros);\n#endif\n}<\/code><\/pre>\n\n\n\n<p>Seuraavalla funktiolla muodostetaan satunnaisbittej\u00e4. Erona fort_pseudo_random_data funktioon on ett\u00e4 tarvittaessa vaihdetaan fort_key avainta. Itseasiassa varsinaiset satunnaisbitit muodostetaan fort_key avaimen muodostuksen j\u00e4lkeen aiemmalla fort_pseudo_random_data funktiolla.<\/p>\n\n\n\n<p>Aliohjelman ensimm\u00e4isess\u00e4 varsinaisessa iffiss\u00e4 p\u00e4\u00e4tell\u00e4\u00e4n tehd\u00e4\u00e4nk\u00f6 avaimen muodostus t\u00e4ll\u00e4 kutsulla. Muodostus tehd\u00e4\u00e4n, jos halutaan tehd\u00e4 avainnus jokaisella ajokerralla (fort_reseed_always==1), tai jos on ensimm\u00e4inen kutsukerta (fort_next_reseed==0) tai edellisest\u00e4 avainnuksesta on kulunut sekunnin kymmennys (tenth) ja ensimm\u00e4inen puskuri on t\u00e4ynn\u00e4 (64 merkki\u00e4 satunnaisuutta).<\/p>\n\n\n\n<p>Jos avainnus tehd\u00e4\u00e4n, c muuttujaa k\u00e4ytt\u00e4v\u00e4ss\u00e4 luupissa k\u00e4yd\u00e4\u00e4n asiaankuuluvat puskurit l\u00e4pi. Jos (fort_fill_pool_when_reseeding==1) lippu on p\u00e4\u00e4ll\u00e4 ja puskuri ei ole t\u00e4ynn\u00e4 t\u00e4ytet\u00e4\u00e4n puskuri merkeill\u00e4 ressu_genbuffer rutiinista. Kaikkien asiaan kuuluvien puskurien sis\u00e4lt\u00f6 ker\u00e4t\u00e4\u00e4n hash-nimiseen tilamuuttujaan (hash_update) ja nollataan k\u00e4ytettyjen puskurien pituus (length) muuttuja. K\u00e4ytetyn puskurin hash tyhjennet\u00e4\u00e4n (hash_init) ja sen arvoksi asetetaan puskurin edellinen hash (hash_update). Kaikkien valittujen puskurien hash:ill\u00e4 (hash_final) p\u00e4ivitet\u00e4\u00e4n fort_reseed():ll\u00e4 fort_key:n uudeksi arvoksi.<\/p>\n\n\n\n<p>Puskureita k\u00e4ytet\u00e4\u00e4n puskurista 0 l\u00e4htien siten ett\u00e4 puskuria nolla k\u00e4ytet\u00e4\u00e4n jokaisessa avaimen muodostuksessa, puskuria yksi k\u00e4ytet\u00e4\u00e4n joka toisessa avaimen muodostuksessa, puskuria kaksi k\u00e4ytet\u00e4\u00e4n joka nelj\u00e4nness\u00e4 avaimen muodostuksessa, puskuria kolme k\u00e4ytet\u00e4\u00e4n joka kahdeksanneksessa avaimen muodostuksessa: rivin ensimm\u00e4inen numero on fort_reseed_count ja sen j\u00e4lkeen ovat puskurin numerot:<\/p>\n\n\n\n<p> 01 0<br> 02 0 1<br> 03 0<br> 04 0 1 2<br> 05 0<br> 06 0 1<br> 07 0<br> 08 0 1 2 3<br> 09 0<br> 10 0 1<br> 11 0<br> 12 0 1 2<br> 13 0<br> 14 0 1<br> 15 0<br> 16 0 1 2 3 4<\/p>\n\n\n\n<p>Eli puskuria 4 k\u00e4ytet\u00e4\u00e4n joka kuudennessatoista kierroksessa. T\u00e4ss\u00e4 viel\u00e4 viimeiset kierrokset ennen kun laskuri menee ymp\u00e4ri:<\/p>\n\n\n\n<p> 4294967278 0 1<br> 4294967279 0<br> 4294967280 0 1 2 3 4<br> 4294967281 0<br> 4294967282 0 1<br> 4294967283 0<br> 4294967284 0 1 2<br> 4294967285 0<br> 4294967286 0 1<br> 4294967287 0<br> 4294967288 0 1 2 3<br> 4294967289 0<br> 4294967290 0 1<br> 4294967291 0<br> 4294967292 0 1 2<br> 4294967293 0<br> 4294967294 0 1<br> 4294967295 0<br> 00 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19<br>        20 21 22 23 24 25 26 27 28 29 30 31<br> 01 0<br> 02 0 1<br> 03 0<\/p>\n\n\n\n<p>Viel\u00e4 lista kierroksista, joilla puskuria k\u00e4ytet\u00e4\u00e4n ensimm\u00e4isen kerran. Esimerkiksi puskuria 6 k\u00e4ytet\u00e4\u00e4n ensimm\u00e4isen kerran kierroksella 64.<\/p>\n\n\n\n<p>02 0 1<br> 04 0 1 2<br> 08 0 1 2 3<br> 16 0 1 2 3 4<br> 32 0 1 2 3 4 5<br> 64 0 1 2 3 4 5 6<br> 128 0 1 2 3 4 5 6 7<br> 256 0 1 2 3 4 5 6 7 8<br> 512 0 1 2 3 4 5 6 7 8 9<br> 1024 0 1 2 3 4 5 6 7 8 9 10<br> 2048 0 1 2 3 4 5 6 7 8 9 10 11<br> 4096 0 1 2 3 4 5 6 7 8 9 10 11 12<br> 8192 0 1 2 3 4 5 6 7 8 9 10 11 12 13<br> 16384 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14<br> 32768 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15<br> 65536 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16<br> 131072 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17<br> 262144 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18<br> 524288 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19<br> 1048576 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20<br> 2097152 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21<br> 4194304 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22<br> 8388608 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23<br> 16777216 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24<br> 33554432 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25<\/p>\n\n\n\n<p>Puskureita k\u00e4ytet\u00e4\u00e4n aina tietty m\u00e4\u00e4r\u00e4 nollapuskurista yl\u00f6sp\u00e4in, ja k\u00e4yt\u00f6n j\u00e4lkeen ne t\u00e4yttyv\u00e4t nopeimmin fort_add_random_event funktion modella 2.<\/p>\n\n\n\n<p>Ja viel\u00e4 varsinainen fort_random_data funktion koodi:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define FORT_MIN_POOL_SIZE 64\nunsigned int fort_reseed_always=1;\nunsigned int fort_fill_pool_when_reseeding=1;\nunsigned int fort_reseed_count=0;\nunsigned long fort_next_reseed=0;\n\nint random_pool=0;\n\nvoid fort_random_data(int len, unsigned char *buf)\n{\n  int c;\n  unsigned long tenths;\n  HashCtx hash;\n  unsigned char buffer&#91;HashLen];\n#ifdef FORT_INTERNAL_EVENTS\n  unsigned long micros;\n  if(fort_internal_events) {\n    fort_add_random_event_time(&amp;time_pool,\n        22, fort_event_mode);\n    fort_add_random_event_timer_start(&amp;micros);\n  }\n#endif\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    hash_init(&amp;hash);\n    c=0;\n\n    while(c &lt; 32 &amp;&amp;\n        (fort_reseed_count % (1&lt;&lt;c))==0) {\n#ifdef FORT_INTERNAL_EVENTS\n      unsigned long micros;\n      if(fort_internal_events) {\n        fort_add_random_event_time(&amp;time_pool,\n            23, fort_event_mode);\n        fort_add_random_event_timer_start(\n            &amp;micros);\n      } \/\/ if(fort_internal_events)\n#endif\n#ifdef RESSU\n      if(fort_fill_pool_when_reseeding==1 &amp;&amp;\n         fort_pools&#91;c].length&lt;\n              FORT_MIN_POOL_SIZE) {\n        unsigned char tmp32&#91;32];\n        int len=FORT_MIN_POOL_SIZE -\n            fort_pools&#91;c].length;\n        int n;\n\n        while(len>0) {\n#ifdef FORT_INTERNAL_EVENTS\n          unsigned long micros;\n          if(fort_internal_events) {\n            fort_add_random_event_time(\n                &amp;time_pool, 24,\n                fort_event_mode);\n            fort_add_random_event_timer_start(&amp;micros);\n          } \/\/ if(fort_internal_events)\n#endif\n          n=(len&lt;sizeof(tmp32)) ?\n              len : sizeof(tmp32);\n          memset(tmp32, 0, sizeof(tmp32));\n          ressu_genbuffer(n, tmp32);\n          int pool2=c;\n          fort_add_random_event(&amp;pool2, 29,\n              fort_event_mode, n, tmp32);\n          len-=n;\n#ifdef FORT_INTERNAL_EVENTS\n          if(fort_internal_events)\n            fort_add_random_event_timer_do(\n                &amp;random_pool, 25,\n                fort_event_mode, &amp;micros);\n#endif\n        } \/\/ while(len>0)\n      } \/\/ if(fort_fill_pool_when_reseeding==1\n#endif\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#ifdef FORT_INTERNAL_EVENTS\n      if(fort_internal_events)\n        fort_add_random_event_timer_do(\n             &amp;random_pool, 26,\n             fort_event_mode, &amp;micros);\n#endif\n    } \/\/ while(c &lt; 32\n    hash_update(&amp;hash, (unsigned char *)&amp;cvar,\n        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  } \/\/ if( (fort_reseed_always==1\n  fort_pseudo_random_data(len, buf);\n\n#ifdef FORT_INTERNAL_EVENTS\n  if(fort_internal_events)\n    fort_add_random_event_timer_do(&amp;random_pool,\n        27, fort_event_mode,\n        &amp;micros);\n#endif\n}\n<\/code><\/pre>\n\n\n\n<p>T\u00e4ss\u00e4 lyhennetty versio, josta on poistettu FORT_INTERNAL_EVENTS ja RESSU rivit:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void fort_random_data_readable(int len, unsigned char *buf)\n{\n  int c;\n  unsigned long tenths;\n  HashCtx hash;\n  unsigned char buffer&#91;HashLen];\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    hash_init(&amp;hash);\n    c=0;\n\n    while(c &lt; 32 &amp;&amp;\n        (fort_reseed_count % (1&lt;&lt;c))==0) {\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    } \/\/ while(c &lt; 32\n    hash_update(&amp;hash, (unsigned char *)&amp;cvar,\n        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  } \/\/ if( (fort_reseed_always==1\n  fort_pseudo_random_data(len, buf);\n}<\/code><\/pre>\n\n\n\n<p>Edellisen aliohjelmat<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>unsigned long gettenths()\n{\n  struct timeval tv;\n  gettimeofday(&amp;tv, NULL);\n  return((unsigned long)tv.tv_sec*10 +\n      (int)tv.tv_usec\/100000);\n}<\/code><\/pre>\n\n\n\n<p>Fort_save toiminnolla voidaan tallettaa generaattorin &#8220;tila&#8221;, ja fort_read_file taas lukee generaattorin tilan.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>char fort_random_file&#91;128] = \"fort.rnd\";\n#define FORT_SAVE_SIZE 1024\n\nvoid fort_save()\n{\n  FILE *fp1;\n  unsigned char buffer&#91;FORT_SAVE_SIZE];\n\n  fp1=fopen(fort_random_file,\"w\");\n\n  if(fp1!=NULL) {\n    fort_pseudo_random_data(sizeof(buffer),\n        buffer);\n    fwrite(buffer, 1, sizeof(buffer), fp1);\n    fclose(fp1);\n  }\n  memset(buffer, 0, sizeof(buffer));\n}\n\nvoid fort_read_file()\n{\n  int d;\n  FILE *fp1;\n  unsigned char buffer&#91;FORT_SAVE_SIZE];\n\n  fp1=fopen(fort_random_file, \"rb\");\n\n  if(fp1==NULL) {\n    fort_pseudo_random_data(\n        sizeof(buffer), buffer);\n#ifdef RESSU\n    ressu_genbuffer(sizeof(buffer), buffer);\n#endif\n    d=sizeof(buffer);\n  } else {\n    d=fread(buffer, 1, sizeof(buffer), fp1);\n    fclose(fp1);\n  }\n  fort_reseed(d, buffer);\n\n  fort_save();\n  memset(buffer, 0, sizeof(buffer));\n}<\/code><\/pre>\n\n\n\n<p>Fort_save generoi joukon satunnaisbittej\u00e4 fort_pseudo_random_data funktiolla ja kirjoittaa ne tiedostoon. Fort_read_file taas lukee edell\u00e4 generoidut satunnaisbitit ja m\u00e4\u00e4rittelee uuden fort_key avaimen fort_reseed() rutiinilla. Jos fort_read_file ei onnistu avaamaan tallennettujen satunnaismerkkien tiedostoa, se generoi avainnukseen k\u00e4ytetyt satunnaismerkit ressulla.<\/p>\n\n\n\n<p>K\u00e4ytetty ressugen aliohjelma:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void ressu_genbuffer(int size, unsigned char *buffer)\n{\n  int c;\n\n  for(c=0;c&lt;size;c++)\n    buffer&#91;c]^=ressu_genbyte();\n}<\/code><\/pre>\n\n\n\n<p>Aliohjelmat yksitt\u00e4isten satunnaisten merkkien ja puskurien luomiseen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define FORT_CLEAR\n\n#define FORTCNT 128\n\nunsigned int fort_cnt=FORTCNT;\nunsigned char fort_bytes&#91;FORTCNT];\nint fort_byte = 999999999;\n\nint fort_random_data_byte()\n{\n  if(fort_byte >= fort_cnt) {\n#ifdef FORT_CLEAR\n    memset(fort_bytes, 0, fort_cnt);\n#else\n    if(fort_byte == 999999999)\n        memset(fort_bytes, 0, fort_cnt);\n#endif\n    fort_random_data(fort_cnt, fort_bytes);\n    fort_byte=0;\n  }\n  return(fort_bytes&#91;fort_byte++]);\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  return(c%limit);\n}\n\nvoid fort_random_data_buffer(int size, 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}\n<\/code><\/pre>\n\n\n\n<p>Seuraavana funktio, jolla alustetaan generaattori k\u00e4ytt\u00f6\u00e4 varten. Se ajetaan yleens\u00e4 ressu_init:in j\u00e4lkeen p\u00e4\u00e4ohjelmassa. Ohjelma tulostaa ensiksi rivin fort:in teknisist\u00e4 tiedoista. Seuraavaksi tyhjennet\u00e4\u00e4n cvar ja alustetaan poolit (puskurit). <\/p>\n\n\n\n<p>Huomaa ett\u00e4 alustettaessa ei voida k\u00e4ytt\u00e4\u00e4 satunnaistapahtumia luovia versioita HashInit:ist\u00e4, koska silloin puskuri voi vastaanottaa tapahtuman, vaikka sit\u00e4 ei ole alustettu. Fort_random_data:ssa on sama ongelma kun vanha puskuri tyhjennet\u00e4\u00e4n ja alustetaan uudestaan.<\/p>\n\n\n\n<p>Seuraavaksi generoidaan ressulla fort_key avain. Jos ressua ei ole, fort_key ei viel\u00e4 t\u00e4ss\u00e4 vaiheessa ole kunnossa. Jos sis\u00e4iset tapahtumat ovat k\u00e4yt\u00f6ss\u00e4, fort_key luodaan kunnolla my\u00f6hemmin tulevassa sis\u00e4isi\u00e4 tapahtumia luovassa kappaleessa.<\/p>\n\n\n\n<p>Fopen funktiolla tyhjennet\u00e4\u00e4n fortevents.deb tiedosto ja dump_events muuttujaan laitetaan ensimm\u00e4isen tapahtuman numero nolla.<\/p>\n\n\n\n<p>Sitten tulee edell\u00e4 mainittu sis\u00e4isten tapahtumien luontikappale. T\u00e4m\u00e4n kappaleen suorituksen j\u00e4lkeen puskureissa on hyv\u00e4 m\u00e4\u00e4r\u00e4 satunnaisuutta vaikka ressua ei olisikaan k\u00e4yt\u00f6ss\u00e4. Sis\u00e4isten tapahtumien luonnin j\u00e4lkeen avainnetaan fort_key uudestaan.<\/p>\n\n\n\n<p>Seuraava kappale tekee tapahtumia (events) satunnaisiin ressu:lla arvottuihin l\u00e4hteisiin. (mode=4)<\/p>\n\n\n\n<p>Lopuksi t\u00e4ytet\u00e4\u00e4n viel\u00e4 0 puskuria lis\u00e4\u00e4m\u00e4ll\u00e4 satunnaismerkkej\u00e4 ja alustetaan fort_reseed_count ja fort_next_reseed nollaksi.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void fort_init()                                                                                                                                                                       \n{\n  fprintf(stdout,\"Fort v0.4\");\n  fprintf(stdout,\", hash: %s\", HashName);\n  fprintf(stdout,\", pools: %d*%ld\", 32,\n      sizeof(HashCtx));\n  fprintf(stdout,\", hashsize: %d\", HashLen);\n\n  unsigned int save_fort_internal_events;\n  save_fort_internal_events=fort_internal_events;\n  fort_internal_events=1;\n\n  clearcvar();\n  \n  \/\/ Initialize buffers\n  for(int c=0;c&lt;32;c++) {\n    fort_pools&#91;c].length = 0;\n    HashInit(&amp;fort_pools&#91;c].pool);\n  }\n\n#ifdef RESSU\n  ressu_genbuffer(sizeof(fort_key),fort_key);\n#endif\n\n  FILE *fp1;\n  \/\/ Empty events file\n  if((fp1=fopen(fort_events_file,\"w\"))!=NULL)\n    fclose(fp1);\n  dump_events=0;\n\n  unsigned char temp&#91;64];\n\n  memset(temp, 0, sizeof(temp));\n\n#ifdef FORT_INTERNAL_EVENTS\n  if(fort_internal_events) {\n    \/\/ Create some internal events\n    for(int c=0;c&lt;64;c++)\n      fort_random_data(sizeof(temp), temp);\n  }\n#endif\n  fort_reseed_count=0;\n  fort_next_reseed=0;\n\n  \/\/ Rekey fort_key with new events\n  fort_random_data(sizeof(temp),temp);\n#ifdef RESSU\n  ressu_genbuffer(sizeof(temp),temp);\n#endif\n  fort_reseed(sizeof(temp),temp);\n\n  fort_read_file();\n\n#ifdef FORT_INTERNAL_EVENTS\n  if(fort_internal_events) {\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    int pool2=0;\n    fort_add_random_event_split(&amp;pool2,\n      30, 4, sizeof(temp), temp, 1);\n  }\n#endif\n\n#ifdef FORT_INTERNAL_EVENTS\n  if(fort_internal_events) {\n    \/\/ Fill first pool\n    fort_pseudo_random_data(sizeof(temp), temp);\n#ifdef RESSU\n    ressu_genbuffer(sizeof(temp), temp);\n#endif\n    int pool2=0;\n    fort_add_random_event(&amp;pool2,\n      28, 1, sizeof(temp), temp);\n  }\n#endif\n\n  \/\/ Forget temp variable\n  memset(temp, 0, sizeof(temp));\n\n  fort_internal_events =\n    save_fort_internal_events;\n\n  fort_reseed_count=0;\n  fort_next_reseed=0;\n}<\/code><\/pre>\n\n\n\n<p>T\u00e4ss\u00e4 viel\u00e4 apurutiineja, joiden avulla saadaan ker\u00e4tty\u00e4 satunnaisuutta hash:ien k\u00e4sittely\u00e4 tekevist\u00e4 init, update ja final rutiineista.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int time_pool=0;\nint init_pool=0;\n\nvoid hash_init(HashCtx *hash)\n{\n#ifdef FORT_INTERNAL_EVENTS\n  unsigned long micros;\n  if(fort_internal_events) {\n    fort_add_random_event_time(&amp;time_pool,\n        10, fort_event_mode);\n    fort_add_random_event_timer_start(&amp;micros);\n  }\n#endif\n  HashInit(hash);\n#ifdef FORT_INTERNAL_EVENTS\n  if(fort_internal_events)\n    fort_add_random_event_timer_do(&amp;init_pool,\n        11, fort_event_mode, &amp;micros);\n#endif\n}\n\nint update_pool=0;\n\nvoid hash_update(HashCtx *hash, unsigned char *data, int len)\n{\n#ifdef FORT_INTERNAL_EVENTS\n  unsigned long micros;\n  if(fort_internal_events) {\n    fort_add_random_event_time(&amp;time_pool, \n        12, fort_event_mode);\n    fort_add_random_event_timer_start(&amp;micros);\n  }\n#endif\n  HashUpdate(hash, data, len);\n#ifdef FORT_INTERNAL_EVENTS\n  if(fort_internal_events)\n    fort_add_random_event_timer_do(&amp;update_pool,\n        13, fort_event_mode, &amp;micros);\n#endif\n}\n\nint final_pool=0;\n\nvoid hash_final(unsigned char digest&#91;HashLen], HashCtx *hash)\n{\n#ifdef FORT_INTERNAL_EVENTS\n  unsigned long micros;\n  if(fort_internal_events) {\n    fort_add_random_event_time(&amp;time_pool,\n        14, fort_event_mode);\n    fort_add_random_event_timer_start(&amp;micros);\n  }\n#endif\n  HashFinal(digest,hash);\n#ifdef FORT_INTERNAL_EVENTS\n  if(fort_internal_events)\n    fort_add_random_event_timer_do(&amp;final_pool,\n        15, fort_event_mode, &amp;micros);\n#endif\n}<\/code><\/pre>\n\n\n\n<p>Viel\u00e4 pieni testip\u00e4\u00e4ohjelma:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int main(int argc,char *argv&#91;])\n{\n  unsigned char buffer&#91;32];\n\n  ressu_init();\n  fort_init();\n\n  ressu_genbuffer(sizeof(buffer), buffer);\n  fort_reseed(sizeof(buffer), buffer);\n\n  fort_random_data(sizeof(buffer), buffer);\n\n  for(int c=0;c&lt;sizeof(buffer);c++)\n    fprintf(stdout,\"%02x\",buffer&#91;c]);\n  fprintf(stdout,\"\\n\");\n\n  fort_save();\n\n  return(0);\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Fort:in p\u00e4\u00e4rakenne tallettaa satunnaisbittigeneraattorin l\u00e4hteet (pool), joihin satunnaisuutta lis\u00e4t\u00e4\u00e4n ja joiden pohjalta sit\u00e4 generoidaan. L\u00e4hteit\u00e4 on 32 kappaletta ja niiden muistirakenne sis\u00e4lt\u00e4\u00e4 satunnaismerkkien lukum\u00e4\u00e4r\u00e4n l\u00e4hteess\u00e4 ja hash toiminnon yhteysalueen (HashCtx). Merkkien lukum\u00e4\u00e4r\u00e4\u00e4 ensimm\u00e4isess\u00e4 poolissa (0) k\u00e4ytet\u00e4\u00e4n sen selvitt\u00e4miseksi onko l\u00e4hteiss\u00e4 tarpeeksi satunnaisuutta seuraavaa avainnusta varten. L\u00e4hteen (tai puskurin) HashCtx yhteysalueeseen lis\u00e4t\u00e4\u00e4n uusi ohjelmalle annettu satunnaisuus&hellip; <a class=\"more-link\" href=\"https:\/\/moijari.com\/?p=634\">Continue reading <span class=\"screen-reader-text\">Fort, Fortunan kaltainen satunnaisbittigeneraattori<\/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\/634"}],"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=634"}],"version-history":[{"count":102,"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts\/634\/revisions"}],"predecessor-version":[{"id":963,"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts\/634\/revisions\/963"}],"wp:attachment":[{"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=634"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=634"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=634"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}