Cu mult timp în urmă am scris primul meu . Și acel articol a fost dedicat unei probleme destul de interesante, și anume steganografiei. Desigur, soluția propusă în acel vechi topic nu poate fi numită steganografie în adevăratul sens al cuvântului. Este doar un joc cu formatele de fișiere, dar, cu toate acestea, este un joc destul de interesant.
Astăzi vom încerca să săpăm puțin mai adânc și vom analiza algoritmul LSB. Dacă vă interesează, vă rog să citiți mai departe. (Sub articol, traficul: aproximativ un megabyte.)
În primul rând, trebuie să facem o mică introducere. Toată lumea știe că scopul criptografiei este de a face imposibilă citirea informației secrete. Desigur, criptografia are domeniile sale de aplicare, dar există și o altă abordare pentru protecția datelor. Nu este necesar să criptăm informația, ci putem să facem ca aceasta să pară că nu există. Acesta este motivul pentru care a fost inventată steganografia. Wikipedia ne asigură că „steganografia (din grecescul στεγανοσ – ascuns și grecescul γραφω – scriu, literalmente «scriere ascunsă») este știința transmiterii ascunse a informațiilor prin păstrarea în secret a însăși existenței transmiterii.
Desigur, nimeni nu interzice combinarea metodelor criptografice cu cele steganografice. Mai mult decât atât, în practică așa se și face, dar sarcina noastră este să înțelegem elementele de bază. Dacă studiem cu atenție articolul de pe Wikipedia, putem afla că în algoritmii de steganografie apare așa-numitul container și mesaj. Containerul este orice informație care ajută la ascunderea mesajului nostru secret.
În cazul nostru, containerul va fi o imagine în format BMP. Pentru început, să analizăm structura acestui fișier. Fișierul poate fi împărțit, în mod condiționat, în 4 părți: antetul fișierului, antetul imaginii, paleta și imaginea propriu-zisă. Pentru scopurile noastre, trebuie să știm doar ce este scris în antet.
Primele două octeți din antet sunt semnătura BM, apoi, într-un cuvânt dublu, este scrisă dimensiunea fișierului în octeți, următorii 4 octeți sunt rezervați și trebuie să conțină zerouri și, în final, într-un alt cuvânt dublu este scris offset-ul de la începutul fișierului până la adevărații octeți ai imaginii. Într-un fișier BMP de 24 de biți, fiecare pixel este codificat cu trei octeți BGR.
Acum știm cum să ajungem la imagine, rămâne să înțelegem cum putem să scriem informațiile necesare acolo. Pentru aceasta, ne va ajuta metoda LSB. Esența metodei este următoarea: înlocuim biții de ordine inferiori din byte-urile care codifică culoarea. Să presupunem că byte-ul din mesajul nostru secret este 11001011, iar byte-urile din imagine sunt… 11101100 01001110 01111100 01011001 11…, atunci codificarea va arăta așa. Vom împărți byte-ul mesajului secret în 4 părți de câte 2 biți: 11, 00, 10, 11 și vom înlocui biții inferiori ai imaginii cu fragmentele obținute: …11101111 01001100 01111110 01011001 11…. Această înlocuire, în general, nu este observabilă cu ochiul liber. Mai mult, multe dispozitive de ieșire mai vechi nu vor putea chiar să afișeze asemenea schimbări nesemnificative.
Este clar că putem schimba nu doar 2 biți inferiori, ci și orice alt număr. Aici există următoarea regulă: cu cât schimbăm un număr mai mare de biți, cu atât putem ascunde un volum mai mare de informații și cu atât mai mari vor fi deranjamentele în imaginea originală. De exemplu, iată două imagini:


În ciuda tuturor eforturilor, nu am reușit să observ diferența dintre ele, și totuși în a doua imagine, folosind metoda descrisă, este ascunsă poemul lui Lewis Carroll „Căutarea Snarkului”. Dacă ați citit până aici, cu siguranță sunteți interesați să aflați și despre implementare. Este destul de simplă, dar v-aș avertiza încă de la început că totul este făcut în Delphi. Motivele pentru aceasta sunt două: 1. Cred că Delphi este un limbaj bun; 2. Această programă a fost creată în timpul pregătirii unui curs despre principiile viziunii artificiale, iar băieții cărora le predau acest curs nu cunosc altceva în afară de Delphi. Pentru cei care nu sunt familiarizați cu sintaxa, trebuie să explic un lucru: shl x – deplasament pe biți la stânga cu x, shr x – deplasament pe biți la dreapta cu x.
Să presupunem că scriem în container un text, stocat într-un șir și înlocuim cei doi biți inferiori:
Cod pentru scriere:
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;
cod pentru citire:
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;
Și pentru cei complet leneși – .
Mulțumim.
Sursa: habr.com
