Due immagini identiche non proprio uguali….

Salve cari amici di Ok,panico!

Sono sempre stato affascinato dal mondo della crittografia e in special modo degli algoritmi informatici e oggi vorrei presentarvi un modo per celare del testo dentro ad un’immagine .bmp .

Questa tecnica, che è diversa dalla crittografia in quanto questa cifra un messaggio rendendolo incomprensibile a tutti quelli che non hanno la chiave, si chiama “steganografia” e si limita a nascondere un messaggio alla vista, senza necessariamente crittografarlo.

L’ideale sarebbe perciò un mix di queste due tecniche!!!

Ho cominciato ad appassionarmi a queste tematiche leggendo l’ ottimo libro di Simon Singh “Codici e segreti” , edito da Rizzoli.

Qui viene narrato (….vado a memoria…) che un greco scrisse un messaggio sulla testa rasata di un suo schiavo, aspettò che gli crescessero i capelli e  gli ordino di recarsi  nella città del suo amico destinatario. Qui, le guardie preposte lo perquisirono, ma non trovarono niente. L’amico riuscì invece a leggere il messaggio semplicemente tagliando i capelli dello schiavo.

….Un po’ come l’inchiostro simpatico…

Veniamo al dunque.

L’immagine che useremo DEVE essere in formato .BMP, come la seguente (……. che è in formato jpg perchè WordPress non mi fa fare l’upload di immagini BMP…:( …mannaggia!!).

gilles_villeneuve_ferrari312t4_1979

Ecco l’immagine originale che ho usato in bmp (pesa 2 MB !!)

http://www.juhanpassaatwitter61ll35.altervista.org/uploads/imgupload/@61ll35_img_d5894b9de010cd1895143deb2c3dc17c

Questa invece è l’immagine che contiene un messaggio segreto

http://www.juhanpassaatwitter61ll35.altervista.org/uploads/imgupload/@61ll35_img_66be3d74f107c68ecb53c15a1de87deb

Non avete a portata di mano un file di questo formato, ma migliaia di foto jpg?

Installate ImageMagick, poi date un


convert miaimmagine.jpg miaimmagine.bmp

 

Ho scritto due diversi programmi in C, uno che si occupa di “steganografare il messaggio”, l’altro di rivelarlo.

Questi due programmi accettano come parametri due nomi di file immagine bmp: uno è il file originale, l’altro è quello da noi “steganografato” 🙂

Ecco il sorgente del primo programma che io ho chiamato “steganografa.c”


#include<stdio.h>
#include<string.h>

int main(int argc, char *argv[])
{
    FILE *in;
    FILE *out;
    in=fopen(argv[1],"r");
    out=fopen(argv[2],"w");
    int memo;
    char str[200];//="AAACIAO";
    printf("Inserisci il testo da steganografare...\n");
    scanf("%20000[0-9a-zA-Z!-@{-}]s",str);//,max,stdin);
    //char ch=' ';
    //printf("space=%d\n",ch);
    int len=strlen(str);
    printf("LEN:%d\n",len);
    int a[7],asd=0,i=0,aiuto=0,cont;
    printf("________\n");
    int avanti;
    for (avanti=0;avanti<18;avanti++)
    {
        memo=getc(in);
        putc(memo,out);
    }
    int width1, width2, width3, width4;
    int height1,  height2, height3, height4;
    width1=getc(in);putc(width1,out);
    width2=getc(in);putc(width2,out);
    width3=getc(in);putc(width3,out);
    width4=getc(in);putc(width4,out);
    height1=getc(in);putc(height1,out);
    height2=getc(in);putc(height2,out);
    height3=getc(in);putc(height3,out);
    height4=getc(in);putc(height4,out);
    int aq;
    for (aq=0;aq<28;aq++)
    {
       memo=getc(in);
       putc(memo,out);
    }
    int larghezza=width1+width2*256;
    int altezza =height1+height2*256;
    int quanto=(4-((3*larghezza)%4));
    printf("quanto:%d\n",quanto);
    int contatore;
    for (asd=0;asd<len;asd++)
    {
       int letteraascii=str[asd];
       a[0]=0;
       a[1]=0;
       a[2]=0;
       a[3]=0;
       a[4]=0;
       a[5]=0;
       a[6]=0;
       a[7]=0;
       i=0;
       int pixel,pixel1,fg;
       while(letteraascii>0)
       {
           a[i]=letteraascii%2;
           i++;
           letteraascii=letteraascii/2;
       }

       ///ricrdarsi:invertire array
      /*/////////////////////////
      MODIFICO DI 2 SE BIT 1, MODIFICO DI 1 SE BIT 0
      *//////////////////////////

      for (fg=7;fg>=0;fg--)
      {
          contatore++;
          pixel=getc(in);
          if (a[fg]==1)
          {
              if (pixel<254)
                  pixel1=pixel+2;
          else
              pixel1=pixel-2;
          }
          else //if a[fg]==0
          {
              if (pixel<255)
                  pixel1=pixel+1;
              else
                  pixel1=pixel-1;
          }

          putc(pixel1,out); //
          if (contatore%larghezza==0)
          {
              switch(quanto)
              {
                  case 1:
                      getc(in);putc(0,out);break;
                  case 2:
                      getc(in);putc(0,out);
                      getc(in);putc(0,out);break;
                  case 3:
                      getc(in);putc(0,out);
                      getc(in);putc(0,out);
                      getc(in);putc(0,out);break;
                  case 4:
                      break;
              }
          }
      }
      //contatore++;
}//chiude for LETTERASCII
int pixels;
while(!feof(in))
    {
        pixels=getc(in);
        putc(pixels,out);
        if (contatore%larghezza==0)
        {
            switch(quanto)
            {
                case 1:
                    getc(in);putc(0,out);break;
                case 2:
                    getc(in);putc(0,out);
                    getc(in);putc(0,out);break;
                case 3:
                    getc(in);putc(0,out);
                    getc(in);putc(0,out);
                    getc(in);putc(0,out);break;
                case 4:
                    break;
            }
        }
    }
printf("\n");
int az;

printf("\n");
fclose(in);
fclose(out);

}

Cosa fa questo programma??

Accetta dell’input dall’utente, che è il messaggio che andiamo a iniettare nell’immagine.

Ogni lettera del testo viene convertita nel suo equivalente in ASCII ( la “A” diventa 65), poi questo numero viene convertito in un numero binario (65 è uguale a 01000001).

Ci viene in aiuto un array di 8 elementi dove sono memorizzati i bit di questo numero (65 in questo caso, cioè la lettera “A”, a maiuscolo).

A questo punto siamo pronti per steganografare il testo.

Come?

Beh, abbiamo aperto da programma un’immagine BMP che usiamo come maschera: questa è un file che viene interpretato da programmi di default come pinta come un’immagine,ma da C questo file è una sequenza apparentemente senza senso di byte.

Infatti, i primi byte del file dicono al sistema operativo che quel file è un immagine, poi specificano le dimensioni (altezza e larghezza in pixel dell’immagine) e ulteriori altre amenità che non ci interessano.

La parte interessante arriva dopo una cinquantina di byte dall’inizio del file, dove sono specificate le terne dei colori RGB che compongono il pixel ( il Rosso è rappresentato dai numeri 255,0,0 il viola 255,0,255 ecc ecc)

L’occhio umano non riesce a distinguere due rossi che sono identificati come 255,0,0 e 254,0,0:

Ed è proprio questo principio che sfruttiamo: andiamo a modificare i colori in funzione del messaggio!!

Aumentiamo o diminuiamo di 2 unità una componente cromatica del pixel se l’iesimo bit del byte numeroascii-lettera è 1, di 1 unità se il bit  è zero.

Per esempio se il pixel originale era 136,255,0 e il messaggio da nascondere era 011, il pixel diventa 137,253,2.

Compiliamo


gcc steganografa.c -o steganografa

Eseguiamo con


./steganografa file_bmp_ORIGINALE.bmp file_bmp_STEGANOGRAFATO.bmp

Ci viene chiesto di inserire un  messaggio, non la bibbia intera!

Ecco il sorgente del programma che si occupa di decodificare l’immagine, che io ho chiamato “decodesteg.c”


#include<stdio.h>
#include<string.h>

int main(int argc, char *argv[])
{
    FILE *originale;
    FILE *contraffatto;

    originale=fopen(argv[1],"r");
    contraffatto=fopen(argv[2],"r");

    int memo,pixeloriginale,pixelcontraffatto;
    int asd=0,i=0;
    int avanti;
    for (avanti=0;avanti<34;avanti++)
    {
        getc(originale);
        getc(contraffatto);
    }
    int contatore;
    int a[8];
    a[0]=0;a[1]=0;a[2]=0;a[3]=0;
    a[4]=0;a[5]=0;a[6]=0;a[7]=0;
    i=0;
    int pixel,pixel1,fg;
    int diff,cont=0,asciinum=0;
    while (!feof(contraffatto))
    {
        contatore++;
        pixeloriginale=getc(originale);
        pixelcontraffatto=getc(contraffatto);
        if (pixeloriginale>pixelcontraffatto)
            diff=pixeloriginale-pixelcontraffatto;
        else
            diff=pixelcontraffatto-pixeloriginale;
        if (diff==2)
            {a[cont]=1;cont++;}
        if (diff==1)
            {a[cont]=0;cont++;}

        if (cont==8)
        {
            asciinum=128*a[0]+64*a[1]+32*a[2]+
                16*a[3]+8*a[4]+4*a[5]+2*a[6]+a[7];
            printf("%c",asciinum);
            cont=0;asciinum=0;
            a[0]=0;a[1]=0;a[2]=0;a[3]=0;
            a[4]=0;a[5]=0;a[6]=0;a[7]=0;
        }
        /*if (contatore%larghezza==0)
        {
             switch(quanto)
             {
                 case 1:
                     getc(originale);
                     getc(contraffatto);break;
                 case 2:
                     getc(originale);
                     getc(contraffatto);getc(originale);
                     getc(contraffatto);break;
                 case 3:
                     getc(originale);getc(contraffatto);
                     getc(originale);getc(contraffatto);
                     getc(originale);getc(contraffatto);
                     break;
                 case 4:
                     break;
             }//switch
        }//if
        */
    }//chiude while
    fclose(originale);
    fclose(contraffatto);
    printf("\n");
}//chiude main

Compiliamolo


gcc decodesteg.c -o decodesteg

Eseguiamolo


./decodesteg file_immagine_STEGANOGRAFATO.bmp file_immagine_ORIGINALE.bmp

Questo programma compara uno a uno le componenti cromatiche RGB di ogni  pixel di due immagini, la “contraffatta” e “l’originale”, che ad occhio sembrano identiche, ma che in realtà non lo sono.

Se trova una differenza assoluta di 2 unità lo interpreta come “1”, se la differenza è di 1 unità allora il bit è zero.

L’intero byte numerico viene ricostruito tramite la formula


asciinum=128*a[0]+64*a[1]+32*a[2]+16*a[3]+8*a[4]+4*a[5]+2*a[6]+a[7];

e visualizzato con


printf("%c",asciinum);

Spero di essere stato chiaro in questo post, anche se, come avete capito…. l’apparenza inganna…:)

A presto!

Posta un commento o usa questo indirizzo per il trackback.

Commenti

  • Man from Mars  Il 19 giugno 2014 alle 17:30

    Purtroppo non conosco il C e quindi non posso apprezzare del tutto il codice che hai scritto. Tuttavia è interessante vedere che un problema apparentemente complesso si risolve di fatto in poche righe.
    La domanda che mi è sorta è (non essendo riuscito a capirlo dal codice): c’è un controllo se il messaggio è troppo lungo rispetto alle dimensioni dell’immagine “vettore”?
    So che è un’eventualità molto remota, ma potrebbe verificarsi usando immagini piccole (i conticini li lascio da parte).

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google photo

Stai commentando usando il tuo account Google. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

%d blogger hanno fatto clic su Mi Piace per questo: