![](https://habrastorage.org/files/70c/3bb/797/70c3bb797daf4b97853843594950594b.png)
Перевод поста Джона Маклуна (Jon McLoone) "Doing Spy Stuff with Mathematica".
Код, приведенный в статье, можно скачать здесь.
Выражаю огромную благодарность Кириллу Гузенко KirillGuzenko за помощь в переводе.
Я читал о IT проблемах недавно арестованных, как заявлялось, русских шпионов. Говорилось, что они пользовались не самыми надёжными инструментами цифровой стеганографии (вики). И мне стало интересно — насколько быстро я смогу реализовать стеганографию через цифровые изображения в Mathematica, используя метод, известный как "вставка младшего бита" (least significant bit insertion).
Идея стеганографии основывается на том, чтобы спрятать сообщения в какой-то другой информации таким образом, чтобы никто факта коммуникации не заметил. Само слово происходит от латино-греческий комбинации, означающей «скрытное письмо»; данным термином назывался процесс нанесения секретного сообщения на лысую голову человека, на которой затем отрастали волосы и, тем самым, прятали сообщение. В случае цифровой стеганографии всё делается посредством математики.
Первое, что мы должны сделать, это выбрать какое-нибуть невинно выглядящее изображение, чтобы передать его нашим шпионским боссам, возможно, через какой-то общественный онлайн форум. Эта картинка не должна вызвать подозрений, если мы разместим её на дискуссионном сайте о птицеводстве:
![](https://habrastorage.org/getpro/habr/post_images/7e0/6be/bc0/7e06bebc008a68bc36728aa88603d452.png)
![](https://habrastorage.org/getpro/habr/post_images/db9/46e/45a/db946e45a59422aa672fa03aa50c75d9.png)
Удивительно, однако в это изображение возможно встроить другое, большее по размеру полноцветное изображение и получить его обратно с помощью десятка строк кода в Mathematica.
Ключевая идея — использовать младшие биты в каждом цветовом канале каждого пикселя в качестве места, в котором спрятана информация. Мы начнём с того, что присвоим всем этим битам значение 0, применяя к каждому байту через And двоичное слово 11111110.
Мы должны заставить Mathematica использовать строго 8 бит на канал, потому что она по умолчанию работает в гораздо более точном цветовом пространстве, то есть будем использовать служебное слово “Byte” в некоторых места нашего кода.
![](https://habrastorage.org/getpro/habr/post_images/07b/978/687/07b978687748272c24607a01699bf080.png)
В достаточно сложных изображениях человеческий глаз не сможет обнаружить потерю информации. То есть то, что некоторый цветовой канал отдельного пикселя стал темнее или светлее чем раньше на 1/256 обнаружить просто невозможно.
![](https://habrastorage.org/getpro/habr/post_images/d79/433/33a/d7943333a8a647cdecfe42158e256eab.png)
![](https://habrastorage.org/getpro/habr/post_images/d75/e5f/8c0/d75e5f8c0672866621b76f3a6645569e.png)
Даже если вычесть усеченный вариант из оригинала, чтобы показать только значения разностей, то всё равно ничего не разглядеть, разве только если у вас весьма зоркий взгляд и очень хороший монитор.
![](https://habrastorage.org/getpro/habr/post_images/bb5/8ff/3cf/bb58ff3cf06023e2b78fd644f989368e.png)
![](https://habrastorage.org/getpro/habr/post_images/6b2/1d3/eda/6b21d3edab3f8af1d5ca81f568a4b4cf.png)
И только если выкрутить контраст на максимум, то мы увидим, что разница не равна нулю.
![](https://habrastorage.org/getpro/habr/post_images/9e7/d6f/5e1/9e7d6f5e16103a85f95905f180150c0e.png)
![](https://habrastorage.org/getpro/habr/post_images/a94/cf3/d03/a94cf3d03af09f46200f1af964a030b1.png)
Далее мы должны преобразовать наше секретное послание в последовательность битов и вставить их в обнулённые биты в изображении-носителе. Получается по биту на канал, то есть по три на пиксель для RGB изображения.
Для кодирования символов в соответствующие им номера в ASCII будем использовать функцию ToCharacterCode:
![](https://habrastorage.org/getpro/habr/post_images/05c/efd/608/05cefd608e6b8dc98024ea0b716e1d4c.png)
![](https://habrastorage.org/getpro/habr/post_images/55e/12c/a48/55e12ca487b34e1fb4584da61509453a.png)
Затем мы получим их двоичные представления, выдерживая при этом по 8 бит на число, добавляя при необходимости нули в начале (иначе мы не будем знать, где кончается один байт и начинается другой).
![](https://habrastorage.org/getpro/habr/post_images/db8/52f/d91/db852fd916499eed22221d09e330f70a.png)
![](https://habrastorage.org/getpro/habr/post_images/399/bf5/dbe/399bf5dbe9a42beefcc2a9708e78a09a.png)
Затем дополним список нулями, чтобы сровняться с общим количеством значений каналов пикселей, в которых мы будем прятать информацию (ширина * высота изображения * 3 канала RGB). Теперь, когда у нас есть нужное количество бит, мы преобразуем данные в соответствии с разрешением изображения и добавим их в изображение-носитель с очищенными битами.
Вот все эти операции вместе:
![](https://habrastorage.org/getpro/habr/post_images/fba/d76/dee/fbad76dee0a8272ee817f1c49395f7fc.png)
Для совершения обратного процесса мы должны взять младшие биты из каждого канала пикселя и сгруппировать их в слова по 8 бит, а затем сконвертировать их обратно в текст.
![](https://habrastorage.org/getpro/habr/post_images/8bd/c42/eaa/8bdc42eaa300d6910c7678af156eb4bb.png)
Давайте протестируем:
![](https://habrastorage.org/getpro/habr/post_images/8a6/3b7/872/8a63b7872a65c9281d038e66ae846fce.png)
![](https://habrastorage.org/getpro/habr/post_images/659/cd7/86b/659cd786bfc434d9ee4cee710419b5ec.png)
И обратный процесс:
![](https://habrastorage.org/getpro/habr/post_images/d43/491/764/d434917649652dd274155c34f1982f5b.png)
![](https://habrastorage.org/getpro/habr/post_images/16e/3ac/b12/16e3acb12cc4db0705081653782240de.png)
Экспортировать изображение следует в формат без потерь, такой, как PNG, с оригинальным размером изображения. Любое преобразование в формат с потерями, такой как JPG, или изменения в масштабе уничтожает информацию в младших битах, где мы храним наше секретное сообщение.
Изображение курицы Матильды состоит из 450*450 пикселей и имеет три цветовых канала. Это означает, что мы можем передать 450*450*3/8 символов. Более 75 000. Более чем достаточно, чтобы передать весь текст Приключений Алисы в стране чудес.
Мы можем добавить информации не больше, чем удалили. Файл по-прежнему будет такого же размера и визуально точно таким же.
По сути, в среднем половина пиксельных каналов имеют те же значения, что и в оригинальном изображении, около четверти значений пиксельных каналов на один бит меньше оригинала, у примерно четверти на один бит больше, то есть наше изображение ближе к оригиналу, чем усечённая версия.
![](https://habrastorage.org/getpro/habr/post_images/4cd/8c6/c3a/4cd8c6c3ae7892e8cefd370a88af33f8.png)
![](https://habrastorage.org/getpro/habr/post_images/367/d20/bb9/367d20bb962fb971b3c50dd68435d597.png)
![](https://habrastorage.org/getpro/habr/post_images/e2d/34f/741/e2d34f74160a8bc49696633c4c78521f.png)
![](https://habrastorage.org/getpro/habr/post_images/8cf/70e/480/8cf70e480d595ecdf550a1ef2c332178.png)
Мы получаем решение для передачи любой информации, которую можно представить в 8-битной кодировке ASCII. Mathematica для подобных задач содержит в себе набор инструментов, так что для передачи сообщения, состоящего из более богатого набора символов, мы можем поступить так:
![](https://habrastorage.org/getpro/habr/post_images/5d3/ea6/510/5d3ea65103a4d638010ff448f6d6767c.png)
![](https://habrastorage.org/getpro/habr/post_images/56f/fce/c92/56ffcec92eb61491d987e742c63f4dec.png)
![](https://habrastorage.org/getpro/habr/post_images/be1/2fb/627/be12fb627837a26b90dae50ddabaebac.png)
Мы можем использовать преобразование в ASCII для вставки файлов или данных в специальных форматах. Например, мы можем вставить изображение. Тут мы импортируем файл PNG, а затем перекодируем его в строку ASCII формата JPG.
![](https://habrastorage.org/getpro/habr/post_images/ebe/da1/1cc/ebeda11cce5903cd21e47e5ebbbf2aa0.png)
Эта строка, благодаря сжатию JPG, содержит лишь 32000 символов, несколько меньше текста про Алису — удивительно, как легко спрятать целое изображение! Мы можем экспортировать изображение в любой формат без потерь; важно только то, что секретное изображение закодировано в JPG, и при декодировании и интерпретации это следует учитывать.
![](https://habrastorage.org/getpro/habr/post_images/fad/789/16b/fad78916bcffdbf64f9e91994cf3510c.png)
![](https://habrastorage.org/getpro/habr/post_images/123/f22/ff9/123f22ff9bbc31c876b5efd123beaff7.png)
Изображение-носитель по прежнему выглядит для нас таким же, хотя в нём теперь скрыто секретное изображение агента H и агента B:
![](https://habrastorage.org/getpro/habr/post_images/a23/52a/7b7/a2352a7b717ba818585270f1538c4f4a.png)
![](https://habrastorage.org/getpro/habr/post_images/bca/1af/365/bca1af36507a5860ec9616368b7f705d.png)
Ничто из приведённого выше не является безопасным с точки зрения криптографии; это лишь способ незаметно передать информацию. Криптографические методы должны быть применены к самому секретному сообщению перед его вставкой в изображение-носитель. И, конечно, ничто из этого не поможет, если вы не уверены в получателе, который, возможно, уже находится под наблюдением, или который достаточно «сообразителен» для того, чтобы попросить агента ФБР под прикрытием следить за вашим ноутбуком.
Комментарии (3)
boeing777
29.07.2015 23:05Картинка с увеличенным контрастом разности похожа на результат работы фильтра noise в Photoshop. Интересно, Adobe там тоже что-то закодировали? :)
По делу: для увеличения плотности инкапсуляции можно использовать сокращенный алфавит вместо 8-битного ASCII. Например, base64-кодирование или нечто подобное. Разумеется, такой способ применим только для текста, а не двоичных данных.
SneakyJoe
А есть ещё и такие штуки как rarjpeg. Тоже способ начального уровня сокрытия.
Alexufo
есть еще плагин в фотошопе называющийся «Digimarc»