Как мы научились прятать секретные послания в роликах про котиков
Предположим, вам нужно передать секретное сообщение так, чтобы никто не догадался о его существовании. Шифрование скрывает содержание, но не сам факт передачи. А что, если вместо зашифрованного файла отправить обычное видео с котиками?
Именно такую задачу мы решили исследовать. В результате научились передавать до 337 байт в секунду внутри видео H.264, почти в 90 раз быстрее нашего первоначального варианта.
Почему это сложно?
Можно спрятать сообщение в метаданных или младших битах пикселей. Но видеокодек при сжатии все это уничтожит. Ничего личного. Просто работа у него такая.
Поэтому мы воспользовались дискретным косинусным преобразованием (DCT). Оно представляет блоки изображения наборами частотных коэффициентов. Берем два коэффициента и договариваемся: первый больше второго — единица, меньше — ноль. Если соотношение неправильное, немного изменяем коэффициенты.
Получатель восстанавливает биты из видео, не имея оригинала. Метод известен как дифференциальная DCT-модуляция. Придумали его не мы.
Три тысячи голосов за один бит
Изначально мы записывали один бит во множество блоков кадра. Получатель определял его голосованием: большинство блоков переживет сжатие и сохранит правильный ответ.
Надежно, но скорость — 3,75 байта в секунду при 30 кадрах. Котику пришлось бы очень долго гоняться за хвостом.
Тогда мы задумались: зачем три тысячи блоков голосуют за один бит? Разделим их на сто групп, и пусть каждая передает собственный бит!
Так появились параллельные каналы. Причем качество изображения практически не изменилось: мы использовали те же блоки, только распределили их между разными битами.
Победа над ошибками
Разумеется, чем меньше блоков голосуют за каждый бит, тем больше ошибок. Мы применили три приема.
Во-первых, взвешенное голосование: чем больше разница между коэффициентами, тем надежнее голос.
Во-вторых, адаптивное встраивание: на гладкой стене изменения заметны, а в кошачьей шерсти прекрасно маскируются. Мы стали слабее изменять гладкие участки и сильнее — текстурные. На одном ролике доля ошибок упала с 7,55% до 0,21%.
В-третьих, коррекцию ошибок Рида — Соломона с перемежением данных. Видеокодек портит биты целыми группами, поэтому мы перемешали данные так, чтобы повреждения распределялись между разными защищенными блоками.
Последний прием увеличил полезную скорость с 198 до 337 байт/с.
Что получилось?
Мы собрали утилиту, которая встраивает в видео произвольный файл, извлекает его и проверяет целостность по SHA-256.
На реальных роликах 720p/1080p при H.264, 2 Мбит/с и 30 кадрах в секунду получили 97–337 байт/с полезных данных.
Для понимания масштаба: 10 КБ можно передать примерно за полминуты видео.
Не гигабитный Ethernet, конечно. Зато информация находится непосредственно в изображении, а не в метаданных.
Кроме тайной переписки, технология пригодна для цифровых водяных знаков, идентификации видеокопий и защиты авторских прав.
Но главное наше открытие — возможность обменять избыточную надежность на пропускную способность практически без дополнительных искажений изображения.
В нашем случае — почти в сто раз.
А котик, который десять минут гоняется за собственным хвостом, по-прежнему не вызывает особенных вопросов.
В отличие от человека, пересылающего десятиминутный файл из случайных байтов.