LSB-steganografio

Iam mi skribis mian unua afiŝo sur hub. Kaj tiu afiŝo estis dediĉita al tre interesa problemo, nome steganografio. Kompreneble, la solvo proponita en tiu malnova temo ne povas esti nomata steganografio en la vera senco de la vorto. Ĝi estas nur ludo kun dosierformatoj, sed sufiĉe interesa ludo tamen.

Hodiaŭ ni provos fosi iom pli profunde kaj rigardi la LSB-algoritmon. Se vi interesiĝas, vi estas bonvena sub kato. (Sub la tranĉo estas trafiko: ĉirkaŭ megabajto.)

Antaŭ ĉio, necesas fari mallongan enkondukon. Ĉiuj scias, ke la celo de kriptografio estas malebligi legi sekretajn informojn. Kompreneble, kriptografio havas siajn aplikojn, sed ekzistas alia aliro al datuma protekto. Ni ne devas ĉifri la informojn, sed ŝajnigi, ke ni ne havas ĝin. Ĝuste tial estis inventita steganografio. Vikipedio certigas al ni, ke “steganografio (el la greka στεγανοσ – kaŝita kaj la greka γραφω – mi skribas, laŭvorte “sekreta skribo”) estas la scienco de la kaŝita transdono de informoj tenante la fakton mem de transdono sekreta.

Kompreneble, neniu malpermesas kombini kriptografiajn kaj steganografiajn metodojn. Krome, praktike ili faras tion, sed nia tasko estas kompreni la bazaĵojn. Se vi zorge studas la Vikipedian artikolon, vi ekscios, ke steganografiaj algoritmoj inkluzivas la t.n. ujo kaj mesaĝo. Ujo estas ajna informo kiu helpas kaŝi nian sekretan mesaĝon.

En nia kazo, la ujo estos bildo en BMP-formato. Unue, ni rigardu la strukturon de ĉi tiu dosiero. La dosiero povas esti dividita en 4 partojn: dosierkapo, bildokapo, paletro kaj la bildo mem. Por niaj celoj, ni nur bezonas scii kio estas skribita en la kaplinio.

La unuaj du bajtoj de la kaplinio estas la BM-signaturo, tiam la dosiergrandeco en bajtoj estas skribita en duobla vorto, la sekvaj 4 bajtoj estas rezervitaj kaj devas enhavi nulojn, kaj fine, alia duobla vorto enhavas la ofseton de la komenco de la dosiero al la realaj bajtoj de la bildo. En 24-bita bmp-dosiero, ĉiu pikselo estas ĉifrita kun tri BGR-bajtoj.

Nun ni scias kiel atingi la bildon, restas nur kompreni kiel ni povas skribi tie la informojn, kiujn ni bezonas. Por tio ni bezonos la LSB-metodon. La esenco de la metodo estas jena: ni anstataŭigas la malplej signifajn bitojn en la bajtoj respondecaj pri kolorkodado. Ni diru, se la sekva bajto de nia sekreta mesaĝo estas 11001011, kaj la bajtoj en la bildo estas...11101100 01001110 01111100 0101100111..., tiam la kodado aspektos tiel. Ni dividos la sekretan mesaĝan bajton en 4 du-bitajn partojn: 11, 00, 10, 11, kaj anstataŭigos la malalt-ordajn bitojn de la bildo per la rezultaj fragmentoj: ...11101111 01001100 01111110 0101100111…. Tia anstataŭaĵo ĝenerale ne estas rimarkebla por la homa okulo. Plie, multaj pli malnovaj eligaj aparatoj eĉ ne povos montri tiajn malgrandajn ŝanĝojn.

Estas klare, ke vi povas ŝanĝi ne nur la 2 malplej signifajn bitojn, sed ajnan nombron da ili. Estas la sekva ŝablono: ju pli da bitoj ni ŝanĝas, des pli da informoj ni povas kaŝi, kaj des pli da interfero ĉi tio kaŭzos en la originala bildo. Ekzemple, jen du bildoj:

LSB-steganografio
LSB-steganografio

Malgraŭ miaj plej bonaj klopodoj, mi ne povis vidi la diferencon inter ili, sed tamen, en la dua bildo, uzante la priskribitan metodon, la poemo de Lewis Carroll "La Ĉasado de la Snark" estas kaŝita. Se vi legis ĉi tien, tiam vi verŝajne interesiĝas lerni pri la efektivigo. Ĝi estas sufiĉe simpla, sed mi tuj avertos vin, ke ĉio estas farita en Delfo. Estas du kialoj por tio: 1. Mi pensas, ke Delfo estas bona lingvo; 2. Ĉi tiu programo naskiĝis en la procezo de preparado de kurso pri la bazoj de komputila vizio, kaj la infanoj, al kiuj mi instruas ĉi tiun kurson, ankoraŭ ne scias ion alian ol Delphi. Por tiuj, kiuj ne konas la sintakson, unu afero devas esti klarigita: shl x estas bita movo maldekstren per x, shr x estas bit-flanka movo dekstren per x.

Ni supozas, ke ni skribas tekston konservitan en ŝnuro en la ujon kaj anstataŭigas la pli malaltajn du bajtojn:
Registradkodo:

por i:=1 al longo(str) do
    komenci
      l1:=bajto(str[i])shr6;
      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.Pozicio:=f.Pozicio-1;
      tmp:=((tmp shr 2) shl 2)+l1;
      f.WriteBuffer(tmp,1);
 
      f.ReadBuffer(tmp,1);
      f.Pozicio:=f.Pozicio-1;
      tmp:=((tmp shr 2) shl 2)+l2;
      f.WriteBuffer(tmp,1);
 
      f.ReadBuffer(tmp,1);
      f.Pozicio:=f.Pozicio-1;
      tmp:=((tmp shr 2) shl 2)+l3;
      f.WriteBuffer(tmp,1);
 
      f.ReadBuffer(tmp,1);
      f.Pozicio:=f.Pozicio-1;
      tmp:=((tmp shr 2) shl 2)+l4;
      f.WriteBuffer(tmp,1);
 
    fino;

kodo por legi:

por i:=1 al MsgSize do
    komenci
      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);
    fino;

Nu, por la vere maldiligentaj - ligo al la programo kaj ĝia fontkodo.

Kontrolo.

fonto: www.habr.com

Aldoni komenton