Newsgroup: it.comp.lang.c
Titolo: Problemino con la password crittata...

Ciao a tutti....
Ho fatto un piccolo programmino che cifra un file(ascii o bin) data una
password(lo xora con quella...)... Il problema sorge per il semplice fatto
che per impedire di incasinare il file, al momento della crittazione il prog
salva la password  all'inizio del file e poi quando il file viene decrittato
verifica se la password inserita al prompt è uguale a quella nel file...
La password salvata nel file è ovviamente crittata, ma in maniera molto
pedestre( lasciando perdere il resto): il primo carattere viene spostato in
avanti di tante posizioni quanto il suo valore ascii(es : la A verrà
spostata in avanti di 65 posizioni e avrà quindi valore 130, ecc...)... Così
pensavo di aver risolto il problema ma in realtà ho notevolente indebolito
l'algoritmo per due motivi:
1) La password è all'inizio del file, bisogna solo stabilire quanto è
lunga(min 8 caratteri, max 50)...
2) Una volta stabilita la lunghezza, considerando il fatto che la password
non sarà una frase o parola senza senso(la maggior parte della volte) si può
ridurre notevolmente il numero delle possibili combinazioni oltre al fatto
che ciascun carattere della password crittata sarà il risultato di :  valore
carattere pass in chiaro + valore carattere pass in chiaro...
Quindi per esempio, una password di otto caratteri con solo le 26 lettere
dell'alfabeto(minuscole per esempio) non avrà più 200 miliardi di possibili
combinazioni, ma poche decine di migliaia! Questo mi manda a puttane la
maggior parte della(poca) sicurezza disponibile ...
D'altronde è utile che il prog verifichi prima di provare a decrittare se la
pass è giusta o no: uno potrebbe essersi sbagliato a digitarla....
Comunque il prog è questo qua:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 50
FILE *fp;
FILE *ch;
long dimensione;
long i=0;
char buffer;
char password[256];
char pass[200];
char pass3[MAX];
char pass4[MAX];
int h=0;
int lunghezza;
int j=0;
int k;
char lettura;
char scrittura;
main(int argc, char *argv[])
{
 if(argc<2)
  {
   fprintf(stderr,"\nSintassi corretta: %s nomefileorigine...\n",argv[0]);
   exit(1);
  }
 while(lunghezza<8)
 {
 printf("\n\n\tPassword: ");
 scanf("%s",pass3);
 fflush(stdout);
 lunghezza=strlen(pass3);
 if(lunghezza<8)
  {
   printf("\nPer ragioni di sicurezza, la password deve offrire almeno una
protezione a 64 bit!)");
   printf("\nCioé almeno circa 18.000.000.000.000.000.000 di combinazioni
possibili!");
   printf("\nInserire quindi una password di almeno 8 caratteri(max 50
caratteri,cioé 400 bit)!");
  }
 }
 fp=fopen(argv[1],"rb");
 if(fp==NULL)
  {
   fprintf(stderr,"\nErrore in apertura file origine...\n");
   exit(1);
  }
 ch=fopen("xyzk.xyzk","wb");
 if(ch==NULL)
  {
   fprintf(stderr,"\nErrore in apertura file destinazione...\n");
   exit(1);
  }
 fseek(fp,0,SEEK_END);
 dimensione=ftell(fp);
 rewind(fp);
 fgets(password,3,fp);
 if(password[0]=='-' && password[1]=='-')
  {
   fseek(fp,107,SEEK_SET);
   i=107;
   for(h=0;h<strlen(pass3);h++)
    {
     lettura=fgetc(fp);
     lettura=lettura-pass3[h];
     pass4[h]=lettura;
    }
   if(strcmp(pass3,pass4)==0)
    {
     printf("\n\nDecrittazione in corso...\n\n");
     fseek(fp,107+lunghezza,SEEK_SET);
     i=107+lunghezza;
    }
   else
    {
     printf("\n\nImpossibile decrittare il file: password
scorretta...\n\n");
     exit(0);
    }
  }
 else
  {
   rewind(fp);
   fprintf(ch,"-----------------------------------------------Begin
crypt------------------------------------------------\n",argv[1]);
   for(h=0;h<strlen(pass3);h++)
    {
     scrittura=pass3[h]+pass3[h];
     fwrite(&scrittura,sizeof(scrittura),1,ch);
    }
  }
 for(i=i;i<dimensione;i++)
  {
   buffer=fgetc(fp);
   buffer=buffer^pass3[j];
   if(j>lunghezza)
    {
     j=0;
    }
   j++;
   fwrite(&buffer,sizeof(buffer),1,ch);
  }
 fclose(fp);
 fclose(ch);
 remove(argv[1]);
 rename("xyzk.xyzk",argv[1]);
return 0;
}
Ho pensato anche di fare un wipe a xyzk.xyzk prima di eliminarlo...(per
esempio riempendolo di Z)
Voi come fareste ad eliminare il problema?
Io avevo pensato di crittare la password con un'altra password: c'è un altra
maniera meno scomoda?
Grazie in anticipo a chi mi risponderà
Steve

verifica se la password inserita al prompt è uguale a quella nel file...
La struttura che hai pensato e' debolissima... la password non la devi
mettere per nulla nel file. Potresti usare questo sistema alternativo:
  1) In fase di cifratura chiedi la password all'utente
  2) Scrivi il file criptato (solo i dati e non la password)
  3) Scrivi alla fine del file quanto fa la somma di tutti i
     caratteri del file originale (prima della cifratura).
Quando un utente vuole decifrare il file:
  1) Chiedi la password
  2) Decifri il file secondo la password inserita
  3) Verifichi che la somma dei caratteri coincida e altrimenti
     segnali all'utente che la password non era corretta
Al massimo puo' succedere che un tentativo di decodifica fallito
venga invece segnalato come riuscito... ma non e' un problema visto
che il file risultato conterrebbe comunque dati errati.
Nota... con questo sistema (e con tutti i sistemi "seri" o quasi)
anche l'autore del programma non e' in grado di decifrare un file
se non conosce la password. Questo e' molto importante.
Andrea
PS: Se il file ha una struttura nota o prevedibile (ad es. perche'
    ha un header standard) allora una decifrazione sarebbe
    comunque molto semplice perche' basterebbe effettuare un XOR
    della parte iniziale del file con i dati che si sanno essere
    presenti e si ottiene immediatamente la password in chiaro.
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

Si effettivamente non era un gran metodo il mio....
Io comunque avevo risolto in modo simile al tuo....
Al posto di fare una sorta di checksum finale,  scrivevo la password
inserita in questo modo:
for(h=0;h<lunghezza;h++)
    totale=totale+pass3[h];
   for(h=0,k=2;h<lunghezza,k<lunghezza+2;h++,k++)
    parziale[h]=totale-(totale/k);
   for(h=0;h<lunghezza;h++)
    pass3[h]=pass3[h]^parziale[h];
   fprintf(ch,pass3);
dove totale è la somma totale dei caratteri della password, pass3 è la
password(o meglio il puntatore all'inizio della password) parziale[h] è il
h-esimo valore con cui xorare il h-esimo carattere della password in base a
quella formula, con k che va da 2 a lunghezza-2, lunghezza è la lunghezza
della password, h e k dei contatori, ch il file in cui scrivere la
password...
Così facendo dovrebbe essere difficile decrittarla, perchè non conosco + la
checksum finale...
Infatti io per verificarla non la decritto, ma eseguo lo stesso procedimento
confrontando poi il risultato....
Domanda: secondo te è sicuro sto metodo qui ? Altrimenti faccio come mi hai
detto tu?
Domanda 2: C'è forse qualche possibilità di collisione? A me non sembra
perchè anche se la somma è la stessa i caratteri della password devono
essere nello stesso ordine....
Grazie della tua risposta
Steve

 password...
Scusa ch è il puntatore al file in cui scrivere la password.... :-)

essere nello stesso ordine....
Sicuramente esistono collisioni. In algebra si chiama "principio
dei cassetti" e in questo caso traduce in "siccome il numero di
password e' maggiore del numero di possibili valori per una
somma esistono sicuramente password diverse che generano la
stessa somma".
Questo pero' non e' un problema per la cifratura/decifratura;
anzi complica la vita a chi cerca di decifrare il file senza
sapere la password (anche se la somma finale e' giusta magari
il file non e' stato decodificato correttamente).
Andrea


 la cosa e' sicuramente piu' complessa)
E' vero difatti sto elaborando un craccatore di password....
Questo č il prog che cifra la password:
#include <stdio.h>
#include <string.h>
int totale,lunghezza,i,k;
int parziale[200];
char strange[200];
char strange2[200];
FILE *fp;
main()
{
 fp=fopen("password.txt","wb");
 scanf("%s",strange);
 lunghezza=strlen(strange);
 for(i=0;i<lunghezza;i++)
  {
   totale=totale+strange[i];
  }
 for(i=0,k=2;i<lunghezza,k<lunghezza+2;i++,k++)
   parziale[i]=totale-(totale/k);
 for(i=0;i<lunghezza;i++)
  {
   strange[i]=(strange[i]^parziale[i]);
  }
 fprintf(fp,"%s",strange);
 scanf("%s",strange2);
 totale=0;
 lunghezza=strlen(strange2);
 for(i=0;i<lunghezza;i++)
  {
   totale=totale+strange2[i];
  }
 for(i=0,k=2;i<lunghezza,k<lunghezza+2;i++,k++)
   parziale[i]=totale-(totale/k);
 for(i=0;i<lunghezza;i++)
  {
   strange2[i]=(strange2[i]^parziale[i]);
  }
 if(strcmp(strange,strange2)==0)
  printf("\nLe due stringhe sono uguali\n");
 else
  printf("\nLe due stringhe sono diverse!\n");
 return 0;
}
Questo invece tenta di fare un brute force grezzo:
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
char a,b,c,d,e,f,g,h;
int i,x,y;
int lunghezza;
long calcoli=0;
int checksum=0;
int parziale[30];
time_t inizio , fine;
FILE *fp;
char buffer[30],al[30];
main()
{
time(&inizio);
fp=fopen("password.txt","rb");
fgets(buffer,9,fp);
for(a='a';a<='z';a++)
for(b='a';b<='z';b++)
for(c='a';c<='z';c++)
for(d='a';d<='z';d++)
for(e='a';e<='z';e++)
for(f='a';f<='z';f++)
for(g='a';g<='z';g++)
for(h='a';h<='z';h++)
 {
  checksum=0;
  calcoli++;
  al[0]=a;
  al[1]=b;
  al[2]=c;
  al[3]=d;
  al[4]=e;
  al[5]=f;
  al[6]=g;
  al[7]=h;
  lunghezza=strlen(al);
  for(y=0;y<lunghezza;y++)
   {
    checksum=checksum+al[y];
   }
  for(y=0,x=2;y<lunghezza,x<lunghezza+2;y++,x++)
   {
    parziale[y]=checksum-(checksum/x);
   }
  for(y=0;y<lunghezza;y++)
   {
    al[y]=(al[y]^parziale[y]);
   }
  for(i=0;i<8;i++)
   checksum=checksum+al[i];
  if(strcmp(al,buffer)==0)
   {
    for(y=0;y<lunghezza;y++)
     al[y]=al[y]^parziale[y];
    printf("\nPassword: %s\n",al);
    time(&fine);
    i=difftime(fine,inizio);
    if(i<1)
     i=1;
    printf("\nTempo impiegato: %d\n",i);
    printf("Password tentate: %ld\n",calcoli);
    printf("Combinazioni al secondo: %ld\n",calcoli/i);
    exit(0);
   }
        }
time(&fine);
i=difftime(fine,inizio);
printf("\nTempo impiegato: %d\n",i);
return 0;
}
Mi sorge perň un problema: come faccio a partire da...
a
b
...
aa
ab
....
e cosě via?
So che un po' di tempo fa era stato postato un messaggio del genere ma non
riesco + a trovarlo...
Grazie di tutto...
Steve