LSB стэганаграфія

Калісьці даўно я напісаў свой першы пост на хабры. І прысвечаны той пост быў вельмі цікавай праблеме, а менавіта стэганаграфіі. Вядома, рашэнне, прапанаванае ў тым старым топіцы, нельга назваць стэганаграфіяй у праўдзівым сэнсе гэтага слова. Гэта ўсяго толькі гульня з фарматамі файлаў, але, тым не менш, даволі цікавая гульня.

Сёння мы паспрабуем капнуць крыху глыбей і разгледзім алгарытм LSB. Калі вам цікава, калі ласка пад кат. (Пад катам трафік: каля мегабайта.)

Перш за ўсё, неабходна зрабіць невялікі ўступ. Усім вядома, што прызначэнне крыптаграфіі - зрабіць немагчымым чытанне сакрэтнай інфармацыі. Зразумела, крыптаграфія мае свае вобласці ўжывання, але ёсць і іншы падыход да абароны дадзеных. Можна не шыфраваць інфармацыю, а зрабіць выгляд, што ў нас яе няма. Менавіта для гэтага і прыдумана стэганаграфія. Вікіпедыя запэўнівае нас што, «стеганаграфія (ад грэч. στεγανοσ — утоены і грэч. γραφω — пішу, літаральна «тайнапіс») — гэта навука аб утоенай перадачы інфармацыі шляхам захавання ў таямніцы самога факту перадачы.

Вядома ж, ніхто не забараняе сумяшчаць крыптаграфічныя і стэганаграфічныя метады. Больш за тое, на практыцы так і робяць, але нашая задача разабрацца з асновамі. Калі ўважліва вывучыць артыкул з Вікіпедыі, можна даведацца, што ў алгарытмах стэганаграфіі фігуруе т.зв. кантэйнер і паведамленне. Кантэйнер - гэта любая інфармацыя, якая дапамагае схаваць наша сакрэтнае паведамленне.

У нашым выпадку кантэйнерам будзе выступаць карцінка ў фармаце BMP. Для пачатку разгледзім структуру гэтага файла. Файл умоўна можна разбіць на 4 часткі: загаловак файла, загаловак выявы, палітру і сама выява. Для нашых мэт трэба ведаць толькі тое, што запісана ў загалоўку.

Першыя два байта загалоўка - гэта сігнатура BM, далей у падвойным слове запісаны памер файла ў байтах, наступныя 4 байта зарэзерваваны і павінны ўтрымоўваць нулі і, нарэшце, у яшчэ адным падвойным слове запісана зрушэнне ад пачатку файла, да ўласна байтаў малюнка. У 24-бітным bmp-файле кожны піксел кадуюцца трыма байтамі BGR.

Цяпер мы ведаем, як дабрацца да выявы, засталося зразумець, як туды можна запісаць неабходную нам інфармацыю. Для гэтага нам і спатрэбіцца метад LSB. Сутнасць метаду заключаецца ў наступным: мы замяняем малодшыя біты ў байтах, якія адказваюць за кадаваньне колеру. Дапушчальны, калі чарговы байт нашага сакрэтнага паведамлення – 11001011, а байты ў малюнку –…11101100 01001110 01111100 0101100111…, то кадаваньне будзе выглядаць так. Мы разаб'ем байт сакрэтнага паведамлення на 4 двухбітавыя часткі: 11, 00, 10, 11, і заменім атрыманымі фрагментамі малодшыя біты выявы: …11101111 01001100 01111110 0101100111…. Такая замена ў агульным выпадку не прыкметная чалавечаму воку. Больш за тое, многія старыя прылады вываду, нават не змогуць адлюстраваць такія нязначныя перамены.

Зразумела, што можна мяняць не толькі 2 малодшыя біты, але і любую іх колькасць. Тут ёсць наступная заканамернасць: чым большую колькасць біт мы мяняем, тым большы аб'ём інфармацыі мы можам схаваць, і тым большыя перашкоды ў зыходным малюнку гэта выкліча. Для прыкладу вось вам два выявы:

LSB стэганаграфія
LSB стэганаграфія

Пры ўсім жаданні я так і не здолеў убачыць розніцы паміж імі, а тым не менш у другой выяве з дапамогай апісанага метаду схаваная паэма Люіса Кэрала «Паляванне на Снарка». Калі вы дачыталі да гэтага моманту, то вам напэўна цікава даведацца і аб рэалізацыі. Яна задаволеная простая, але адразу папярэджу, што зроблена ўсё на Delphi. Прычын гэтаму дзве: 1. Я лічу Delphi добрай прыдатнай мовай; 2. Гэтая праграма нарадзілася, падчас падрыхтоўкі курса па асновах машыннага зроку, а рабяты, якім я гэты курс чытаю, пакуль нічога акрамя Delphi не ведаюць. Для тых, хто не знаёмы з сінтаксісам трэба растлумачыць адну рэч shl x - пабітавы зрух налева на x, shr x - пабітавы зрух направа на x.

Лічым, што мы запісваем у кантэйнер тэкст, які захоўваецца ў радку і заменны малодшыя два байта:
Код для запісу:

for i:=1 to length(str) do
    пачынаць
      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;

код для счытвання:

for i:=1 to MsgSize do
    пачынаць
      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;

Ну і для зусім лянівых - спасылка на праграму і яе зыходны код.

Дзякуй.

Крыніца: habr.com

Дадаць каментар