- PVSM.RU - https://www.pvsm.ru -
Как нам подсказывает Википедия [1], стеганография – это наука о скрытой передаче информации путём сохранения в тайне самого факта передачи. В отличие от криптографии, которая скрывает содержимое секретного сообщения, стеганография скрывает сам факт его существования. Стеганографию обычно используют совместно с методами криптографии, таким образом, дополняя её.
Преимущество стеганографии над чистой криптографией состоит в том, что сообщения не привлекают к себе внимания. Сообщения, факт шифрования которых не скрыт, вызывают подозрение и могут быть сами по себе уличающими в тех странах, в которых запрещена криптография. Таким образом, криптография защищает содержание сообщения, а стеганография защищает сам факт наличия каких-либо скрытых посланий.
Чтобы не загружать читателя, ограничусь в использовании формул и прочих строгих математических выкладок. В списке использованных источников приведены ссылки на книги, где подробно описана математическая модель стеганосистемы. Статья же делится на две части:
1. Теоретическая: схема типичной стеганосистемы;
2. Пример конкретной стеганосистемы (на основе изображений JPEG) и схема её реализации.
Рассмотрим структурную схему типичной стеганосистемы. В общем случае стеганосистема может быть рассмотрена как система связи.

Основными стеганографическими понятиями являются сообщение и контейнер. Сообщение – это секретная информация, наличие которой необходимо скрыть. Контейнером называется несекретная информация, которую можно использовать для скрытия сообщения. В качестве сообщения и контейнера могут выступать как обычный текст, так и файлы мультимедийного формата.
Пустой контейнер (или так называемый контейнер-оригинал) – это контейнер, который не содержит скрытой информации. Заполненный контейнер (контейнер-результат) – контейнер, который содержит скрытую информацию. Одно из требований, которое при этом ставится: контейнер-результат не должен быть визуально отличим от контейнера-оригинала. Выделяют два основных типа контейнера: потоковый и фиксированный.
Потоковый контейнер представляет собой последовательность битов, которая непрерывно изменяется. Сообщение встраивается в него в реальном времени, поэтому в кодере заранее неизвестно, хватит ли размеров контейнера для передачи всего сообщения. В один контейнер большого размера может быть встроено несколько сообщений.
Основная проблема заключается в выполнении синхронизации, определении начала и конца последовательности. Если в данных контейнера существуют биты синхронизации, заголовки пакетов и т.д., то скрытая информация может следовать сразу же после них. Сложность организации синхронизации является преимуществом с точки зрения обеспечения скрытости передачи.
В фиксированном контейнере размеры и характеристики последнего заранее известны. Это позволяет выполнять вложение данных оптимальным (в определенном смысле) образом. Далее будем рассматривать фиксированные контейнеры.
Перед тем как выполнить вложение сообщения в контейнер, его необходимо преобразовать в определенный удобный для упаковки вид. Кроме того, перед упаковкой в контейнер, для повышения защищенности секретной информации последнюю можно зашифровать достаточно устойчивым криптографическим кодом. Во многих случаях также желательна устойчивость полученного стеганосообщения к искажениям (в том числе и злоумышленным).
В процессе передачи звук, изображение или какая-либо другая информация, используемая в качестве контейнера, может подвергаться разным трансформациям (в том числе с использованием алгоритмов с потерей данных): изменение объема, преобразование в другой формат и т.п., – поэтому для сохранения целостности встроенного сообщения может понадобиться использование кода с исправлением ошибок (помехоустойчивое кодирование). Начальную обработку скрываемой информации выполняет изображенный на рисунке прекодер.
Следует отметить, что для увеличения секретности встраивания, предварительная обработка довольно часто выполняется с использованием ключа.
Упаковка сообщения в контейнер (с учетом формата данных, представляющих контейнер) выполняется с помощью стеганокодера. Вложение происходит, например, путем модификации наименьших значащих битов контейнера. Вообще, именно алгоритм (стратегия) внесения элементов сообщения в контейнер определяет методы стеганографии, которые в свою очередь делятся на определенные группы, например, в зависимости от того, файл какого формата был выбран в качестве контейнера.
В большинстве стеганосистем для упаковки и извлечения сообщений используется ключ, который предопределяет секретный алгоритм, определяющий порядок внесения сообщения в контейнер. По аналогии с криптографией, тип ключа обуславливает существование двух типов стеганосистем:
В качестве секретного алгоритма может быть использован генератор псевдослучайной последовательности (ПСП) битов. Качественный генератор ПСП, ориентированный на использование в системах защиты информации, должен соответствовать определенным требованиям. Перечислим некоторые из них:
Статистически (криптографически) безопасный генератор ПСП должен соответствовать следующим требованиям:
Следует отметить, что метод случайного выбора величины интервала между встроенными битами не является достаточно эффективным. Скрытые данные должны быть распределены по всему контейнеру, поэтому равномерное распределение длины интервалов (от наименьшего к наибольшему) может быть достигнуто только приблизительно, поскольку должна существовать уверенность в том, что все сообщение встроено (то есть, поместилось в контейнер).
Скрываемая информация заносится в соответствии с ключом в те биты, модификация которых не приводит к существенным искажениям контейнера. Эти биты образуют так называемый стеганопуть. Под «существенным» подразумевается искажение, которое приводит к росту вероятности выявления факта наличия скрытого сообщения после проведения стеганоанализа.
Стеганографический канал – канал передачи контейнера-результата (вообще, существование канала как, собственно говоря, и получателя – наиболее обобщенный случай, поскольку заполненный контейнер может, например, храниться у «отправителя», который поставил перед собой цель ограничить неавторизованный доступ к определенной информации. В данном случае отправитель выступает в роли получателя).
В стеганодетекторе определяется наличие в контейнере (возможно уже измененном) скрытых данных. Различают стеганодетекторы, предназначенные только для обнаружения факта наличия встроенного сообщения, и устройства, предназначенные для выделения этого сообщения из контейнера, – стеганодекодеры.
Итак, в стеганосистеме происходит объединение двух типов информации таким образом, чтобы они по-разному воспринимались принципиально разными детекторами. В качестве одного из детекторов выступает система выделения скрытого сообщения, в качестве другого – человек.
Алгоритм встраивания сообщения в простейшем случае состоит из двух основных этапов:
В нашей работе будем реализовывать стеганосистему на основе JPEG. JPEG – это метод сжатия изображений с потерями. Он прекрасно сжимает изображения с непрерывными тонами, в которых близкие пикселы обычно имеют схожие цвета, но не очень хорошо справляется с двухуровневыми черно-белыми образами.
Для начала кратко рассмотрим алгоритм JPEG, более подробное описание и примеры можно найти в книгах, указанных в источниках. Кодировщик 8-битных RGB-изображений можно описать семью пунктами (на вход подаётся массив компонент изображения):
Алгоритм симметричный, так что кодировщик будет выполнять обратные действия.
Приступим к рассмотрению стеганосистемы на основе изображений формата JPEG. В основе лежит простейший метод LSB (Least Significant Bit, наименее значащий бит).
Суть метода LSB заключается в том, что человек в большинстве случаев не способен заметить изменений в последнем бите цветовых компонент изображения. Фактически, LSB – это шум, поэтому его можно использовать для встраивания информации путем замены менее значащих битов пикселей изображения битами секретного сообщения. Метод работает с растровыми изображениями, представленными в формате без компрессии (например, BMP). Основной недостаток метода – высокая чувствительность к малейшим искажениям контейнера.
В нашей же стеганосистеме будем применять DCT LSB стеганографию. Основное отличие заключается в том, что данные записываются не в цветовые компоненты, а в коэффициенты дискретного косинус-преобразования. Рассмотрим схему кодировщика (декодер делает всё тоже самое, но в обратном порядке).
На входе: цветное изображение, скрываемые данные, пароль.
На выходе: изображение в формате JPEG со скрытыми данными.
По приведенной схеме стеганосистемы можно легко написать программу. Исходные коды моей реализации можно найти на GitHub [3]. Программу нельзя назвать полноценной, скорее альфа-версией, но основной функционал в ней реализован. Четвертый пункт для кодировщика реализован здесь [4], а для декодировщика здесь [5]. За основу взяты уже готовые реализации JPEG, SHA-256, AES-256.
void jpeg_encoder::code_block(int component_num)
{
DCT2D(m_sample_array);
load_quantized_coefficients(component_num);
double psnr = 0;
for (int i = 0; i < 64; i++)
{
if (m_coefficient_array[i] > 1)
{
short t = m_sample_array[i];
bit_stream::write_bit(t, bit_stream::read_bit(t) == 1 ? 0 : 1);
psnr += (t - m_sample_array[i]) * (t - m_sample_array[i]);
}
}
psnr /= 64;
if (psnr != 0)
psnr = 20 * log10(255 / sqrt(psnr));
else
psnr = 70;
if (psnr > 55)
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
if (m_coefficient_array[8 * i + j] > 1)
{
int bits = bitstr->get_next_bit();
if (bits != -1)
{
bit_stream::write_bit(m_coefficient_array[8 * i + j], bits);
}
bitr++;
}
}
}
}
if (m_pass_num == 1)
code_coefficients_pass_one(component_num);
else
code_coefficients_pass_two(component_num);
}
void jpeg_decoder::transform_mcu(int mcu_row)
{
jpgd_block_t* pSrc_ptr = m_pMCU_coefficients;
uint8* pDst_ptr = m_pSample_buf + mcu_row * m_blocks_per_mcu * 64;
for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
{
idct(pSrc_ptr, pDst_ptr, m_mcu_block_max_zag[mcu_block]);
double psnr = 0;
for (int i = 0; i < 64; i++)
{
if (pSrc_ptr[i] > 1)
{
short t = pDst_ptr[i];
bit_stream::write_bit(t, bit_stream::read_bit(t) == 1 ? 0 : 1);
psnr += (t - pDst_ptr[i]) * (t - pDst_ptr[i]);
}
}
psnr /= 64;
if (psnr != 0)
psnr = 20 * log10(255 / sqrt(psnr));
else
psnr = 70;
if (!done && psnr > 55)
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
if (pSrc_ptr[g_ZAG[8 * i + j]] > 1)
{
int bits = bit_stream::read_bit(pSrc_ptr[g_ZAG[8 * i + j]]);
if (bitstr->set_next_bit(bits) == -1)
{
done = true;
int size = bitstr->get_readed_size();
char* str = new char[size];
bitstr->get_data(str);
str[size] = '';
m_stparams->stego_data = str;
}
}
}
}
}
pSrc_ptr += 64;
pDst_ptr += 64;
}
}
В заключение приведем характеристики полученного продукта:
Автор: m0j0
Источник [7]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/news/50784
Ссылки в тексте:
[1] Википедия: http://ru.wikipedia.org/wiki/Стеганография
[2] PSNR: http://en.wikipedia.org/wiki/PSNR
[3] GitHub: https://github.com/m0j0/stego
[4] здесь: https://github.com/m0j0/stego/blob/master/jpge.cpp#L723
[5] здесь: https://github.com/m0j0/stego/blob/master/jpgd.cpp#L1498
[6] en.wikipedia.org/wiki/JPEG: http://en.wikipedia.org/wiki/JPEG
[7] Источник: http://habrahabr.ru/post/206094/
Нажмите здесь для печати.