10 марта 2011 г.

Стеганография в Matlab. Пример последовательного вcтраивания в НЗБ. (LSB embedding).

Теория хороша только в случае подтверждения практикой. Так и в вопросах стеганографии знать, что скрываемое сообщение можно поместить в НЗБ (наименее значимые биты), не значит уметь это сделать. Существует несколько готовых стеганографических программ, как платных, так и бесплатных, которые спрячут файл в изображение или аудио. Однако использование таких программ не дает полного контроля над процессом. Куда происходит встраивание? Насколько оно стойко к обнаружению? Насколько изменяется файл?.. На многие подобные вопросы ответа не будет.
Для начала сделаем простой стеганографический скрипт в системе математического моделирования Matlab.
Почему Matlab? Просто эта система позволяет сконцентрировать внимание на алгоритме сокрытия. Не нужно уметь открывать файл, распознавать его формат, показывать изображение на экране… Все это Matlab уже умеет. Так же он умеет работать с изображением как с матрицей, выполнять битовые операции (and, or, xor…) и многое, многое другое. Язык написания скриптов же очень прост и становится интуитивно понятным для любого кто хоть немного знаком с программированием.
Будем считать, что Matlab у вас уже установлен и запущен. Об основных окнах и приемах работы в matlab можно почитать в http://matlab.exponenta.ru/ml/book1/index.php 

- в рабочем каталоге создаем папку, «images». Помещает в папку цветное изображение, в которое будем прятать данные;
- создаем пустой M-File
- назовем этот файл sample_embedding

Загружаем в Matlab изображение, которое будет служить контейнером для скрываемого сообщения:
Рис. 1.  Наглядное представление цветовых
компонент изображения

emb_IMG_name='./images/murzik.bmp';
emb_IMG = imread(emb_IMG_name);

В Workspace появилась переменная IMG <1024xl024x3 uint3>. Это трехмерный массив цветовых компонент RGB (red, green, blue).
В Matlab принята особая система работы с матрицами, которая несколько отличается от привычной для программистов работы с массивами. К элементам матриц можно обращаться как традиционным способом :

RedComponentPixel=IMG(1,1,1);
или
GreenComponentPixel=IMG(1,1,2);

так и с помощью линейной индексации:

RedComponentPixel=IMG(1);
или
GreenComponentPixel=IMG(1048577).

в приведенных строках переменным RedComponentPixel и GreenComponentPixel. присваиваются значения яркости красной и зеленой компоненты левого верхнего пикселя рисунка 1024х1024. 
Рис. 2. Представление индексации
массивов в Matlab
Понять линейное индексирование цветовых компонент можно из рисунка 2. 
 Подробнее о работе с матрицами в matlab  можно почитать на http://matlab.exponenta.ru/ml/book1/matlab/chapter3/3_5.php.

Определим размер рисунка в пикселях:

emb_IMG_size_y=size(emb_IMG,1);
emb_IMG_size_x=size(emb_IMG,2);

Рассчитаем количество информации которую можно внедрить в НЗБ:

emb_max_Bytes=emb_IMG_size_y*emb_IMG_size_x*3/8;% Bytes


Определяем сколько бит необходимо для хранения максимально возможного  размера файла.

emb_num_bits=ceil(log2(emb_max_Bytes));% bits


Загружаем в переменную emb_FILE файл, который будем встраивать.

fid = fopen(emb_FILE_name);
emb_FILE = fread(fid);
status =fclose(fid);
emb_FILE_size=size(emb_FILE,1);% Bytes


Для примера объемности встраиваемых данных был взят RAR-архив первого тома «Войны и мира» в текстовом формате. Пароль архива: Password.
Проверяем, не превышает ли  встраиваемый файл максимально допустимый размер.
if (emb_FILE_size*8+emb_num_bits<=emb_max_Bytes*8)
  emb_possible=true;
else
  emb_possible=false; 
end;

Если стеганографическое встраивание возможно, кодируем длину скрываемого файла последовательностью бит.

% FILE size -> bit's row
emb_FILE_size_arr=zeros(emb_num_bits,1);
for ind=0:1:emb_num_bits-1,
  emb_FILE_size_arr(ind+1)=bitand(bitshift(emb_FILE_size,-ind),1);
end;


Так же разделяем байты файла который будем встраивать на биты. Этот шаг нужен так как встраивание будет происходить побитно.

% hidded FILE -> bit's row
emb_DATA_bits = uint8(im2bw([bitand(emb_FILE,128),...
                            bitand(emb_FILE,64), ...
                            bitand(emb_FILE,32), ...
                            bitand(emb_FILE,16), ...
                            bitand(emb_FILE,8),  ...
                            bitand(emb_FILE,4),  ...
                            bitand(emb_FILE,2),  ...
                            bitand(emb_FILE,1)],0.6));

Объединяем битовую последовательность в которой закодирован размер файла с битовой последовательностью самого файла.

%FILE size bits + FILE data bits
emb_BITs=[emb_FILE_size_arr; emb_DATA_bits(:)];

Формируем индекс для встраивания битовой последовательности:

emb_BITs_ind=1:size(emb_BITs,1);
emb_BITs_ind=emb_BITs_ind';

Долгожданный момент! Встраиваем битовый ряд файла в НЗБ изображения.

emb_new_IMG(emb_BITs_ind)=bitshift(emb_IMG(emb_BITs_ind),-1);
emb_new_IMG(emb_BITs_ind)=bitshift(emb_new_IMG(emb_BITs_ind),1)+emb_BITs;

Записываем стеганоизображение в файл и показываем его пользователю.

imwrite(emb_new_IMG,'stego_murzik2.bmp','bmp');
imshow(emb_new_IMG);

В той же папке, где располагается скрипт для встраивания появится BMP-файл. Наименее значимые биты которого содержат скрытое сообщение.

Для тех у кого нет желания собирать весь скрипт из текста сообщения, искать файл для изображения и файл который можно спрятать, а попробовать как это все работает хочется, даю ссылку на архив со всеми файлами. 

24 комментария:

  1. Доброго времени суток!
    Во время тестирования мною данного скрипта, вылетают ошибки о совместимости размерностей матриц(конкретнее emb_new_IMG(emb_BITs_ind)=bitshift(emb_new_IMG(emb_BITs_ind),1)+emb_BITs; тут)
    Если в исходнике таких казусов нет, то, прошу Вас, перезалейте пожалуйста архив.
    Заранее благодарен.

    ОтветитьУдалить
  2. Архив перезалил. Код проверил. Все должно работать. Спасибо за проявленный интерес.

    ОтветитьУдалить
  3. ПРивет всем во время, теста проги,вылетает такаже ошибка emb_new_IMG(emb_BITs_ind)=bitshift(emb_new_IMG(emb_BITs_ind),1)+emb_BITs из чего могу предположить что архив не был перезалит и ли у автора данное проги просто ривые руки, прога всетаки нужная спасибо)

    ОтветитьУдалить
  4. Опишите, пожалуйста, подробно ваши действия. Какого формата файлы? Какой глубины цвета? Какого размера? Какая версия Matlab? Выложите, пожалуйста, полное сообщение об ошибке.
    С мнением о своих кривых руках категорически несогласен :-)

    ОтветитьУдалить
  5. Али из Украина18 ноября 2011 г. в 14:33

    Спасибо, вы мне очень помогли.

    ОтветитьУдалить
  6. Пожалуйста. Спасибо за комментарий.

    ОтветитьУдалить
  7. Вы большой молодец,Gr1g0ry. Скажите, пожалуйста, Gr1g0ry, будет ли работать Ваш скрипт для встраивания стегоинформации в файлы формата jpeg 2000 и не будет ли встроенная информация при дальнейшей обработке потеряна.

    ОтветитьУдалить
  8. Спасибо за лестный отзыв.
    По поводу вопроса могу сказать, что осуществить с помощью Matlab встраивание и извлечение данных из jpeg 2000 возможно. Однако, для сохранения целостности данных нельзя применять к файлам изображения сжатие с потерями. Но, именно, высокое качество сжатия с потерями является одним из основных достоинств jpeg 2000.
    Для встраивания скрытой информации в форматы данных с потерями, рекомендую посмотреть стеганографические алгоритмы, которые работают в частотной форме представления изображения (сокрытие в коэффициентах вейвлет преобразования и т. п.).

    ОтветитьУдалить
  9. Я последовал Вашему совету(спасибо!) и несколько проанализировал файл jp2 на предмет встраивания инфы. Встраивание возможно только после этапа квантования в вевлет-коэффициенты, иначе часть встоенной инфы потеряется. Я программирую на С, там как бы всё возможно задавай какие хошь параметры и всё тако. А в матлабе не юзал, вот интересно, можно ли разложить файл jp2 по шагам и вытащить вейвлет-коэффициенты коэффициенты

    ОтветитьУдалить
  10. Мощно..а есть какой нибудь алгоритм для встраивания данных в видео файл,а не в изображение? Заранее спасибо

    ОтветитьУдалить
  11. Спасибо, за проявленый интерес, но стеганографией для встраивания в видео я не занимался. Хотя очевидно, что встраивание в видео возможно.

    ОтветитьУдалить
  12. А сложнее чем с изображением, как думаете?

    ОтветитьУдалить
  13. здравствуйте, тоже вылетает ошибка emb_new_IMG(emb_BITs_ind)=bitshift(emb_new_IMG(emb_BITs_ind),1)+emb_BITs и никак не могу разобраться

    ОтветитьУдалить
  14. Спасибо огромное, очень пригодилось)

    ОтветитьУдалить
  15. Скажи пожалуйста пароль к архиву Война и Мир

    ОтветитьУдалить
  16. Здравствуйте, тоже вылетает ошибка emb_new_IMG(emb_BITs_ind)=bitshift(emb_new_IMG(emb_BITs_ind),1)+emb_BITs и никак не могу разобраться. Подскажите в чем проблема?

    ОтветитьУдалить
  17. Т.к. появилось много сообщений об ошибках, то я решил проверить работоспособность скрипта: скачал архив и запустил встраивание.
    Никаких проблемм обнаружить не смог - stego_murzik2.bmp успешно создается.
    Опишите ожалуйста проблемму подробнее, дайте полный текст ошибки, дайте изображение, на котором проводилось встраивание и файл, который встраивался. Подробно опишите последовательность действий по запуску скрипта. Спасибо за проявленный интерес.

    ОтветитьУдалить
    Ответы
    1. Спасибо, Григорий! Всё отлично работает, программа пригодилась

      Удалить
  18. Почему увеличивается размер файла?

    ОтветитьУдалить
  19. Здраствуйте! Ви случайно не знаете как наложить свою информацию в уже имеющийся аудиофайл, именно методом фазовой модуляции?

    ОтветитьУдалить
  20. Уважаемый Григорий,у меня та же проблема,что и у предыдущего "анонимщика"поэтому отвечаю на ВАШИ ОТВЕТЫ АДРЕСОВАННЫЕ ЕМУ-фОРМАТ ФАЙЛА БМП,размер контейнера (изображение) 345600 байт,версия матлаб 6.4.1.размер внедряемого изображения 6980 байт. После этой операции появляется сообщение что операция + не определена для UINT 8 emb_new_IMG(emb_BITs_ind)=bitshift(emb_new_IMG(emb_BITs_ind),1)+emb_B
    ITs А при обозначении типов данных на double выдаёт еррор и советует привести в соответствие размеры матриц

    ОтветитьУдалить