Kažkada aš parašiau savo
Šiandien pabandysime pasigilinti ir pažvelgti į LSB algoritmą. Jei susidomėjote, esate laukiami pagal kat. (Po išpjova yra srautas: apie megabaitą.)
Visų pirma, būtina padaryti trumpą įžangą. Visi žino, kad kriptografijos tikslas – padaryti, kad nebūtų įmanoma perskaityti slaptos informacijos. Žinoma, kriptografija turi savo taikymą, tačiau yra ir kitas požiūris į duomenų apsaugą. Mes neturime šifruoti informacijos, bet apsimesti, kad jos neturime. Kaip tik todėl buvo išrasta steganografija. Vikipedija mus patikina, kad „steganografija (iš graikų στεγανοσ – paslėptas ir graikų γραφω – rašau, pažodžiui „slaptas rašymas“) yra mokslas apie paslėptą informacijos perdavimą, išlaikant paslaptyje patį perdavimo faktą.
Žinoma, niekas nedraudžia derinti kriptografinių ir steganografinių metodų. Be to, praktiškai jie tai daro, tačiau mūsų užduotis yra suprasti pagrindus. Atidžiai išstudijavę Vikipedijos straipsnį, sužinosite, kad steganografijos algoritmai apima vadinamuosius. konteineris ir pranešimas. Konteineris yra bet kokia informacija, padedanti paslėpti mūsų slaptą pranešimą.
Mūsų atveju konteineris bus BMP formato vaizdas. Pirmiausia pažvelkime į šio failo struktūrą. Failą galima suskirstyti į 4 dalis: failo antraštę, vaizdo antraštę, paletę ir patį vaizdą. Mūsų tikslams mums tereikia žinoti, kas parašyta antraštėje.
Pirmieji du antraštės baitai yra BM parašas, tada failo dydis baitais rašomas dvigubu žodžiu, kiti 4 baitai yra rezervuoti ir juose turi būti nuliai, o galiausiai kitame dvigubame žodyje yra poslinkis nuo failo pradžios. failą iki tikrųjų vaizdo baitų. 24 bitų bmp faile kiekvienas pikselis yra užkoduotas trimis BGR baitais.
Dabar žinome, kaip pasiekti vaizdą, belieka suprasti, kaip galime ten įrašyti mums reikalingą informaciją. Tam mums reikės LSB metodo. Metodo esmė tokia: baituose, atsakinguose už spalvų kodavimą, pakeičiame mažiausiai reikšmingus bitus. Tarkime, jei kitas mūsų slapto pranešimo baitas yra 11001011, o baitai paveikslėlyje yra...11101100 01001110 01111100 0101100111..., tada kodavimas atrodys taip. Slapto pranešimo baitą padalinsime į 4 dviejų bitų dalis: 11, 00, 10, 11, o žemos eilės vaizdo bitus pakeisime gautais fragmentais: ...11101111 01001100 01111110 0101100111… Toks pakeitimas paprastai nėra pastebimas žmogaus akiai. Be to, daugelis senesnių išvesties įrenginių net negalės rodyti tokių nedidelių pakeitimų.
Akivaizdu, kad galite pakeisti ne tik 2 mažiausiai reikšmingus bitus, bet bet kokį jų skaičių. Yra toks modelis: kuo daugiau bitų pakeisime, tuo daugiau informacijos galime paslėpti ir tuo daugiau trikdžių tai sukels pradiniame vaizde. Pavyzdžiui, čia yra du vaizdai:
Nepaisant visų pastangų, nesugebėjau įžvelgti skirtumo tarp jų, tačiau vis dėlto antrame vaizde, naudojant aprašytą metodą, paslėptas Lewiso Carrollo eilėraštis „Snarko medžioklė“. Jei perskaitėte iki šiol, tikriausiai norite sužinoti apie įgyvendinimą. Tai gana paprasta, bet iš karto perspėsiu, kad viskas daroma Delfyje. Tam yra dvi priežastys: 1. Manau, kad Delphi yra gera kalba; 2. Ši programa gimė ruošiant kompiuterinio matymo pagrindų kursą, o vaikinai, kuriems aš dėstau šį kursą, dar nieko nežino, išskyrus Delphi. Tiems, kurie nėra susipažinę su sintaksė, reikia paaiškinti vieną dalyką: shl x yra bitų poslinkis į kairę x, shr x yra bitų poslinkis į dešinę x.
Darome prielaidą, kad į konteinerį rašome eilutėje saugomą tekstą ir pakeičiame du apatinius baitus:
Įrašymo kodas:
i:=1 iki ilgio(str) daryti
pradėti
l1:=baitas(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.Pozicija:=f.Pozicija-1;
tmp:=((tmp shr 2) shl 2)+l1;
f.WriteBuffer(tmp,1);
f.ReadBuffer(tmp,1);
f.Pozicija:=f.Pozicija-1;
tmp:=((tmp shr 2) shl 2)+l2;
f.WriteBuffer(tmp,1);
f.ReadBuffer(tmp,1);
f.Pozicija:=f.Pozicija-1;
tmp:=((tmp shr 2) shl 2)+l3;
f.WriteBuffer(tmp,1);
f.ReadBuffer(tmp,1);
f.Pozicija:=f.Pozicija-1;
tmp:=((tmp shr 2) shl 2)+l4;
f.WriteBuffer(tmp,1);
pabaigą;
kodas skaityti:
i:=1 iki MsgSize padaryti
pradėti
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);
pabaigą;
Na, o tikrai tinginiams -
Ačiū.
Šaltinis: www.habr.com