Иногда нужно передать сообщение так, чтобы посторонний даже не догадался, что оно вообще существует. Обычный шифр прячет смысл письма, но сам факт переписки виден: все понимают, что перед ними тайное сообщение. А можно поступить хитрее — спрятать текст внутри обычной фотографии. Снаружи это просто картинка, и никто не станет искать в ней письмо.
Наука о том, как прятать сам факт сообщения, называется стеганографией (от греческих слов «скрытый» и «пишу»). Этим приёмом пользуются очень давно, а сегодня проще всего прятать текст именно в цифровых картинках, потому что в них миллионы пикселей, и каждый можно чуть-чуть изменить незаметно для глаза.
Тема актуальна, потому что мы каждый день обмениваемся фотографиями в мессенджерах, и полезно понимать, что в картинке может скрываться больше, чем видно, и почему такое письмо иногда «ломается» при пересылке.
Гипотеза. Если изменять в каждом пикселе только самые младшие биты, можно спрятать в картинку целое письмо так, что глаз не заметит разницы. Но чем больше битов задействовать ради объёма, тем сильнее портится картинка, и в какой-то момент подмена становится видна.
Цель работы — показать на практике, как спрятать текст внутри картинки, и измерить, сколько текста помещается и когда тайник становится заметным.
Задачи:
Цифровая картинка — это сетка из множества точек, пикселей. Цвет каждого пикселя задаётся тремя числами от 0 до 255: сколько в нём красного, зелёного и синего цвета (система RGB). Смешивая их, можно получить любой оттенок. Например, картинка размером 300×200 содержит 60 000 пикселей, а значит 180 000 отдельных чисел-каналов.
Каждое число от 0 до 255 компьютер хранит в двоичном виде — восемью битами (нулями и единицами). Например, число 200 записывается как 11001000. Самая левая цифра отвечает за 128, а самая правая — всего за 1. Эту крайнюю правую цифру называют младшим битом.
Если поменять только младший бит, число 200 превратится в 201 или останется 200 — то есть цвет изменится на одну двести пятьдесят шестую. Такую крошечную разницу человеческий глаз не различает. Зато в этот младший бит можно записать один бит нашего письма. А в картинке таких битов — миллионы.
Текст сначала превращают в длинную цепочку битов. В начало добавляют «заголовок» — число, которое говорит, сколько букв в письме. Затем биты письма по очереди записывают в младшие биты пикселей: первый бит — в младший бит красного канала первого пикселя, второй — в зелёный, и так далее.
Чтобы достать письмо, нужно знать правило: сколько младших битов использовано. Программа читает эти биты в том же порядке, собирает из них буквы и восстанавливает текст. Тот, кто правила не знает, видит просто картинку.
Чтобы не спорить «видно или не видно» на глаз, заметность измеряют числом. Я использовала показатель PSNR — он показывает, насколько сильно изменённая картинка отличается от исходной, и измеряется в децибелах (дБ). Правило простое: чем больше децибел, тем меньше заметна разница. Если PSNR выше 40 дБ, глаз разницы практически не видит; если ниже — подмену уже можно заметить.
Для исследования сделана программа — страница, которая открывается в браузере и всё считает прямо на компьютере, без интернета (это важно: тайные картинки никуда не отправляются). В программе четыре части: «Спрятать письмо», «Прочитать письмо», «Эксперимент» и справка.
Я выбираю картинку, пишу текст и указываю, сколько младших битов использовать. Программа прячет письмо и показывает рядом три картинки: исходную, картинку с письмом и «разницу», усиленную во много раз, чтобы изменения стало видно.
Я брала одну и ту же картинку и прятала в неё максимально длинное письмо, используя от 1 до 8 младших битов каждого цвета. Для каждого случая программа измеряла: сколько символов поместилось (вместимость), показатель PSNR и самый большой сдвиг яркости у пикселя. Все данные можно сохранить в файл.
Отдельно я проверяла, переживёт ли письмо сжатие картинки — такое же, какое происходит при отправке «фото» в мессенджере.
Результаты эксперимента собраны в таблице 1.
Из таблицы видно две противоположные вещи. С одной стороны, вместимость растёт ровно во столько раз, сколько битов мы берём: при 1 бите помещается около 12 000 символов, при 4 битах — почти 49 000, при 8 битах — около 98 000. С другой стороны, картинка при этом всё сильнее портится: показатель PSNR падает с 51 дБ (при 1 бите) до 10 дБ (при 8 битах), а максимальный сдвиг яркости вырастает с 1 до 223 из 255.
Если сопоставить оба показателя, видно «золотую середину»: невидимыми (PSNR выше 40 дБ) остаются только варианты с 1 и 2 битами. Начиная с 3 бит разница уже заметна, а при 4 и больше — хорошо видна. При этом даже одного бита хватает, чтобы спрятать целое письмо. Значит, лучший выбор — 1–2 бита: и места достаточно, и подмена невидима.
Когда картинку отправляют как фото, мессенджер сжимает её, чтобы она весила меньше, и при этом слегка меняет пиксели. В опыте после такого сжатия письмо прочитать не удалось — вместо текста получился мусор. Причина в том, что сжатие огрубляет как раз мелкие, «незаметные» детали, а именно в них спрятано письмо.
В ходе работы я:
Гипотеза подтвердилась. В младшие биты картинки действительно можно спрятать целое письмо незаметно для глаза: при 1–2 битах показатель PSNR выше 40 дБ, и разницу не видно. И так же подтвердилась вторая часть гипотезы: чем больше битов, тем больше объём, но тем заметнее подмена — начиная с 4 бит картинка портится явно.
Я узнала и важное ограничение: стеганография прячет сам факт письма, но не шифрует его — кто знает правило, прочитает текст. Поэтому на практике письмо сначала шифруют, а уже потом прячут, и тогда тайна защищена дважды.
Что можно изучить дальше: как прятать письмо не подряд, а «рассыпая» по всей картинке; как объединить шифрование и стеганографию; можно ли прятать текст в звук или видео.