Применение стеганографических методов для встраивания информации в архивные форматы изображений
Секция: Технические науки
XLVI Студенческая международная заочная научно-практическая конференция «Молодежный научный форум: технические и математические науки»
Применение стеганографических методов для встраивания информации в архивные форматы изображений
В этой статье мы постараемся осветить основные аспекты стеганографии, особенно подробно остановимся на скрытии информации в изображениях и приведем пример программы, которая будет скрывать данные в изображениях формата JPEG.
Введение
Встраивание информации в наименее значимые биты контейнера (или сокращённо НЗБ-встраивание) – исторически один из первых и, пожалуй, наиболее известный широкой публике подход, который может применяться как для стеганографии, так и для защиты сигналов цифровыми водяными знаками.
Основная идея метода заключается в том, что любое полутоновое изображение может быть представлено в виде совокупности битовых плоскостей. Так, контейнер будет иметь вид:
(1)
где: – битовые плоскости, – номер битовой плоскости,
– их количество.
Наименее и наиболее значащими битовыми плоскостями являются соответственно и : если изменить значение бита , то яркость изменится на единицу; если же изменить значение бита , то яркость изменится на 128. Младшие битовые плоскости выглядят как слабокоррелированный шум. Осмысленные детали, как правило, начинают проступать лишь с четвёртой битовой плоскости. Это означает, что наименее значимые битовые плоскости можно модифицировать с целью встраивания скрытого сообщения или цифрового водяного знака [2].
Далее будем рассматривать лишь случай встраивания информации в первую битовую плоскость. Тогда носитель информации будет иметь вид:
где: для всех
Сравнивать соответствие встроенной и извлеченной информации будем по формуле [3]:
(2)
Алгоритм JPEG
JPEG – наиболее распространенный графический формат, применяемый для хранения изображений. В нем применяются специальные алгоритмы преобразования цветовых пространств, архивации, квантования. Рассмотрим более подробно процесс сжатия изображения.
1. Переводим изображение из цветового пространства RGB, с компонентами, отвечающими за красную (Red), зеленую (Green) и синюю (Blue) составляющие цвета точки, в цветовое пространство YCrCb (иногда называют YUV).
2. Разбиваем исходное изображение на матрицы 8х8. Формируем из каждой три рабочие матрицы — по 8 бит отдельно для каждой компоненты. При больших коэффициентах сжатия этот шаг может выполняться чуть сложнее. Изображение делится по компоненте Y — как и в первом случае, а для компонент Cr и Cb матрицы набираются через строчку и через столбец.
3. Применяем дискретное косинусное преобразование к каждой рабочей матрице. При этом мы получаем матрицу, в которой коэффициенты в левом верхнем углу соответствуют низкочастотной составляющей изображения, а в правом нижнем — высокочастотной.
4. Производим квантование. Для каждой компоненты (Y, U и V), в общем случае, задается своя матрица квантования.
5. Переводим матрицу 8x8 в 64-элементный вектор при помощи «зигзаг»-сканирования как показано на рисунке 1.
Рисунок 1. Зигзаг-сканирование
Таким образом, в начале вектора мы получаем коэффициенты матрицы, соответствующие низким частотам, а в конце — высоким.
6. Свертываем вектор с помощью алгоритма группового кодирования (RLE – сжатие). При этом получаем пары типа (пропустить, число), где «пропустить» является счетчиком пропускаемых нулей, а «число» – значение, которое необходимо поставить в следующую ячейку.
7. Свертываем получившиеся пары кодированием по Хаффману с фиксированной таблицей.
Процесс восстановления изображения в этом алгоритме полностью симметричен. Метод позволяет сжимать некоторые изображения в 10–15 раз без серьезных потерь.
Реализация стеганографического НЗБ-встраивания в коэффициенты квантования JPEG
Произведем встраивание в изображение строки длиной 32 бита в первую битовую плоскость на этапе квантования.
clc;
clear;
RGB = imread('lena.jpg');
YCbCr = rgb2ycbcr(RGB);
k = 50;
Y = YCbCr(:,:,1);
Cb = YCbCr(:,:,2);
Cr = YCbCr(:,:,3);
[m,n] = size(Y);
Y_bdct = bdct(Y);
Cr_bdct = bdct(Cr);
Cb_bdct = bdct(Cb);
MK = jpeg_qtable(k);
Y_quantize = quantize(Y_bdct, MK);
Cr_quantize = quantize(Cr_bdct, MK);
Cb_quantize = quantize(Cb_bdct, MK);
b = [0,1,0,1,1,1,0,1,0,1,1,0,1,0,1,0,1,1,1,0,0,1,0,1];
Nb = length(b);
Cb_quantize = uint32(Cb_quantize);
CW = lsb_embed(Cb_quantize, b, 1, 1);
Cb_quantize = CW;
Y_dequantize = dequantize(Y_quantize, MK);
Cr_dequantize = dequantize(Cr_quantize, MK);
Cb_dequantize = dequantize(Cb_quantize, MK);
Y_ibdct = ibdct(Y_dequantize);
Cr_ibdct = ibdct(Cr_dequantize);
Cb_ibdct = ibdct(Cb_dequantize);
Y2 = uint32(Y_ibdct);
Cr2 = uint32(Cr_ibdct);
Cb2 = uint32(Cb_ibdct);
YCbCr =cat(3, Y2, Cb2, Cr2);
YCbCr = uint8(YCbCr);
RGB = ycbcr2rgb(YCbCr);
figure;
imshow(RGB);
bR = lsb_extract(CW, Nb, 1, 1);
r = lsb_check(b, bR, Nb)
Пример работы программы:
Произведем стеганографическое встраивание в коэффициенты квантования JPEG той же строки длиной 32 бита в первую битовую плоскость. Пример встраивания строки отображен на рисунке 2.
Рисунок 2. Пример стеганографического встраивания в коэффициенты квантования JPEG. Слева – исходное изображение, справа – заполненный контейнер
Встраиваемая строка имеет вид:
b = [0,1,0,1,1,1,0,1,0,1,1,0,1,0,1,0,1,1,1,0,0,1,0,1,0,1,0,1,1,1,0,1];
Извлеченные данные:
bR = [0,1,0,1,1,1,0,1,0,1,1,0,1,0,1,0,1,1,1,0,0,1,0,1,0,1,0,1,1,1,0,1];
Выполним проверку правильности данных по формуле 2. Результат равен 1, что говорит о совпадении встроенной и извлеченной строки.