Egyszer régen írtam az első bejegyzésemet a Habr-ra Ma megpróbálunk egy kicsit mélyebbre ásni és megvizsgáljuk az LSB algoritmust. Ha érdekel, szeretettel várlak a folytatásban. (A folytatásban a forgalom: körülbelül egy megabájt.)
Mindenekelőtt szükséges egy rövid bevezető. Mindenki tudja, hogy a kriptográfia célja a titkos információk elolvasásának lehetetlenné tétele. Természetesen a kriptográfiának megvannak a saját alkalmazási területei, de létezik egy másik megközelítés az adatok védelmére. Nem szükséges titkosítani az információt, hanem úgy is lehet tenni, mintha nem is lenne. Erre való a steganográfia. A Wikipédia azt állítja, hogy a „steganográfia (görögül: στεγανοσ — rejtett és γραφω — írok, szó szerint „titkos írás”) az információ rejtett átadásának tudománya, a tényleges átadás tényének titokban tartásával.
Természetesen senki sem tiltja a kriptográfiai és steganográfiai módszerek egyesítését. Sőt, a gyakorlatban így is tesznek, de a mi feladatunk az alapok megértése. Ha alaposan megvizsgáljuk a Wikipédia cikkét, megtudhatjuk, hogy a steganográfiai algoritmusokban úgynevezett konténer és üzenet szerepel. A konténer bármilyen információ, amely segít elrejteni titkos üzenetünket.
A mi esetünkben a konténer egy BMP formátumú kép lesz. Először is nézzük meg e fájl struktúráját. A fájl alapvetően négy részre bontható: fájlfejléc, képfájl, paletta és maga a kép. Céljainkhoz csak annyit kell tudni, hogy mi van a fejlécben.
A fejléc első két bájtja a BM aláírás, ezt követően egy dupla szóban a fájl mérete bájtban, a következő négy bájt foglalt, és nullákat kell tartalmaznia, végül egy másik dupla szóban az elmozdulás van a fájl előre meghatározott elejétől a kép bájtjainak sajátos helyéig. A 24 bites bmp fájlban minden egyes pixel három bájtban van kódolva BGR formátumban.
A fejléc első két bájtja a BM jelzés, ezt követi egy dupla szó, amely a fájl méretét tárolja bájtokban, a következő 4 bájt fenntartott, és nullákat kell tartalmaznia, és végül egy másik dupla szóban a fájl elejétől a kép bájtjainak eltolása van. A 24-bites bmp-fájlban minden pixel három bájttal van kódolva: BGR.
Most már tudjuk, hogyan juthatunk el a képekhez, most már azt is meg kell értenünk, hogyan rögzíthetjük a szükséges információt. Ehhez a LSB módszer segít. A módszer lényege a következő: helyettesítjük a színkódolásért felelős byte-ok legkisebb biteit. Tegyük fel, hogy a titkos üzenetünk következő byte-ja – 11001011, míg a képek byte-jai –...11101100 01001110 01111100 0101100111…, akkor a kódolás így néz ki. A titkos üzenet byte-ját négy kéthetes részre bontjuk: 11, 00, 10, 11, és a kép legkisebb biteit kicseréljük a kapott darabokra: ...11101111 01001100 01111110 0101100111.... Ilyen helyettesítése általában nem észlelhető az emberi szem számára. Sőt, sok régi kimeneti eszköz nem is tudja megjeleníteni az ilyen apró változásokat.
Nyilvánvaló, hogy nem csupán 2 legkisebb bitet lehet változtatni, hanem bármennyi bitet. Van egy törvényszerűség: minél több bitet változtatunk, annál nagyobb mennyiségű információt tudunk elrejteni, és annál nagyobb zűrzavart okozunk az eredeti képen. Példaként itt van két kép:


Minden kívánság ellenére nem tudtam megkülönböztetni őket, és mégis a második képen a leírt módszer segítségével Lewis Carroll „A Sznarkra vadászat” című versét rejtettük el. Ha idáig eljutott, valószínűleg érdekli a megvalósítás is. Egyszerűen van, de előre figyelmeztetem, hogy mindez Delphi-ben készült. Két oka van ennek: 1. Úgy vélem, a Delphi egy nagyszerű nyelv; 2. Ez a program a gépi látás alapjainak tanfolyama során született, és azok a srácok, akinek ezt a kurzust tartom, egyelőre csak a Delphi-t ismerik. Azoknak, akik nem ismerik a szintaxist, el kell magyarázni egy dolgot: shl x – bit balra tolás x-szel, shr x – bit jobbra tolás x-szel.
Tekintjük, hogy egy szöveget rögzítünk egy konténerbe, amely egy stringben tárolódik, és lecseréljük a legkisebb két byte-ot:
Íme a rögzítő kód:
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;
a kiolvasás kódja:
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;
Nos, a teljesen lusták számára – .
Köszönöm.
Forrás: habr.com
