Tempo fa ho scritto il mio . Quel post era dedicato a un problema piuttosto interessante, ovvero la steganografia. Certo, la soluzione proposta in quel vecchio topic non può essere definita steganografia nel vero senso della parola. È semplicemente un gioco con i formati dei file, ma rimane comunque un gioco piuttosto intrigante.
Oggi cercheremo di andare un po' più a fondo e analizzeremo l'algoritmo LSB. Se vi interessa, siete i benvenuti sotto il tag. (Sotto il tag, il traffico: circa un megabyte.)
Prima di tutto, è necessario fare una piccola introduzione. È risaputo che lo scopo della crittografia è rendere impossibile la lettura delle informazioni segrete. Naturalmente, la crittografia ha i suoi campi di applicazione, ma c'è anche un altro approccio alla protezione dei dati. Non è necessario crittografare le informazioni, ma si può semplicemente far finta che non ci siano. È per questo che è stata ideata la steganografia. Wikipedia ci assicura che «la steganografia (dal greco στεγανοσ — nascosto e γραφω — scrivo, letteralmente 'scrittura segreta') è la scienza della trasmissione nascosta di informazioni mediante la segretezza del fatto stesso della trasmissione.»
Certo, non ci sono divieti nell'unire metodi crittografici e steganografici. Anzi, è proprio quello che si fa in pratica, ma il nostro obiettivo è comprendere le basi. Se si esamina attentamente l'articolo su Wikipedia, si può scoprire che negli algoritmi di steganografia si parla di un contenitore e di un messaggio. Il contenitore è qualsiasi informazione che aiuta a nascondere il nostro messaggio segreto.
Nel nostro caso, il contenitore sarà un'immagine in formato BMP. Iniziamo analizzando la struttura di questo file. Possiamo suddividere il file in quattro parti: l'intestazione del file, l'intestazione dell'immagine, la tavolozza e l'immagine stessa. Per i nostri scopi, è necessario sapere solo ciò che è registrato nell'intestazione.
I primi due byte dell'intestazione sono la firma BM, seguiti da una parola doppia che registra la dimensione del file in byte, i successivi 4 byte sono riservati e devono contenere zeri e, infine, in un'altra parola doppia è registrato lo spostamento dall'inizio del file ai byte dell'immagine. In un file bmp a 24 bit, ogni pixel è codificato in tre byte BGR.
Ora sappiamo come accedere all'immagine, resta da capire come possiamo scrivere le informazioni necessarie. A questo serve il metodo LSB. La sostanza del metodo consiste nel sostituire i bit meno significativi nei byte che codificano il colore. Supponiamo che il prossimo byte del nostro messaggio segreto sia 11001011 e i byte nell'immagine siano… 11101100 01001110 01111100 0101100111…, la codifica apparirà quindi in questo modo. Suddivideremo il byte del messaggio segreto in 4 parti di due bit: 11, 00, 10, 11, e sostituiremo i bit meno significativi dell'immagine con i frammenti ottenuti: … 11101111 01001100 01111110 0101100111…. Questa sostituzione in generale non è percepibile ad occhio nudo. Inoltre, molti vecchi dispositivi di output potrebbero anche non essere in grado di visualizzare tali variazioni insignificanti.
È chiaro che non possiamo cambiare solo 2 bit meno significativi, ma qualsiasi loro quantità. Qui c'è la seguente regola: maggiore è il numero di bit che cambiamo, maggiore è la quantità di informazioni che possiamo nascondere, e maggiori saranno le interferenze nell'immagine originale. Per esempio, ecco due immagini:


Nonostante tutto, non sono riuscito a vedere differenze tra di loro; tuttavia, nella seconda immagine, grazie al metodo descritto, è nascosta la poesia di Lewis Carroll "La ricerca dello Snark". Se sei arrivato fin qui, sicuramente ti interessa conoscere anche l'implementazione. È piuttosto semplice, ma ti avviso subito che è stata realizzata in Delphi. Le ragioni sono due: 1. Credo che Delphi sia un buon linguaggio; 2. Questo programma è nato durante la preparazione di un corso sulle basi della visione artificiale, e i ragazzi a cui insegno non conoscono ancora nulla oltre Delphi. Per chi non è familiare con la sintassi, è necessario chiarire una cosa: shl x – spostamento bit a sinistra di x, shr x – spostamento bit a destra di x.
Supponiamo di scrivere in un contenitore un testo memorizzato in una stringa e di sostituire i due byte meno significativi:
Codice per la scrittura:
for i:=1 to length(str) do
begin
l1:=byte(str[i]) shr 6;
l2:=byte(str[i]) shl 2; l2:=l2 shr 6;
l3:=byte(str[i]) shl 4; l3:=l3 shr 6;
l4:=byte(str[i]) shl 6; l4:=l4 shr 6;
f.ReadBuffer(tmp,1);
f.Position:=f.Position-1;
tmp:=((tmp shr 2) shl 2)+l1;
f.WriteBuffer(tmp,1);
f.ReadBuffer(tmp,1);
f.Position:=f.Position-1;
tmp:=((tmp shr 2) shl 2)+l2;
f.WriteBuffer(tmp,1);
f.ReadBuffer(tmp,1);
f.Position:=f.Position-1;
tmp:=((tmp shr 2) shl 2)+l3;
f.WriteBuffer(tmp,1);
f.ReadBuffer(tmp,1);
f.Position:=f.Position-1;
tmp:=((tmp shr 2) shl 2)+l4;
f.WriteBuffer(tmp,1);
end;
codice per la lettura:
for i:=1 to MsgSize do
begin
f.ReadBuffer(tmp,1);
l1:=tmp shl 6;
f.ReadBuffer(tmp,1);
l2:=tmp shl 6; l2:=l2 shr 2;
f.ReadBuffer(tmp,1);
l3:=tmp shl 6; l3:=l3 shr 4;
f.ReadBuffer(tmp,1);
l4:=tmp shl 6; l4:=l4 shr 6;
str:=str+char(l1+l2+l3+l4);
end;
E per i completamente pigri – .
Grazie.
Fonte: habr.com
