Salasanan salakirjoitus tertussa

Kaikki oikeudet tietenkin pidätetään. Viimeinen versio ohjelmasta löytyy seuraavasta linkistä: moijari.com:5002. Ressu satunnaislukuja löytyy osoitteesta: moijari.com:5001. Ikuinen kalenteri osoitteesta: moijari.com:5003.

Salasana on salakirjoitettuna muodossa:

sha256:ee84f5affcf47d:51567b8c4c20db2a00ea24eaae125a26f5c7c87fdbe5b90a02225fc97008b49a (oheinen salasana on muuten "SalaSana1234") ja vielä
unsigned char *peppper="l7IKrgcLMgsl_4Wv";

Alussa salatun salasanan tallennusformaatti, kaksoispisteen jälkeen alkaa salt:ti ja seuraavan kaksoispisteen jälkeen alkaa kryptattu salasana.

Tämä ensimmäinen rutiini salakirjoittaa password kentässä olevan salasanan ja muodostaa encpasswd kentän joka sisältää salasanan salakirjoitetussa muodossa.

int encryptpasswd(unsigned char encpasswd[ENCPASSWD_SIZE],unsigned char *password)
{
  int c,d;

  HashCtx ctx;

  unsigned char salt[7];
  unsigned char salthex[15];
  unsigned char twodigit[3];
  unsigned char temp[HashLen];
  unsigned char temphex[HashLen*2+1];

  memset(encpasswd,0,ENCPASSWD_SIZE);

  ressu_genbytes2(sizeof(salt),salt);

  ...

Ohjelman alussa varataan erilaisia ohjelman tarvitsemia muistialueita. Salt kentän tarkoituksena on erilaistaa sama salasana eri käyttäjillä ja vaikeuttaa kryptattujen salasanojen hakemiston muodostamista. Salt on salakirjoittamattomana salakirjoitetussa salasanassa , ja kopioidaan sellaisenaan salasanan tarkastukseen. Temp kenttää taas käytetään kryptatun salasanan tallettamiseen..

Seuraavat ohjelmarivit muuttavat salt:in heksamuotoon:

  ...
  for(c=0;c<sizeof(salt);c++) {
    sprintf(twodigit,"%02x",salt[c]);
    strcat(salthex,twodigit);
  }
  ...

Seuraava kappale tekee varsinaisen salakirjoituksen, Salakirjoitus tehdään sha256 tiivisterutiinilla. HASHROUNDS on tällä hetkellä sata tuhatta, ja siihen on valittu mahdollisimman suuri luku, joka silti pitää logon-vaiheen keston kohtuullisena. Pepper on aloitusarvo rutiinille.

  ...
  memset(temp,0,sizeof(temp));
  strcpy(temp,pepper);
  for(c=0;c<HASHROUNDS;c++) {
    HashInit(&ctx);
    HashUpdate(&ctx,temp,sizeof(temp));
    HashUpdate(&ctx,salt,sizeof(salt));
    HashUpdate(&ctx,password,strlen(password)+1);
    HashFinal(temp,&ctx);
  }
  ...

Seuraavassa edellisen koodikappaleen tulos temp muuttujassa laitetaan heksamuotoon:

  ...
  temphex[0]='\0';
  for(c=0;c<sizeof(temp);c++) {
    sprintf(twodigit,"%02x",temp[c]);
    strcat(temphex,twodigit);
  }
  ...

Kootaan salakirjoitettu salasana:

  ...
  strcpy(encpasswd,"sha256:");
  strcat(encpasswd,salthex);
  strcat(encpasswd,":");
  strcat(encpasswd,temphex);
  ...

Ja tyhjennetään vielä välikentät, jottei niitä vuoda ulos aliohjelmasta: ja funktion lopussa vielä return lause (0=ok).

  ...
  memset(salt,0,sizeof(salt));
  memset(salthex,0,sizeof(salthex));
  memset(temp,0,sizeof(temp));
  memset(temphex,0,sizeof(temphex));

  return(0);
}

Salasanan tarkistus funktio tekee oikeastaan samat asiat, hieman muuteltuna: koodikappaleen loppu tarkistaa salakirjoitetun salasanan tallennusformaatin ja  hakee salt:in heksamuodossa. Salt haetaan parametrina annetusta salakirjoitetusta salasanasta.

int checkpasswd(unsigned char encpasswd[ENCPASSWD_SIZE],unsigned char *password)
{
  int c,d,e,byte,ok;
  unsigned char *p,*s;
  HashCtx ctx;

  unsigned char salt[7];
  unsigned char salthex[15];
  unsigned char twodigit[3];
  unsigned char temp[HashLen];
  unsigned char temphex[HashLen*2+1];
  unsigned char encpasswd2[128];

  p=encpasswd;

  if(strncmp(p,"sha256:",7))
    return(1);

  p+=7;
  s=salthex;
  while(*p!=':') {
    *s++=*p++;
  }
  *s='\0';
  ...

Salasanan tarkistusrutiini hakee saltin satunnaisbittigeneraattorin sijasta annetusta salakirjoitetusta salasanasta.

Seuraava siirtää heksana olevan saltin binäärimuotoon:

  ...
  c=0;
  s=salthex;
  for(;;) {
    if((d=gethexdigit(*s++))==-1) break;
    if((e=gethexdigit(*s++))==-1) break;
    byte=d*16+e;
    salt[c++]=byte;
  }
  ...

Varsinainen salasanan kryptausosa on samanlainen kun edellisessä crypt rutiinissa:

  ...
  memset(temp,0,sizeof(temp));
  strcpy(temp,pepper);
  for(c=0;c<HASHROUNDS;c++) {
    HashInit(&ctx);
    HashUpdate(&ctx,temp,sizeof(temp));
    HashUpdate(&ctx,salt,sizeof(salt));
    HashUpdate(&ctx,password,strlen(password)+1);
    HashFinal(temp,&ctx);
  }
  ...

Muokanaan salakirjoitettu salasana temp kentästä temphex kenttään heksamuotoon:

  ...
  temphex[0]='\0';
  for(c=0;c<sizeof(temp);c++) {
    sprintf(twodigit,"%02x",temp[c]);
    strcat(temphex,twodigit);
  }
  ...

Muodostetaan varsinainen salasana salakirjoitetussa muodossa:

  ...
  strcpy(encpasswd2,"sha256:");
  strcat(encpasswd2,salthex);
  strcat(encpasswd2,":");
  strcat(encpasswd2,temphex);
  ...

Vertaillaan salakirjoitettuna annettua salasanaa ja selväkielisestä salasanasta muodostettua salakirjoitettua salasanaa keskenään, tyhjennellään kenttiä ja palautetaan totuusarvo:

  ...
  if(!strcmp(encpasswd,encpasswd2)) {
    fprintf(stdout,"\n*************ok");
    ok=0;
  } else {
    fprintf(stdout,"\n*************error");
    ok=1;
  }

  memset(encpasswd2,0,ENCPASSWD_SIZE);
  memset(salt,0,sizeof(salt));
  memset(salthex,0,sizeof(salthex));
  memset(temp,0,sizeof(temp));
  memset(temphex,0,sizeof(temphex));

  return(ok);
}

Tässä vielä gethexdigit:

int gethexdigit(char h)
{
  int byte;

  if(h>='0' && h<='9')
    byte=h-'0';
  else if(h>='a' && h<='f')
    byte=h-'a'+10;
  else if(h>='A' && h<='F')
    byte=h-'A'+10;
  else
    byte=-1;

  return(byte);
}