Ciò che caratterizza la steganografia,
come si è visto, è l'esistenza di un secondo messaggio facilmente
percepibile, il cui senso è generalmente del tutto disgiunto da quello
del messaggio segreto che esso contiene. Nel seguito si indicherà questo
secondo messaggio come messaggio contenitore o più semplicemente contenitore.
Come si può facilmente immaginare, le nuove
tecnologie e in particolar modo i sistemi per l'elaborazione dell'informazione,
hanno consentito anche nel caso della steganografia la progettazione di nuove
tecniche, sempre più sofisticate, sicure e pratiche da usare. Questo
capitolo cercherà proprio di esporre le idee che stanno alla base dei
più diffusi programmi per computer che consentono di steganografare un
messaggio dentro un altro. Le prime definizioni proposte riguardano l'origine
del file contenitore: alcune tecniche - probabilmente le più numerose
- come si vedrà consentono di "iniettare" il messaggio segreto
dentro un messaggio contenitore già esistente, modificandolo in modo
tale sia da contenere il messaggio sia da risultare, al livello al quale viene
percepito dai sensi umani, praticamente indistinguibile dall'originale. Indichiamo
l'insieme di queste tecniche con il termine steganografia iniettiva. Esistono
tuttavia altre tecniche steganografiche che hanno capacità proprie di
generare potenziali messaggi contenitori e utilizzano il messaggio segreto per
"pilotare" il processo di generazione del contenitore. Per queste
tecniche adottiamo il termine steganografia generativa. Alla fine del capitolo
verranno passati in rassegna esempi di programmi di entrambi i tipi.
Secondo un sistema di classificazione diverso,
le tecniche steganografiche possono essere ripartite in tre classi: steganografia
sostitutiva, steganografia selettiva e steganografia costruttiva.
Le tecniche del primo tipo sono di gran lunga
le più diffuse, tanto che in genere con il termine steganografia ci si
riferisce implicitamente a esse. Tali tecniche si basano sulla seguente osservazione:
la maggior parte dei canali di comunicazione (linee telefoniche, trasmissioni
radio, ecc.) trasmettono segnali che sono sempre accompagnati da qualche tipo
di rumore. Questo rumore può essere sostituito da un segnale - il messaggio
segreto - che è stato trasfor mato in modo tale che, a meno di conoscere
una chiave segreta, è indistinguibile dal rumore vero e proprio, e quindi
può essere trasmesso senza destare sospetti.
Quasi tutti i programmi che sono facilmente reperibili
si basano su questa idea, sfruttando la grande diffusione di file contenenti
una codifica digitale di immagini, animazioni e suoni; spesso questi file sono
ottenuti da un processo di conversione analogico/digitale e contengono qualche
tipo di rumore. Per esempio, uno scanner può essere visto come uno strumento
di misura più o meno preciso. Un'immagine prodotta da uno scanner, da
questo punto di vista, è il risultato di una specifica misura e come
tale è soggetta a essere affetta da errore.
La tecnica base impiegata dalla maggior parte
dei programmi, consiste semplicemente nel sostituire i "bit meno significativi"
delle immagini digitalizzate con i bit che costituiscono il file segreto (i
bit meno significativi sono assimilabili ai valori meno significativi di una
misura, cioè quelli che tendono a essere affetti da errori.) Spesso l'immagine
che ne risulta non è distinguibile a occhio nudo da quella originale
ed è comunque difficile dire se eventuali perdite di qualità siano
dovute alla presenza di informazioni nascoste oppure all'errore causato dall'impiego
di uno scanner poco preciso, o ancora alla effettiva qualità dell'immagine
originale prima di essere digitalizzata. Per fissare meglio le idee, ecco un
esempio concreto. Uno dei modi in cui viene solitamente rappresentata un'immagine
prodotta da uno scanner è la codifica RGB a 24 bit: l'immagine consiste
di una matrice MxN di punti colorati (pixel) e ogni punto è rappresentato
da 3 byte, che indicano rispettivamente i livelli dei colori primari rosso (Red),
verde (Green) e blu (Blue) che costituiscono il colore. In questo modello i
colori possibili sono 224 = 16777216; i cosiddetti grigi sono i colori in cui
i livelli di rosso, verde e blu sono coincidenti e quindi sono soltanto 256.
Supponiamo che uno specifico pixel di un'immagine prodotta da uno scanner sia
rappresentato dalla tripla (12, 241, 19) (si tratta di un colore tendente al
verde, dato che la componente verde predomina fortemente sulle altre due); in
notazione binaria, le tre componenti sono:
===============
12 = 00001100
241 = 11110001
19 = 00010011
===============
quelli che in precedenza abbiamo chiamato i "bit meno significativi"
dell'immagine sono gli ultimi a destra, cioè 0-1-1, e sono proprio quelli
che si utilizzano per nascondere il messaggio segreto. Se volessimo nascondere
in quel pixel l'informazione data dalla sequenza binaria 101, allora bisognerebbe
effettuare la seguente trasformazione:
==============================
00001100 --> 00001101 = 13
11110001 --> 11110000 = 240
00010011 --> 00010011 = 19
==============================
La tripla è così diventata (13, 240, 19); si noti che questo tipo
di trasformazione consiste nel sommare 1, sottrarre 1 o lasciare invariato ciascun
livello di colore primario, quindi il colore risultante differisce in misura
minima da quello originale. Dato che un solo pixel può contenere un'informazione
di 3 bit, un'immagine di dimensioni MxN può contenere un messaggio segreto
lungo fino a (3*M*N)/8 byte, per esempio un'immagine 1024x768 può contenere
294912 byte.
La tecnica appena descritta rappresenta il cuore
della steganografia sostitutiva, anche se di fatto ne esistono numerose variazioni.
Innanzitutto è ovvio che tutto quello che abbiamo detto vale non solo
per le immagini, ma anche per altri tipi di media, per esempio suoni e animazioni
digitalizzati. Inoltre - e questo è meno ovvio - lavorando con le immagini
come file contenitori non sempre si inietta l'informazione al livello dei pixel,
ma si è costretti a operare su un livello di rappresentazione intermedio;
è questo il caso, per esempio, delle immagini in formato JPEG, nel quale
le immagini vengono memorizzate solo dopo essere state compresse con una tecnica
che tende a preservare le loro caratteristiche visive piuttosto che l'esatta
informazione contenuta nella sequenza di pixel. Se iniettassimo delle informazioni
in una bitmap e poi la salvassimo in formato JPEG, le infor mazioni andrebbero
perdute, poiché non sarebbe possibile ricostruire la bitmap originale.
Per poter utilizzare anche le immagini JPEG come contenitori, è tuttavia
possibile iniettare le informazioni nei coefficienti di Fourier ottenuti dalla
prima fase di compressione.
Esiste un altro caso interessante che merita di
essere discusso, ed è quello dei formati di immagini che fanno uso di
palette. La palette (tavolozza) è un sottoinsieme prestabilito di colori.
Nei for mati che ne fanno uso, i pixel della bitmap sono vincolati ad assumere
come valore uno dei colori presenti nella palette: in questo modo è possibile
rappresentare i pixel con dei puntatori alla palette, invece che con la terna
esplicita RGB (red, green and blue). Ciò in genere permette di ottenere
dimensioni inferiori della bitmap, ma il reale vantaggio è dato dal fatto
che le schede grafiche di alcuni anni fa utilizzavano proprio questa tecnica
e quindi non potevano visualizzare direttamente immagini con un numero arbitrario
di colori. Il caso più tipico è quello delle immagini in for mato
GIF con palette di 256 colori, ma le palette possono avere anche altre dimensioni.
Come è facile immaginare, un'immagine appena prodotta da uno scanner
a colori sarà tipicamente costituita da più di 256 colori diversi,
tuttavia esistono algoritmi capaci di ridurre il numero dei colori utilizzati
mantenendo il degrado della qualità entro limiti accettabili. Si può
osservare che, allo stesso modo in cui avviene con il formato JPEG, non è
possibile iniettare infor mazioni sui pixel prima di convertire l'immagine in
formato GIF, perché durante il processo di conversione c'è perdita
di informazione (osserviamo anche che questo non vale per le immagini a livelli
di grigi: tali immagini infatti sono particolarmente adatte per usi steganografici.)
La soluzione che viene di solito adottata per usare immagini GIF come contenitori
è dunque la seguente: si riduce il numero dei colori utilizzati dall'immagine
a un valore inferiore a 256 ma ancora sufficiente a mantenere una certa qualità
dell'immagine, dopodiché si finisce di riempire la palette con colori
molto simili a quelli rimasti. A questo punto, per ogni pixel dell'immagine,
la palette contiene più di un colore che lo possa rappresentare (uno
è il colore originale, gli altri sono quelli simili ad esso che sono
stati aggiunti in seguito), quindi abbiamo una possibilità di scelta.
Tutte le volte che abbiamo una possibilità di scelta fra più alternative,
abbiamo la possibilità di nascondere un'infor mazione: questo è
uno dei principi fondamentali della steganografia. Se le alternative sono due
possiamo nascondere un bit (se il bit è 0, scegliamo la prima, se è
1 la seconda); se le alternative sono quattro possiamo nascondere due bit (00
-> la prima, 01 -> la seconda, 10 -> la terza, 11 -> la quarta)
e così via.
La soluzione appena discussa dell'utilizzo di
GIF come contenitori è molto ingegnosa ma purtroppo presenta un problema:
è facile scrivere un programma che, presa una GIF in ingresso, analizzi
i colori utilizzati e scopra le relazioni che esistono tra di essi; se il programma
scopre che l'insieme dei colori utilizzati può essere ripartito in sottoinsiemi
di colori simili, è molto probabile che la GIF contenga infor mazione
steganografata. Di fatto, questo semplice metodo di attacco è stato portato
avanti con pieno successo da diverse persone ai programmi che utilizzano immagini
a palette come contenitori, tanto che qualcuno ha finito per sostenere che non
è possibile fare steganografia con esse.
Per mostrare quanto sia ampia la gamma di tecniche
steganografiche, accenniamo a un'altra possibilità di nascondere informazioni
dentro immagini GIF. Come abbiamo detto, in questo formato viene prima memorizzata
una palette e quindi la bitmap (compressa con un algoritmo che preserva completamente
le infor mazioni) consistente di una sequenza di puntatori alla palette. Se
scambiamo l'ordine di due colori della palette e corrispondentemente tutti i
puntatori ad essi, otteniamo un file diverso che corrisponde però alla
stessa immagine, dal punto di vista dell'immagine il contenuto informativo dei
due file è identico. La rappresentazione di immagini con palette è
quindi intrinsecamente ridondante, dato che ci permette di scegliere un qualsiasi
ordine dei colori della palette (purché si riordinino corrispondentemente
i puntatori a essi). Se i colori sono 256, esistono 256! modi diversi di scrivere
la palette, quindi esistono 256! file diversi che rappresentano la stessa immagine.
Inoltre è abbastanza facile trovare un metodo per numerare univocamente
tutte le permutazioni di ogni data palette (basta, per esempio, considerare
l'ordinamento sulle componenti RGB dei colori). Dato che abbiamo 256! possibilità
di scelta, è possibile codificare log(256!) = 1683 bit, cioè 210
byte. Si noti che questo numero è indipendente dalle dimensioni dell'immagine,
in altre parole è possibile iniettare 210 bytes anche su piccole immagini
del tipo icone 16x16 semplicemente permutando in modo opportuno la palette.
Dopo avere esaminato alcune tecniche steganografiche
di tipo sostitutivo, discutiamo adesso i problemi relativi alla loro sicurezza.
Innanzitutto premettiamo che le norme che valgono generalmente per i programmi
di crittografia dovrebbero essere osservate anche per l'utilizzo dei programmi
steganografici. Per ciò che riguarda le specifiche caratteristiche della
steganografia, si tengano presente i seguenti principi: in primo luogo si eviti
di usare come contenitori file prelevati da siti pubblici o comunque noti (per
esempio, immagini incluse in pacchetti software, ecc.); in secondo luogo si
eviti di usare più di una volta lo stesso file contenitore (l'ideale
sarebbe quello di generarne ogni volta di nuovi, mediante scanner e convertitori
da analogico a digitale, e distruggere gli originali dopo averli usati).
Come si è visto, queste tecniche consistono
nel sostituire un elemento di scarsa importanza (in certi casi di importanza
nulla) da file di vario tipo, con il messaggio segreto che vogliamo nascondere.
Quello che viene ritenuto il principale difetto di queste tecniche è
che in genere la sostituzione operata può alterare le caratteristiche
statistiche del rumore presente nel media utilizzato. Lo scenario è il
seguente: si suppone che il nemico disponga di un modello del rumore e che utilizzi
tale modello per controllare i file che riesce a intercettare. Se il rumore
presente in un file non è conforme al modello, allora il file è
da considerarsi sospetto. Si può osservare che questo tipo di attacco
non è per niente facile da realizzare, data l'impossibilità pratica
di costruire un modello che tenga conto di tutte le possibili sorgenti di errori/
rumori, tuttavia in proposito esistono degli studi che in casi molto specifici
hanno avuto qualche successo.
La steganografia selettiva e quella costruttiva
hanno proprio lo scopo di eliminare questo difetto della steganografia sostitutiva.