POLITECNICO DI BARI Facoltà di Ingegneria Corso di Laurea in Ingegneria Informatica “Sicurezza dei Sistemi Informatici” REALIZZAZIONE DI UNA APPLICAZIONE DI STEGANOGRAFIA IN JAVA USANDO I FILE GRAFICI GIF E JPG CONTENUTI Steganografia Struttura, memorizzazione, interpretazione di una immagine Compressione delle immagini Formati GIF e JPG Un esempio di steganografia in Java Conclusioni STEGANOGRAFIA La steganografia è l’arte e la scienza di scrivere messaggi segreti all’interno di un contenitore multimediale (immagine, suono, ecc.) in modo che nessuno possa conoscerne l’esistenza. Obiettivi: nascondere in modo sicuro informazioni segrete e private; proteggere i diritti sui dati quando sono coinvolti interessi economici e profitti (watermarking). STEGANOGRAFIA VS CRITTOGRAFIA Steganografia Crittografia la rilevazione del messaggio nascosto comporta il fallimento della tecnica di steganografia. l’esistenza del messaggio è nota ma il significato è oscuro. Soluzione ibrida: steganografia e crittografia sono impiegate in maniera combinata codificando il messaggio prima di inserirlo all’interno del suo contenitore. STRUTTURA, MEMORIZZAZIONE E INTERPRETAZIONE DI UNA IMMAGINE (1) Immagine matrice di punti colorati detti pixel. Pixel quattro unsigned byte di dati: 3 byte rappresentano i colori rosso, verde e blu (color byte); 1 byte rappresenta la trasparenza (alpha byte) . STRUTTURA, MEMORIZZAZIONE E INTERPRETAZIONE DI UNA IMMAGINE (2) Ogni unsigned byte assume valori nell’intervallo 0 – 255. Rappresentazione dei colori: nero: R = G = B = 0; bianco: R = G = B = 255; tonalità di grigio: R = G = B = un valore nel range (0-255); colore: unione di una certa quantità di rosso, verde e blu; Possibili colori = (28)3 = 16.777.216 STRUTTURA, MEMORIZZAZIONE E INTERPRETAZIONE DI UNA IMMAGINE (3) Alpha byte: 0 il pixel è completamente trasparente senza tener conto del valore dei color byte; 255 il pixel è completamente opaco con il colore del pixel esclusivamente determinato dal valore assunto dai tre color byte; (0–255) il pixel mostrerà il colore determinato dai tre color byte in maniera sempre più evidente. COMPRESSIONE DELLE IMMAGINI (1) La compressione è l’atto di ridurre lo spazio occupato da un oggetto, agendo sugli elementi costitutivi dell’oggetto stesso. In informatica un oggetto è un file, un insieme di file, e cioè un insieme di bit. Comprimere un oggetto informatico = diminuire il numero di 1 e di 0, ovvero di bit, che lo compongono. Compressione nel mondo fisico ≠ compressione nel mondo informatico. COMPRESSIONE DELLE IMMAGINI (2) Come si attua la compressione? Usando un algoritmo di compressione ossia un insieme dei calcoli aventi per scopo la riduzione delle dimensioni di un file o di un insieme di file. Proprietà fondamentale di un algoritmo di compressione: Reversibilità capacità di leggere i file che sono stati compressi con un particolare formato, ripristinando l’informazione in essi contenuta, cioè decomprimendoli. COMPRESSIONE DELLE IMMAGINI (3) Esistono numerosi formati di compressione. Le differenze sono date dalla misura della reversibilità: Formato lossless è in grado di restituire, al termine della decompressione, un’immagine esattamente uguale - pixel per pixel - all’originale com’era prima che venisse compresso; Formato lossy non è in grado di assicurare una reversibilità assoluta. IL FORMATO GIF (1) La sigla GIF sta per Graphics Interchange Format, un formato grafico sviluppato alla fine degli anni ‘80 da CompuServe. La compressione operata da GIF usa l’algoritmo LZW, che è un criterio di compressione non distruttivo. L’algoritmo LZW usa un dizionario delle stringhe di simboli ricorrenti nel file, costruito in modo tale che ad ogni nuovo termine aggiunto al dizionario sia accoppiata in modo esclusivo un’unica stringa. Il risparmio di spazio in un file compresso con LZW dipende dal fatto che il numero di bit necessari a codificare il “termine” che rappresenta una stringa nel dizionario è inferiore al numero di bit necessari a scrivere nel file non compresso tutti i caratteri che compongono la stringa. IL FORMATO GIF (2) Fa uso di una tavolozza indicizzata di al più 256 colori inglobati nel file GIF generato sensibile perdita di informazioni quando l’immagine di partenza è codificata in uno spazio colore RGB; 1 bit per pixel immagini in bianco e nero; al crescere del numero dei bit per pixel avremo formati GIF con 4, 8, 16, 32, 64, 128 o 256 colori; è prevista l’opzione interlacciamento; due versioni: 87a e 89a. Quest’ultima supporta sia trasparenza sia animazione. STANDARD JPEG JPEG (Joint Photographic Expert Group) è uno standard di compressione distruttiva per le immagini a tono continuo sia a colori sia in bianco e nero. Da immagine non compressa a immagine compressa Jpeg: 1) 2) 3) 4) 5) 6) Trasformazione dello spazio colore; Riduzione, in base alla componente, di gruppi di pixel a valori medi; DCT applicata a blocchi di 8 x 8 pixel suddivisi in base alla componente; Divisione e arrotondamento all’intero dei 64 valori ottenuti con la DCT; Compressione non distruttiva dei coefficienti quantizzati; Inserimento nel file compresso di intestazioni e parametri per la decompressione. UN ESEMPIO DI STEGANOGRAFIA Analisi di una applicazione Java che, sfruttando i principi della steganografia, consente di nascondere un messaggio all’interno di una immagine. Il file contenitore che ospiterà il messaggio da occultare è una immagine nei formati gif o jpg. STRUTTURA DELLA APPLICAZIONE DI STEGANOGRAFIA E’ composta da due programmi: Il programma driver detto ImgDriver : 1) 2) 3) 4) 5) 6) estrae i pixel da un’immagine; converte i valori dei pixel in dati interi; memorizza i valori dei pixel all’interno di un array tridimensionale di interi; passa l’array tridimensionale di interi all’ImgProcessing; ottiene l’array tridimensionale di interi, modificato secondo l’algoritmo di steganografia, dall’ImgProcessing; visualizza l’immagine originale, l’immagine modificata ed una serie di informazioni di output. Il programma di processing detto ImgProcessing : 1) 2) 3) riceve i valori dei pixel all’interno di un array tridimensionale di interi; processa questi dati mediante l’algoritmo di steganografia implementato; restituisce un array tridimensionale di interi contenente i valori modificati dei pixel. APPLICAZIONE DI STEGANOGRAFIA (1) Due versioni che differiscono unicamente per il programma di processing impiegato. Ciascun programma di processing implementa un diverso algoritmo di steganografia: ImgProcessingFourBit un carattere per pixel; caratteri a 8 bit; modifica i 4 LSB del rosso e del verde in un pixel e memorizza il messaggio in pixel adiacenti. ImgProcessingTwoBit un carattere per pixel; caratteri a 6 bit; modifica i 2 LSB del rosso, del verde e del blu in un pixel, memorizza il messaggio a partire da un pixel interno all’immagine e calcola un salto casuale al successivo pixel da modificare. APPLICAZIONE DI STEGANOGRAFIA (2) Ciascuna versione dell’applicazione viene eseguita digitando da linea di comando: java ImgDriver ImgProcessingFourBit NomeImmagine oppure java ImgDriver ImgProcessingTwoBit NomeImmagine Se non è specificata nessuna immagine da linea di comando, il programma cercherà una immagine nella directory corrente chiamata bandieraItalia.jpg. Se nè il programma di processing nè l’immagine sono specificati allora il programma verrà terminato mostrando un messaggio di errore. ImgDriver (1) rawImage oneDPix threeDPix threeDPix è passato al programma di processing Ottenuto con il metodo convertToThreeDim Ottenuto con il metodo convertToOneDim modImg oneDPix threeDPixMod rawImage e modImg contengono rispettivamente l’immagine originale e l’immagine modificata in forma grezza; oneDPix è un 1D array di interi avente un pixel per elemento; threeDPix e threeDPixMod sono 3D array di interi così strutturati: int[righe][colonne][colori] Le prime due dimensioni dell’array corrispondono alle righe e alle colonne dell’immagine. La terza dimensione ha sempre 4 valori che corrispondono ai colori di ciascun pixel così indicizzati: 0 alpha, 1 rosso, 2 verde, 3 blu ImgDriver (2) int[][][] convertToThreeDim(int[] oneDPix,int imgCols,int imgRows) { //Si istanzia il 3D array che conterrà l'immagine. int[][][] data = new int[imgRows][imgCols][4]; for(int row = 0; row < imgRows; row++) { //Si estrae una riga di pixel per volta e la si memorizza in un array di interi temporaneo. int[] aRow = new int[imgCols]; for(int col = 0; col < imgCols; col++) { int element = row * imgCols + col; aRow[col] = oneDPix[element]; } //end for loop su colonne. //Si spostano i dati della riga nel 3D array. Si fa uso dell'operazione //di AND bit a bit e dello SHIFT a destra per selezionare i dati corretti. for(int col = 0; col < imgCols; col++) { //Alpha data[row][col][0] = (aRow[col] >> 24) & 0xFF; //Rosso data[row][col][1] = (aRow[col] >> 16) & 0xFF; //Verde data[row][col][2] = (aRow[col] >> 8) & 0xFF; //Blu data[row][col][3] = (aRow[col]) & 0xFF; } //end for loop su colonne. } //end for loop su righe. return data; } //end convertToThreeDim ImgDriver (3) int[] convertToOneDim(int[][][] data,int imgCols,int imgRows) { //Si istanzia il 1D array che conterrà i pixel dell'immagine come interi. int[] oneDPix = new int[imgCols * imgRows]; //Si spostano i dati nel 1D array. Si fa uso degli //operatori di OR bit a bit e di SHIFT a sinistra //per mettere i quattro byte in un dato intero. for(int row = 0,cnt = 0; row < imgRows; row++) { for(int col = 0; col < imgCols; col++) { oneDPix[cnt] = ((data[row][col][0] << 24) & 0xFF000000) | ((data[row][col][1] << 16) & 0x00FF0000) | ((data[row][col][2] << 8) & 0x0000FF00) | ((data[row][col][3]) & 0x000000FF); cnt++; } //end for loop su colonne. } //end for loop su righe. return oneDPix; } //end convertToOneDim PROGRAMMA DI PROCESSING (1) Entrambe i programmi di processing ImgProcessingFourBit e ImgProcessingTwoBit implementano l’interfaccia ImgInterface: import java.io.*; interface ImgInterface { int[][][] processImg (int[][][] threeDPix, int imgRows, int imgCols) throws IOException; } //end ImgInterface Il primo parametro è un reference al 3D array di interi (contenente il valore dei pixel non modificati), il secondo ed il terzo sono rispettivamente il numero di righe e di colonne dell’immagine. Il metodo restituisce un 3D array di interi contenente il valore dei pixel modificati secondo l’algoritmo di steganografia implementato nel corpo del metodo. PROGRAMMA DI PROCESSING (2) da ImgDriver threeDPix imgRows imgCols processImg temp3D a ImgDriver immagine modificata threeDPix è il 3D array di interi costruito da ImgDriver a partire dalla immagine originale; imgRows e imgCols sono righe e colonne dell’immagine; processImg è il metodo implementato dal programma di processing per realizzare l’algoritmo di steganografia; temp3D è il 3D array di interi modificato restituito a ImgDriver. ImgProcessingFourBit inserimento messaggio temp3D msg copia di threeDPix stringa contenente testo nello standard Unicode msgBytes fourBitBytes testo a 8 bit per carattere array contenente un gruppo da 4 bit per byte temp3D 3D array modificato con un carattere per pixel estrazione messaggio temp3D ExtractedFourBitBytes extracedMsg 3D array modificato con un carattere per pixel array contenente un gruppo da 4 bit per byte stringa contenente testo estratto nello standard Unicode ciascuno dei due gruppi di bit in un carattere da 8 bit viene memorizzato nei 4 LSB del rosso e del verde del pixel selezionato; i caratteri sono memorizzati a partire da un punto interno all’immagine e sempre in pixel adiacenti. ImgProcessingTwoBit inserimento messaggio temp3D msg msgUpper copia di threeDPix stringa contenente stringa con testo nello caratteri in standard Unicode maiuscolo-32 msgBytes twoBitBytes testo a 6 bit per carattere array contenente una coppia di bit per byte temp3D 3D array modificato con un carattere per pixel estrazione messaggio temp3D ExtractedTwoBitBytes extracedMsg 3D array modificato con un carattere per pixel array contenente una coppia di bit per byte stringa contenente testo estratto nello standard Unicode ciascuna delle tre coppie di bit in un carattere da 6 bit viene memorizzata nei 2 LSB del rosso, verde e blu del pixel prescelto; il messaggio è nascosto a partire da un qualsiasi pixel interno all’immagine; il messaggio non è nascosto in pixel tra loro adiacenti. Si usa il valore contenuto nei 2 LSB del blu per determinare il numero di pixel da saltare prima di modificare un altro pixel. CONCLUSIONI ImgProcessingFourBit : semplice e poco accorto nel modificare i bit meno significativi dei color byte; l’introduzione di un breve messaggio all’interno dell’immagine può essere rilevata da parte di un osservatore; la presenza del messaggio sarebbe ancora più evidente se il testo da inserire fosse abbastanza lungo. ImgProcessingTwoBit : ottimi risultati sia nel caso di messaggi brevi che nel caso di messaggi lunghi; modifica di 2 soli LSB per color byte; il successivo pixel da modificare è scelto in modo casuale in base al valore assunto dai 2 LSB del blu nel pixel appena modificato.