Egyszer régen megírtam az én
Ma megpróbálunk egy kicsit mélyebbre ásni, és megvizsgáljuk az LSB algoritmust. Ha érdekel, várjuk a cat alá. (A vágás alatt a forgalom: körülbelül egy megabájt.)
Mindenekelőtt egy rövid bevezetőt kell készíteni. Mindenki tudja, hogy a kriptográfia célja, hogy lehetetlenné tegye a titkos információk olvasását. Természetesen a kriptográfiának megvannak a maga alkalmazásai, de van egy másik megközelítés is az adatvédelemben. Nem kell titkosítanunk az információt, hanem úgy teszünk, mintha nem rendelkeznénk vele. Pontosan ezért találták fel a szteganográfiát. A Wikipédia biztosít minket arról, hogy „a szteganográfia (a görög στεγανοσ - rejtett és a görög γραφω - én írom, szó szerint "titkos írás") tudománya az információ rejtett továbbításának tudománya azáltal, hogy az átvitel tényét titokban tartja.
Természetesen senki sem tiltja a kriptográfiai és szteganográfiai módszerek kombinálását. Ráadásul a gyakorlatban ezt meg is teszik, de a mi feladatunk az alapok megértése. Ha figyelmesen áttanulmányozza a Wikipédia cikket, rájön, hogy a szteganográfiai algoritmusok között szerepel az ún. konténer és üzenet. A konténer minden olyan információ, amely segít elrejteni titkos üzenetünket.
Esetünkben a tároló egy BMP formátumú kép lesz. Először is nézzük meg ennek a fájlnak a szerkezetét. A fájl 4 részre osztható: fájlfejléc, képfejléc, paletta és maga a kép. Célunkhoz csak azt kell tudnunk, hogy mi van a fejlécben.
A fejléc első két bájtja a BM aláírás, majd a fájl mérete bájtban dupla szóban van írva, a következő 4 bájt le van foglalva és nullákat kell tartalmaznia, végül egy másik dupla szó tartalmazza az eltolást a fájlt a kép tényleges bájtjaira. Egy 24 bites bmp fájlban minden képpont három BGR bájttal van kódolva.
Most már tudjuk, hogyan juthatunk el a képhez, csak azt kell megérteni, hogyan írhatjuk oda a szükséges információkat. Ehhez szükségünk lesz az LSB módszerre. A módszer lényege a következő: a színkódolásért felelős bájtokban a legkisebb jelentőségű biteket cseréljük ki. Tegyük fel, hogy ha titkos üzenetünk következő bájtja 11001011, és a képen lévő bájtok...11101100 01001110 01111100 0101100111..., akkor a kódolás így fog kinézni. A titkos üzenet bájtját felosztjuk 4 kétbites részre: 11, 00, 10, 11, és a kép alacsony rendű bitjeit a kapott töredékekre cseréljük: ...11101111 01001100 01111110 0101100111… Az ilyen csere az emberi szem számára általában nem észrevehető. Ráadásul sok régebbi kimeneti eszköz nem is képes ilyen kisebb változtatásokat megjeleníteni.
Nyilvánvaló, hogy nem csak a 2 legkisebb jelentőségű bitet módosíthatja, hanem tetszőleges számút. A következő minta van: minél több bitet változtatunk, annál több információt tudunk elrejteni, és ez annál nagyobb interferenciát okoz az eredeti képben. Például itt van két kép:
Minden igyekezetem ellenére nem láttam a különbséget köztük, de ennek ellenére a második képen a leírt módszerrel Lewis Carroll „A Snark vadászata” című verse rejtőzik. Ha idáig elolvasta, valószínűleg érdekli a megvalósítás. Nagyon egyszerű, de azonnal figyelmeztetlek, hogy minden a Delphiben megtörtént. Ennek két oka van: 1. Szerintem a Delphi egy jó nyelv; 2. Ez a program a számítógépes látás alapjairól szóló tanfolyam előkészítése során született, és a srácok, akiknek ezt a kurzust tartom, még nem tudnak semmit a Delphi-n kívül. Azok számára, akik nem ismerik a szintaxist, egy dolgot kell elmagyarázni: az shl x bitenkénti eltolás x-szel balra, az shr x bitenkénti eltolás x-szel jobbra.
Feltételezzük, hogy egy karakterláncban tárolt szöveget írunk a tárolóba, és lecseréljük az alsó két bájtot:
Felvételi kód:
for i:=1 to long(str) do
kezdődik
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.Pozíció:=f.Pozíció-1;
tmp:=((tmp shr 2) shl 2)+l1;
f.WriteBuffer(tmp,1);
f.ReadBuffer(tmp,1);
f.Pozíció:=f.Pozíció-1;
tmp:=((tmp shr 2) shl 2)+l2;
f.WriteBuffer(tmp,1);
f.ReadBuffer(tmp,1);
f.Pozíció:=f.Pozíció-1;
tmp:=((tmp shr 2) shl 2)+l3;
f.WriteBuffer(tmp,1);
f.ReadBuffer(tmp,1);
f.Pozíció:=f.Pozíció-1;
tmp:=((tmp shr 2) shl 2)+l4;
f.WriteBuffer(tmp,1);
end;
leolvasható kód:
i:=1 esetén MsgSize do
kezdődik
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;
Nos, az igazán lustáknak...
Köszönöm.
Forrás: will.com