Някога написах свой . Този пост беше посветен на много интересен проблем, а именно стеганографията. Разбира се, решението, предложено в тази стара тема, не може да се нарече стеганография в истинския смисъл на думата. Това е просто игра с файловите формати, но, все пак, доста интересна игра.
Днес ще се опитаме да се задълбочим повече и да разгледаме алгоритъма LSB. Ако ви интересува, заповядайте под кат. (Под кат трафик: около мегабайт.)
Първо, е необходимо да направим малко въведение. Всички знаем, че предназначението на криптографията е да направи четенето на секретна информация невъзможно. Разбира се, криптографията има своите области на приложение, но има и друг подход за защита на данните. Може да се не шифрова информация, а просто да се направи така, че да изглежда, че нямаме такава. Именно за това е измислена стеганографията. Уикипедия ни уверява, че „стеганография (от гръцки. στεγανοσ — скрит и гръцки. γραφω — пиша, буквално „тайнопис“) — това е наука за скритата предаване на информация чрез запазване в тайна самия факт на предаването.
Разбира се, никой не забранява да се комбинират криптографски и стеганографски методи. Освен това, в практиката точно така и се прави, но нашата задача е да се разберем с основите. Ако внимателно проучите статията в Уикипедия, можете да научите, че в алгоритмите на стеганографията фигурира т.н. контейнер и съобщение. Контейнерът е всяка информация, която помага да скрием нашето секретно съобщение.
В нашия случай контейнерът ще бъде изображение във формат BMP. Първо, нека разгледаме структурата на този файл. Файлът условно може да бъде разделен на 4 части: заглавие на файла, заглавие на изображението, палитра и самото изображение. За нашите цели трябва да знаем само това, което е записано в заглавието.
Първите два байта на заглавието са сигнатурата BM, след това в двойното слово е записан размерът на файла в байтове, следващите 4 байта са резервирани и трябва да съдържат нули и най-накрая, в още едно двойно слово е записано.offset от началото на файла, до самите байтове на изображението. В 24-битов bmp файл всеки пиксел е кодирани с три байта BGR.
Сега знаем как да достигнем до изображението, остава да разберем как да запишем необходимата информация. За тази цел ни е нужен метод LSB. Същността на метода е следната: заменяме най-малките битове в байтовете, отговорни за кодиране на цвета. Да предположим, ако текущият байт на нашето секретно съобщение е – 11001011, а байтовете в изображението – …11101100 01001110 01111100 0101100111…, то кодиране ще изглежда така. Ще разделим байта на секретното съобщение на 4 двубитови части: 11, 00, 10, 11, и ще заменим получените фрагменти с най-малките битове на изображението: …11101111 01001100 01111110 0101100111…. Тази замяна обикновено не е забележима за човешкото око. Освен това, много стари устройства за извеждане дори не могат да покажат такива незначителни промени.
Ясно е, че можем да променяме не само 2 най-малките бита, но и всяко тяхно количество. Тук има следната закономерност: колкото повече битове променяме, толкова по-голям обем информация можем да скрием и толкова по-големи смущения в оригиналното изображение ще предизвика това. Например, ето ви два изображения:


При всички усилия не успях да видя разлика между тях, и все пак во второто изображение с помощта на описания метод е скрита поемата на Луис Караъл «Ловът на Снарка». Ако сте прочели до този момент, вероятно ви интересува и реализацията. Тя е сравнително проста, но веднага предупреждавам, че всичко е направено на Delphi. Причините за това са две: 1. Считам Delphi за добър и полезен език; 2. Тази програма се роди в процеса на подготовка на курс по основите на машинното зрение, а момчетата, на които го преподавам, все още не знаят нищо освен Delphi. За тези, които не са запознати с синтаксиса, трябва да поясня едно нещо: shl x – битовият ляв сдвиг на x, shr x – битовият десен сдвиг на x.
Смятаме, че записваме в контейнера текст, намиращ се в строка и заменяме най-малките два байта:
Код за запис:
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;
код за прочитане:
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;
А за съвсем мързеливите - .
Благодаря.
Източник: habr.com
