LSB steganografie

Kdysi dávno jsem napsal svůj první příspěvek na habru. Tento příspěvek byl věnován velmi zajímavému problému, a sice steganografii. Samozřejmě, řešení navržené v tom starém tématu nelze nazvat steganografií v pravém slova smyslu. Je to pouhá hra s formáty souborů, ale i přesto je to velmi zajímavá hra.

Dnes se pokusíme kopnout o něco hlouběji a prozkoumáme algoritmus LSB. Pokud máte zájem, srdečně vás zvu pod článek. (Pod článkem je přenos: kolem megabytu.)

Nejprve je třeba udělat malé úvodní vysvětlení. Všichni víme, že účelem kryptografie je znemožnit čtení tajných informací. Samozřejmě, kryptografie má své oblasti použití, ale existuje i jiný přístup k ochraně dat. Můžeme informace nešifrovat, ale udělat, že je nemáme. Právě k tomu byla vymyšlena steganografie. Wikipedie nás ujistí, že „steganografie (z řeckého στεγανοσ – skrytý a γραφω – píšu, doslova 'tajné psaní') je věda o skryté přenosu informací tím, že se tají samotný fakt přenosu.

Samozřejmě, nikdo nezakazuje kombinovat kryptografické a steganografické metody. Ba naopak, v praxi se to takto dělá, ale naším úkolem je porozumět základům. Pokud si pečlivě prostudujeme článek na Wikipedii, zjistíme, že v algoritmech steganografie figuruje tzv. kontejner a zpráva. Kontejner je jakákoliv informace, která pomáhá skrýt naši tajnou zprávu.

V našem případě bude kontejnerem obrázek ve formátu BMP. Nejdříve se podíváme na strukturu tohoto souboru. Soubor lze zjednodušeně rozdělit na 4 části: hlavička souboru, hlavička obrázku, paleta a vlastní obrázek. Pro naše účely potřebujeme vědět jen to, co je zapsáno v hlavičce.

První dva byty hlavičky – to je signatura BM, dále v dvojitém slově je zapsána velikost souboru v bytech, následující 4 byty jsou rezervovány a měly by obsahovat nuly a nakonec v dalším dvojitém slově je zapsán posun od začátku souboru k vlastnímu bytu obrázku. V 24bitovém bmp-souboru je každý pixel kódován třemi byty BGR.

Nyní víme, jak se dostat k obrázku, zbývá pochopit, jak do něj můžeme zapsat potřebné informace. K tomu nám poslouží metoda LSB. Podstata metody spočívá v tom, že nahrazujeme nejnižší bity v bajtech, které odpovídají za kódování barvy. Představme si, že bajt našeho tajného sdělení je – 11001011, a bajty v obrázku jsou – …11101100 01001110 01111100 0101100111…, kódování by vypadalo takto. Rozdělíme bajt tajného sdělení na 4 dvoubity: 11, 00, 10, 11, a nahradíme jimi nejnižší bity obrázku: …11101111 01001100 01111110 0101100111…. Taková výměna není pro lidské oko v zásadě viditelná. Navíc mnoho starších zobrazovacích zařízení nedokáže zobrazit takové nepatrné změny.

Je jasné, že lze měnit nejen 2 nejnižší bity, ale i libovolný jejich počet. Zde platí následující pravidlo: čím více bitů měníme, tím větší objem informací můžeme skrýt, a tím větší rušení v původním obrázku to způsobí. Například vám nabízím dvě obrázky:

LSB steganografie
LSB steganografie

Při veškeré snaze jsem se nedokázal dočkat rozdílu mezi nimi, a přesto v druhém obrázku byla pomocí popsané metody skryta báseň Lewise Carrolla „Hunting of the Snark“. Pokud jste dočetli do tohoto bodu, jistě vás zajímá také realizace. Je poměrně jednoduchá, ale hned varuji, že to je vše napsané v Delphi. Existují k tomu dva důvody: 1. Považuji Delphi za dobrý a decentní jazyk; 2. Tento program vznikl během přípravy kurzu o základech strojového vidění, a studenti, kterým tento kurz vyučuji, zatím znají jen Delphi. Pro ty, kteří nejsou obeznámeni se syntaxí, je třeba vysvětlit jednu věc: shl x – bitový posun vlevo o x, shr x – bitový posun vpravo o x.

Předpokládejme, že zapisujeme do kontejneru text uložený v řetězci a nahrazujeme nejnižší dva bajty:
Kód pro zápis:

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;

Kód pro čtení:

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;

No a pro úplně lenivé – odkaz na program a jeho zdrojový kód.

Děkuji.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster