
jdvrif — Updated!
JPG 이미지용 스테가노그래피 도구
jdvrif
jdvrif(JPG Data Vehicle)는 JPG 이미지를 통해 모든 파일 형식을 은닉하고 추출할 수 있는 빠르고 사용하기 쉬운 스테가노그래피 명령줄 도구입니다. Linux 전용입니다.
데이터 파일은 libdeflate/zlib로 압축된 후, 무작위로 생성된 복구 PIN에서 Argon2id로 파생된 키 아래 XChaCha20-Poly1305(libsodium secretstream)로 암호화되며, 최종적으로 커버 이미지에 삽입됩니다. PIN은 conceal 작업이 끝날 때 한 번만 표시되며 어디에도 저장되지 않습니다. PIN 없이는 은닉된 파일을 복구할 수 없습니다.
기본 conceal 모드를 사용하면 모든 파일 형식을 은닉할 수 있으며, 완성된 이미지는 최대 2GiB로 제한됩니다. 다른 플랫폼 conceal 모드와 호환되는 소셜 미디어 사이트(아래 나열)는 각각 훨씬 더 작은 크기 제한과 기타 요구 사항이 있습니다.
jdvrif의 웹 에디션이 있어 CLI 소스 코드를 다운로드하고 컴파일하는 대신 즉시 편리하게 사용할 수 있습니다. 웹 파일 업로드는 20MiB로 제한됩니다.
해당 언어에 관심이 있는 분들을 위해 실험적인 Rust 포팅 버전 jdvrif-rs도 제공됩니다. 형식 호환이 가능하여 어느 빌드든 다른 빌드의 이미지를 복구할 수 있습니다.
jdvrif는 보안 연구원 ***David Buchanan***이 ***구현한 기법***에서 부분적으로 파생되었습니다.

데모 이미지: "A place of concealment" / PIN: 7912872750612437051
jdvrif의 데이터 은닉 방식
커버 이미지의 픽셀 내에 데이터를 은닉하는 일반적인 LSB(최하위 비트) 스테가노그래피 방식과 달리, jdvrif는 주로 JPG 이미지의 애플리케이션 세그먼트(ICC, EXIF, XMP 등) 내에 데이터를 숨깁니다.
| Conceal 모드 | 데이터가 저장되는 위치 | 출력 이미지를 공유할 수 있는 곳 |
|---|---|---|
| (옵션 없음) | APP2/ICC 프로필 세그먼트 | X-Twitter, Tumblr, Mastodon, Pixelfed, PostImage, ImgBB, ImgPile, Flickr |
| -b | 프레임 처리된 EXIF / Photoshop / XMP 세그먼트 | Bluesky 전용 |
| -r | JPEG DCT 계수(QIM) | Reddit 전용 |
| -x | JPEG DCT 계수(J-UNIWARD/STC) | X-Twitter 전용 |
기본 세그먼트 저장 방식에 대한 두 가지 플랫폼 예외는 Reddit과 X-Twitter입니다. 둘 다 자체 conceal 모드를 가지며, 두 모드 모두 메타데이터 세그먼트를 전혀 사용하지 않습니다. -r과 -x는 대신 JPG 이미지의 DCT 계수에 페이로드를 담습니다.
Reddit은 업로드된 이미지를 재인코딩하고 기본 모드가 의존하는 메타데이터 세그먼트를 폐기하므로, -r이 그곳에서 작동하는 유일한 모드입니다. X-Twitter는 단일하고 작은 ICC 세그먼트를 보존하므로 기본 모드가 해당 플랫폼에서도 여전히 작동하지만, 아주 작은 페이로드에만 해당됩니다.
Reddit conceal 모드(-r)의 경우 QIM 스테가노그래피 방식(JPEG DCT 영역 양자화 인덱스 변조)을 사용합니다. 이는 현재 Reddit에서 작동하는 유일한 저장 방식이기 때문입니다. 커버는 베이스라인 Q75 4:2:0으로 트랜스코딩되며 페이로드는 휘도 DCT 블록에 담깁니다.
Reddit 플랫폼의 저장 용량을 최대화하려면 2048x2048, 4096x4096, 8192x8192(최대) 등 큰 차원 크기의 커버 이미지를 사용하십시오.
이 방식에서는 커버 이미지의 품질이 중요하지 않으며, 커버 이미지 파일 크기를 최소화하는 데 도움이 되도록 가장 큰 차원에서는 기본 품질로 유지해야 합니다.
X-Twitter 플랫폼은 데이터가 APP2/ICC 세그먼트 내에 은닉되는 jdvrif의 기본 방식을 사용할 수 있지만, X-Twitter는 이를 최대 크기가 ~10KiB에 불과한 단일 ICC 세그먼트로 제한합니다.
그보다 더 많은 ~10KiB를 담으려면 X-Twitter 플랫폼 은닉 모드(-x)를 사용하십시오. 이 모드는 메타데이터 세그먼트를 완전히 포기하여 ICC 프로필에 아무것도 기록하지 않고, 대신 Syndrome-Trellis Coding(STC)을 사용한 적응형 J-UNIWARD 스테가노그래피 기법을 사용합니다. 커버는 소스에서 도출된 품질(Q97로 상한 설정)로 프로그레시브 4:2:0으로 트랜스코딩됩니다.
X-Twitter 플랫폼의 저장 용량을 최대화하려면 1024x1024, 2048x2048, 4096x4096(최대) 등과 같이 큰 차원 크기를 가진 고품질/고세부 커버 이미지를 사용하십시오.
-r 및 -x 캐리어는 데이터를 암호화하고 Argon2id를 사용하여 복구 PIN에 위치를 키잉하지만, 임베딩은 여전히 이미지의 DCT 통계를 변경하므로 전용 스테그분석으로 이미지가 숨겨진 데이터를 담고 있음이 드러날 수 있습니다.
jdvrif v9.0으로 생성된 -r 및 -x 이미지는 복구 가능하지만, v9.0은 v9.1로 생성된 -r 또는 -x 이미지를 복구할 수 없습니다.
두 DCT 모드 모두 기본 모드보다 훨씬 적은 데이터를 담으므로, 페이로드를 선택하기 전에 capsize를 사용하여 커버 이미지를 측정하십시오(용량 확인 참조).
요구 사항 및 컴파일 (Linux)
빌드에는 CMake 3.20 이상, util-linux의 flock, 그리고 Ninja(권장) 또는 Make 중 하나가 필요합니다. 컴파일러는 GCC 14 이상이거나, std::format 및 std::print와 같은 기능을 구현한 C++23 표준 라이브러리와 함께 사용하는 Clang 18 이상이어야 합니다. 필요한 네이티브 라이브러리는 libsodium, libjpeg-turbo(turbojpeg 및 libjpeg API 모두), zlib 및 libdeflate입니다. OpenMP는 선택 사항입니다. 존재할 경우 -x J-UNIWARD 비용 계산 단계를 병렬화합니다.
$ 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>를 설정하거나, ASan/UBSan 빌드를 원하면 BUILD_MODE=sanitize를 설정하십시오.
사용법
$ 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:-
✓ X-Twitter
✓ Tumblr
✓ Mastodon
✓ Pixelfed
✓ PostImage
✓ ImgBB
✓ ImgPile
✓ Flickr
Recovery PIN: [***2166776980318349924***]
Important: Keep your PIN safe, so that you can extract the hidden file.
Saved "file-embedded" JPG image: jrif_4e87c566c.jpg (143029 bytes).
Complete!
$ jdvrif recover jrif_4e87c566c.jpg
PIN: *******************
Extracted hidden file: your_secret_file.doc (6165 bytes).
Complete! Please check your file.
jdvrif mode 인수:
conceal - 비밀 데이터 파일을 압축하고 암호화하여 JPG 커버 이미지 안에 삽입합니다.
recover - JPG 커버 이미지에서 숨겨진 데이터 파일을 복호화하고 압축 해제하여 추출합니다 (복구 PIN 필요).
capsize - -r 또는 -x 모드에 대한 커버 이미지의 전송 용량을 보고합니다. 이미지는 저장되지 않습니다.
커버 이미지 요구 사항:
● JPEG 전용, 최소 400x400 픽셀, 그리고 그레이스케일 또는 YCbCr 색상 — CMYK/YCCK 이미지는 먼저 RGB로 변환해야 합니다.
● 기본 및 -b 상한 크기는 4096x4096px입니다. -r은 8192x8192px을 사용하며, -x도 4096x4096px로 제한됩니다.
● 기본 모드(옵션 없음)는 추정 JPEG 품질이 Q97을 초과하는 커버 이미지도 거부합니다. 거부되면 이미지를 더 낮은 품질로 다시 저장하세요.
비밀 데이터 파일 요구 사항:
● 삽입되는 파일명은 20바이트를 초과할 수 없고, . 또는 -로 시작하거나 공백 또는 .로 끝나서는 안 되며, 제어 문자나 양방향 서식 문자 또는 / \ : * ? " < > | 중 어느 것도 포함하지 않는 유효한 UTF-8이어야 합니다. 이름은 이미지에 저장되며 recover 시 복원됩니다.
● 데이터 파일은 암호화 전에 압축되지만, 이미 압축된 것으로 인식되는 파일 형식(.zip, .7z, .mp4, .jpg, .png 등)은 예외입니다. 기본 및 -b 모드에서는 해당 형식이 10MiB보다 클 때만 압축을 건너뛰며, -r 및 -x 모드에서는 항상 건너뜁니다. 작은 플랫폼 제한을 목표로 하는 다른 파일의 경우, 정확한 저장 크기를 알 수 있도록 먼저 직접 압축하는 것을 고려하세요 (zip, rar, 7z 등).
호환 플랫폼
******************
참고: Bluesky는 이제 기본적으로 이미지를 WEBP로 저장합니다.
jdvrif로 숨겨진 데이터를 여전히 복구할 수 있도록 이미지를 JPG로 저장하려면:-
먼저 게시물의 이미지를 클릭하여 열고, 이미지를 마우스 오른쪽 버튼으로 클릭하세요. 메뉴에서 새 탭에서 이미지 열기를 선택하세요.
새 탭을 선택하고 주소 표시줄에서 주소 끝으로 이동하여 @jpg를 추가한 후 Enter를 누르세요.
이미지를 마우스 오른쪽 버튼으로 클릭하고 메뉴에서 ***이미지 저장...***을 선택하세요.
이제 이미지가 JPG로 다운로드되며, jdvrif와 함께 작동합니다.
Bluesky에 게시할 WEBP 이미지를 사용하여 데이터를 숨기는 도구를 원한다면 제 WEBP 스테가노그래피 CLI 도구 wbpdv를 사용할 수 있습니다.
************
게시 크기 제한은 커버 이미지 + 압축된 데이터 파일의 합산 크기로 측정됩니다:
● Flickr (200MiB), ImgPile (100MiB), ImgBB (32MiB), PostImage (32MiB), Pixelfed (15MiB).
크기 제한은 압축된 데이터 파일 크기만으로 측정됩니다:
● Mastodon (~6MiB), Tumblr (~64KiB), X-Twitter (~10KiB / 기본 방법).
예를 들어, Mastodon의 경우 커버 이미지가 1MiB라면 여전히 ~6MiB 크기 제한까지 데이터 파일을 삽입할 수 있습니다.
기타: 자체 conceal 모드가 있는 플랫폼: