Newsgroup: it.comp.lang.c
Titolo: Disordinare un vettore tramite una password

Salve a tutti,
Sto realizzando un programma di steganografia di immagini bitmap,
Ho però un grosso problema: divido la mappa dei pixel in una matrice
immaginaria (che non ho in memoria) ed ad ogni cella della matrice
associo 3 pixel
dell'immagine, ho però bisogno di una funzione che ricevendo come
argomento una stringa
(la password) riesca a disordinare 2 vettori che contengono le
coordinate X e Y di questa matrice
in modo da andare a sparpagliare i dati all'interno dell'immagine.
Ho provato ad usare queste funzioni; la funzione F riceve un carattere
della password
e restituisce una coordinata X e una Y che vado a
memorizzare in una lista dinamica, il problema è la funzione F che
dopo un po mi restituisce
gli stessi valori andando in loop (circa dopo 10000 passaggi):
typedef struct lista_matrice *P_LISTA_MATRICE;
typedef enum {FALSE TRUE} boolean;
typedef struct lista_matrice
    {
    long int X;
    long int Y;
    P_LISTA_MATRICE p_testa;
    } LISTA_MATRICE;
/* ......................... */
P_LISTA_MATRICE genera_password(long int dimensione, long int lato)
{
P_LISTA_MATRICE testa_lista=NULL, aux;
char carat, pass[MAX_STR];
int i, len_pass, seme=SEME;
int X,Y;
long int cont;
printf("\nInserisci Password: ");
for(i=0; (carat=getchar())!=EOF && i<MAX_STR; i++)
    pass[i]=carat;
pass[i]='\0';
len_pass=strlen(pass);
i=0;
printf("\nLato: %li\n",lato);
printf("\nCodici F\nX\tY\n");
while (i<dimensione)
    {
    cont=i%len_pass;
    seme=F(seme, pass[cont], &X, &Y);
    X=(X*lato)/32768;
    Y=(Y*lato)/32768;
    printf("%i\t", i);
    if (!lista_trova(testa_lista, X,Y))
        {
        aux=(P_LISTA_MATRICE)malloc(sizeof(LISTA_MATRICE));
        (*aux).p_testa=testa_lista;
        (*aux).X=X;
        (*aux).Y=Y;
        testa_lista=aux;
        i++;
        printf("%i\t%i\t%i\n",X,Y,i);
        }
    }
return testa_lista;
}
int F(int seme, char carat, int *X, int *Y)
{
int i, num;
srand(seme+(int)carat);
for(i=0;i<100;i++)
    {
    num=rand();
    if(i==25)
        seme=num;
    else if(i==50)
        (*X)=num;
    else if(i==99)
        (*Y)=num;
    }
return seme;
}
boolean lista_trova(P_LISTA_MATRICE testa_lista, int X, int Y)
{
boolean trovato=FALSE;
P_LISTA_MATRICE lista_corrente;
lista_corrente=testa_lista;
while (lista_corrente!=NULL && !trovato)
    {
    if((*lista_corrente).X==X && (*lista_corrente).Y==Y)
        trovato=TRUE;
    lista_corrente=(*lista_corrente).p_testa;
    }
return trovato;
}
Mi chiedevo se esiste un metodo più funzionale...
Grazie in anticipo per l'attenzione!

 Grazie in anticipo per l'attenzione!
Figurati ;)
lb

@Tetsuya:
Grazie del consiglio ma secondo me è più leggibile (*punt).record
soprattutto quando hai puntatori a puntatori di strutture :)
@Lorenzo Beretta:
Si è vero usare la srand tante volte aumenta la confusione...(ed è
anche poco elegante :) ) il problema è che volevo che ogni carattere
della password apportasse un contributo alla dispersione dei dati. La
cosa migliore sarebbe eliminare del tutto la random
ed inserire qualcosa di più matematico. Ma non so cosa!
Comunque il programma va in loop perche la srand qualunque sia
l'argomento restitusce un valore già presente nella lista...
Cioe semi diversi output identici oO
Come l'inizializzeresti la random in modo da tener conto di tutta la
password?
Ps: L'Ahia!  a cosa si riferiva? :)

 ed inserire qualcosa di più matematico. Ma non so cosa!
Non ho capito com'e' che vuoi disperdere i dati nell'immagine, comunque 
vediamo se riesco a darti qualche suggerimento generale:
1. la steganografia e' parecchio studiata, e ci sono anche metodi per 
estrarre l'informazione nascosta nelle immagini anche senza conoscere 
l'immagine originale! Vedi ad es. questa tizia qui e uno dei suoi brevetti:
http://www.ws.binghamton.edu/fridrich/
http://patft1.uspto.gov/netacgi/nph-
Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL&p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=6831991.PN.&OS=PN/6831991&RS=PN/6831991
(il brevetto serve a cercare proprio quello che vuoi fare tu, "embedding of 
a secret message in randomly scattered pixels" :)
2. rand() per questo lavoro non va bene, come hai potuto vedere. Devi 
comunque usare un generatore pseudo-casuale, ma visto che parliamo di 
crittografia, mi sa che ti conviene usare un generatore di qualita' 
crittografica:
http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator
3. Usare la password direttamente non va bene, perche' ti esponi al classico 
attacco dizionario:
http://en.wikipedia.org/wiki/Dictionary_attack
Quello che dovresti fare e' una "salatura" piu' un rinforzo della chiave:
http://en.wikipedia.org/wiki/Salt_%28cryptography%29
http://en.wikipedia.org/wiki/Key_strengthening
A quel punto userei il risultato come seme del generatore pseudocasuale, e 
dovresti avere dei buoni numeri per il tuo algoritmo di shuffling.
Pleg
PS: per la crittografia wikipedia e' effettivamente una buona risorsa :)


Al fatto che se la password � lunga lunga lunga esci dal ciclo for con 
i==MAX_STR, e l'istruzione successiva scrive su pass[MAX_STR]: questo di 
suo pu� anche non essere un danno visto il resto del codice, ma certo 
non promette bene tenersi in giro stringhe non terminate.

@Lorenzo Beretta:
Cavolo hai ragione... mi sono dimenticato di aggiungere +1 quando creo
la stringa... ora ho corretto grazie :)
Comunque mi sono sbagliato nel post precedente il seme era lo stesso
per quello si impiantava...
Ora se rileva che il seme non cambia lo incrementa di uno... diciamo
che è una pezza ma ora funziona tutto come dovrebbe... :)
@Pleg
Grazie per i consigli! non sapevo della tecnica della "salatura".
Vedro anche di mettere un generatore di numeri
pseudocasuali di qualità crittografica!
Grazie ancora a tutti per la disponibilita! :)