Istuntoavaimen luominen

Tässä postissa käyn läpi tertun ns istuntoavaimen muodostamisen. Istuntoavaimen luomiseen tarvitaan satunnaisbittigeneraattori ja joku sisäinen malli, jonka mukaan istuntoavain muodostetaan satunnaisbittigeneraattorin antamista biteistä. Ensin yksinkertainen satunnaisbittigeneraattori ressu:

Tässä käytetään vain yhtä lähdettä, ressua. Varmuuden vuoksi kannattaa lisätä ainakin toinen lähde.

#include <sys/time.h>

unsigned char dba_clockbyte() /* JariK 2013-2020 */
{
  struct timeval tv;

  gettimeofday(&tv,NULL);

  return(tv.tv_usec & 0xff);
}

void dba_ressu_genbytes(int size, unsigned char *buffer) /* JariK 12/2020 */
{
  int c, d, e, f, byte, prevbyte, bits;

  f=0;
  bits=0;

  for(c=0; c<8 || c%8!=0 || c<16 || c<48 ||
      bits<8*size; c++) {
    for(d=0; d<size; d++) {
      e = buffer[d];
      e = ((e&0x80)>>7) | ((e&0x7f)<<1);
      byte = dba_clockbyte();
      buffer[d] = e^byte;
      if(prevbyte != byte) {
        bits++;
        prevbyte = byte;
      }
    }
    for(d=0; d<size; d++) {
      f = (f+buffer[d])%size;
      e = buffer[d];
      buffer[d] = buffer[f];
      buffer[f] = e;
    }
  }
}

Ja sitten rutiinit, joilla satunnaismerkkejä saa merkki kerrallaan:

#define DBA_RESSUCNT 128
#define DBA_RESSU_CLEAR 2

unsigned char dba_ressu_bytes[DBA_RESSUCNT];
int dba_ressu_byte = 999999;
int dba_ressu_cnt = DBA_RESSUCNT;

int dba_ressu_genbyte()
{
  if(dba_ressu_byte>=dba_ressu_cnt) {
#ifdef DBA_RESSU_CLEAR
    memset(dba_ressu_bytes,0,dba_ressu_cnt);
#else
    if(dba_ressu_byte==999999)
      memset(dba_ressu_bytes,0,dba_ressu_cnt);
#endif
    dba_ressu_genbytes(dba_ressu_cnt,dba_ressu_bytes);
    dba_ressu_byte=0;
  }
  return(dba_ressu_bytes[dba_ressu_byte++]);
}

int dba_ressu_genbyte_limit(int limit)
{
  int c;

  while((c = dba_ressu_genbyte())>=
      (256/limit)*limit);
  /* while((c = fort_random_data_byte())>                                                                                       
      (256/limit)*limit); little bug */
  return(c % limit);
}

void dba_ressu_random_clear()
{
  memset(dba_ressu_bytes,0,dba_ressu_cnt);
  dba_ressu_byte=999998;
}

Seuraava rutiini arpoo istuntoavaimen merkki kerrallaan:

// 0123456789
// abcdefghij
// klmnopqrst
// uvwxyzABCD
// EFGHIJKLMN
// OPQRSTUVWX
// YZ

void dba_gensessionid(int size, unsigned char *buffer)
{
  int len,byte,first;
  unsigned char chars[] =
    "0123456789" \
    "abcdefghijklmnopqrstuvwxyz" \
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  unsigned char *n;

  dba_ressu_random_clear();
  n=buffer;
  len=0;
  first=1;
  while(++len<size) {
    if(first)
      byte=dba_ressu_genbyte_limit(sizeof(chars)-11)+10;
    else
      byte=dba_ressu_genbyte_limit(sizeof(chars)-1);
    *n++=chars[byte];
    first=0;
  }
  *n='\0';
  dba_ressu_random_clear();
}

Session id talletetaan kookieksi tulostamalla kookierivi html otsakkeeseen:

#define DBS_RENEW_SESSION_HOURS 24

void dba_renew_cookie()
{
  dbs_html_buf_printf(HTML_HEADER_BUFFER,"Set-Cookie: sessionid=%s; Max-Age=%d\r\n",
              htmlsessionid, 3600*DBS_RENEW_SESSION_HOURS);
}

Vielä pieni pääohjelma: tässä avaimen pituus on 32 merkkiä, viimeinen merkki on ‘\0’.

void main()
{
  char buffer[33];

  dba_gensessionid(sizeof(buffer),buffer);

  fprintf(stdout,"%s\n",buffer);
}

Published
Categorized as muuta