Kādreiz es uzrakstīju savu . Un šo ierakstu es veltīju diezgan interesantai problēmai, proti, steganogrāfijai. Protams, risinājumu, ko es piedāvāju tajā vecajā tēmā, nevar nosaukt par steganogrāfiju īstā vārda nozīmē. Tas ir vienkārši spēle ar failu formātiem, taču, tomēr, diezgan interesanta spēle.
Šodien mēs mēģināsim nedaudz iedziļināties un apskatīsim LSB algoritmu. Ja jums interesē, laipni aicinu zem katra. (Zem katra satiksme: apmēram megabaits.)
Pirmkārt, ir nepieciešams veikt nelielu ievadu. Visi zina, ka kriptogrāfijas mērķis ir padarīt neiespējamu slepenās informācijas lasīšanu. Protams, kriptogrāfijai ir savas pielietošanas jomas, taču ir arī cits pieejas datu aizsardzībai. Mēs varam nešifrēt informāciju, bet tikai izlikties, ka mums tās nav. Tieši šim nolūkam ir izgudrota steganogrāfija. Vikipēdija mūs pārliecina, ka „steganogrāfija (no grieķu στεγανοσ — slēpts un grieķu γραφω — rakstu, burtiski „noslēpumraksts”) ir zinātne par slēptu informācijas pārsūtīšanu, saglabājot pašu pārsūtīšanas faktu noslēpumā.
Protams, neviens neaizliedz apvienot kriptogrāfiskās un steganogrāfiskās metodes. Patiesībā praksē tā arī tiek darīts, bet mūsu uzdevums ir saprast pamatprincipus. Ja uzmanīgi izpētīsiet rakstu no Vikipēdijas, jūs varat uzzināt, ka steganogrāfijas algoritmos figurē tā sauktais konteiners un ziņojums. Konteiners ir jebkāds dati, kas palīdz slēpt mūsu slepeno ziņu.
Mūsu gadījumā konteiners būs attēls BMP formātā. Sāksim ar šī faila struktūras apskati. Failu ērti var sadalīt četrās daļās: faila virsraksts, attēla virsraksts, palete un pats attēls. Mūsu mērķiem ir jāzina tikai tas, kas ir ierakstīts virsrakstā.
Pirmie divi virsraksta biti ir BM paraksts, pēc tam ir divos vārdos ierakstīts faila lielums baitos, nākamie 4 biti ir rezervēti un tiem jābūt nullēm, un visbeidzot, vēl vienā divā vārdā ir ierakstīts nobīde no faila sākuma līdz pašiem attēla baitiem. 24 bitu bmp failā katrs pikselis tiek kodēts ar trim biti BGR.
Tagad mēs zinām, kā piekļūt attēlam, atliek noskaidrot, kā tajā var ierakstīt mums nepieciešamo informāciju. Tāpēc mums noderēs LSB metode. Metodes būtība ir šāda: mēs aizstājām jaunākos bitus bytes, kas atbild par krāsas kodēšanu. Pieņemsim, ja mūsu slepenā ziņojuma nākamais bytes ir 11001011, bet attēlu bytes ir... 11101100 01001110 01111100 0101100111..., tad kodēšana izskatīsies tā. Mēs sadalīsim slepenā ziņojuma bytes četrās divu bitu daļās: 11, 00, 10, 11, un aizstās šos fragmentus ar attēla jaunākajiem bitiem: ... 11101111 01001100 01111110 0101100111.... Šāda aizstāšana parasti ir nemanāma cilvēka acij. Turklāt, daudzi vecie izvades ierīces pat nespēs attēlot šādas nenozīmīgas izmaiņas.
Ir skaidrs, ka var mainīt ne tikai 2 jaunākos bitus, bet jebkuru to skaitu. Šeit ir nākamā likumsakarība: jo vairāk bitu mēs mainām, jo lielāku informācijas apjomu mēs varam noslēpt, un jo lielākas traucējumus tā radīs sākotnējā attēlā. Piemēram, lūk divi attēli:


Neskatoties uz visām vēlmēm, es tā arī nesanācu saskatīt atšķirību starp tiem, taču tomēr otrajā attēlā ar aprakstīto metodi ir noslēpta Lūisa Kēra poēma "Meklējot Snarku". Ja jūs esat izlasījuši līdz šim, tad jums noteikti interesē uzzināt arī par realizāciju. Tā ir diezgan vienkārša, bet uzreiz brīdināšu, ka viss ir izstrādāts Delphi. Šim ir divi iemesli: 1. Es uzskatu, ka Delphi ir kvalitātes valoda; 2. Šī programma radās, gatavojoties kursam par mašīnas redzes pamatiem, un puiši, kuriem es šo kursu pasniedzu, šobrīd neko citu kā Delphi nezina. To, kas nav pazīstams ar sintaksi, vajadzētu paskaidrot vienu lietu shl x – bitu pārvietošana pa kreisi uz x, shr x – bitu pārvietošana pa labi uz x.
Pieņemam, ka mēs ierakstām konteinerā tekstu, kas glabājas rindā un aizstājam jaunākos divus bytes:
Ieraksta kods:
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;
nolasīšanas kods:
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;
Un pavisam slinkajiem – .
Paldies.
Avots: habr.com
