
jdvrif — Updated!
Инструмент стеганографии для изображений JPG
jdvrif
jdvrif (JPG Data Vehicle) — это быстрый и простой в использовании инструмент стеганографии командной строки для сокрытия и извлечения файлов любого типа через JPG-изображение. Только для Linux.
Ваш файл данных сжимается с помощью libdeflate/zlib, затем шифруется с помощью XChaCha20-Poly1305 (secretstream из libsodium) ключом, производным от Argon2id из случайно сгенерированного восстановительного PIN-кода, и наконец встраивается в изображение-контейнер. PIN-код отображается один раз, в конце работы команды conceal, и нигде не сохраняется: без него скрытый файл невозможно восстановить.
Используя режим сокрытия по умолчанию, вы можете скрыть файл любого типа, при этом итоговое изображение ограничено размером в 2GiB. Остальные режимы сокрытия для платформ и совместимые сайты социальных сетей (перечисленные ниже) имеют свои собственные гораздо меньшие ограничения по размеру и другие требования.
Существует веб-версия jdvrif, которую можно использовать сразу же как удобную альтернативу загрузке и компиляции исходного кода CLI. Загрузка файлов через веб-интерфейс ограничена 20MiB.
Для тех, кто интересуется этим языком, также доступен экспериментальный порт на Rust jdvrif-rs. Он совместим по формату: любая из сборок может восстановить изображения, созданные другой.
jdvrif частично основан на реализованной технике исследователя в области безопасности David Buchanan.

Демонстрационное изображение: "A place of concealment" / PIN: 7912872750612437051
Как jdvrif скрывает данные
В отличие от распространённого метода стеганографии LSB (Least Significant Bit), при котором данные скрываются в пикселях изображения-контейнера, jdvrif в основном прячет данные внутри сегментов приложения JPG-изображения (ICC, EXIF, XMP и т. д.).
| Режим сокрытия | Куда помещаются данные | Где можно поделиться итоговым изображением |
|---|---|---|
| (без опции) | сегменты профиля APP2/ICC | X-Twitter, Tumblr, Mastodon, Pixelfed, PostImage, ImgBB, ImgPile, Flickr |
| -b | сегменты EXIF / Photoshop / XMP с обрамлением | только Bluesky |
| -r | DCT-коэффициенты JPEG (QIM) | только Reddit |
| -x | DCT-коэффициенты JPEG (J-UNIWARD/STC) | только X-Twitter |
Два платформенных исключения из метода хранения в сегментах по умолчанию — это Reddit и X-Twitter. У обеих есть собственный режим сокрытия, и ни один из этих режимов вообще не использует сегменты метаданных: -r и -x переносят полезную нагрузку в DCT-коэффициентах JPG-изображения.
Reddit перекодирует загруженные изображения и отбрасывает сегменты метаданных, на которые опирается режим по умолчанию, поэтому -r — единственный режим, который там работает. X-Twitter сохраняет один небольшой сегмент ICC, поэтому режим по умолчанию на этой платформе всё ещё работает, но только для крошечной полезной нагрузки.
Для режима сокрытия Reddit (-r) мы используем метод стеганографии QIM (Quantization Index Modulation в области DCT-коэффициентов JPEG), поскольку это единственный метод хранения, который в настоящее время работает для Reddit. Изображение-контейнер перекодируется в baseline Q75 4:2:0, а полезная нагрузка переносится в его блоках DCT яркости.
Чтобы максимизировать ёмкость хранилища для платформы Reddit, используйте изображение-контейнер с большими размерами, 2048x2048, 4096x4096, 8192x8192 (макс.) и т. д.
Качество изображения-контейнера для этого метода не важно, и его следует оставлять базовым для наибольших размеров, чтобы помочь минимизировать размер файла изображения-контейнера.
Хотя платформа X-Twitter может использовать метод по умолчанию, предоставляемый jdvrif, при котором данные скрываются в сегментах APP2/ICC, X-Twitter ограничивает это одним сегментом ICC с максимальным размером всего ~10KiB.
Чтобы вместить больше этих ~10 КиБ, используйте режим сокрытия платформы X-Twitter (-x). Он полностью отказывается от сегментов метаданных — в ICC-профиль ничего не записывается — и вместо этого использует адаптивный метод стеганографии J-UNIWARD с кодированием Syndrome-Trellis (STC). Контейнер транскодируется в прогрессивный 4:2:0 с качеством, производным от исходного (с ограничением Q97).
Чтобы максимизировать ёмкость хранилища для платформы X-Twitter, используйте контейнерное изображение высокого качества/детализации с большими размерами, 1024x1024, 2048x2048, 4096x4096 (макс.) и т. д.
Носители -r и -x шифруют ваши данные и привязывают их местоположение к вашему PIN-коду восстановления с помощью Argon2id, но встраивание всё равно изменяет статистику DCT изображения, поэтому целенаправленный стегоанализ может выявить, что изображение содержит скрытые данные.
Изображения -r и -x, созданные с помощью jdvrif v9.0, остаются восстановимыми, но v9.0 не может восстановить изображения -r или -x, созданные с помощью v9.1.
Оба режима DCT переносят гораздо меньше данных, чем режим по умолчанию, поэтому используйте capsize для измерения контейнерного изображения перед выбором полезной нагрузки (см. Проверка ёмкости).
Требования и компиляция (Linux)
Для сборки требуются CMake 3.20 или новее, flock из util-linux, а также Ninja (предпочтительно) или Make. Компилятор должен быть GCC 14 или новее либо Clang 18 или новее в паре со стандартной библиотекой C++23, реализующей такие возможности, как std::format и std::print. Требуемые нативные библиотеки: libsodium, libjpeg-turbo (оба API — turbojpeg и libjpeg), zlib и libdeflate. OpenMP необязателен: при его наличии он распараллеливает проход вычисления стоимости J-UNIWARD для -x.
$ sudo apt update
$ sudo apt install g++ cmake ninja-build util-linux libsodium-dev libturbojpeg0-dev libjpeg-dev zlib1g-dev libdeflate-dev
$ g++ --version # confirm the reported version is 14 or newer
$ chmod +x compile_jdvrif.sh
$ ./compile_jdvrif.sh
$ sudo cp jdvrif /usr/bin
Если в вашем дистрибутиве GCC 14 поставляется как версионированный пакет, установите g++-14 и выполните сборку командой CXX=g++-14 ./compile_jdvrif.sh.
Обёртка хранит объектные файлы с отслеживанием зависимостей в src/build/, поэтому при последующих запусках пересобирается только изменённое, а опубликованный бинарный файл jdvrif заменяется только после полной успешной сборки. Задайте JDVRIF_JOBS=<count>, чтобы изменить ограничение параллелизма (по умолчанию: число CPU, но не более 8), JDVRIF_BUILD_DIR=<path> для использования отдельного кэша сборки или BUILD_MODE=sanitize для сборки с ASan/UBSan.
Использование
$ jdvrif
Usage: jdvrif conceal [-b|-r|-x] <cover_image> <secret_file>
jdvrif recover <cover_image>
jdvrif capsize [-r|-x] <cover_image>
jdvrif --info
Запустите jdvrif --info, чтобы получить полное встроенное руководство по режимам, параметрам платформ и ограничениям размера.
$ jdvrif conceal your_cover_image.jpg your_secret_file.doc
Platform compatibility for output image:-