JPGファイルにデータを隠す方法

JPGファイルにデータを隠す方法

XAMLベースの様々なプラットフォーム、クロスプラットフォーム戦略、そして効果的なプロジェクトアーキテクチャ設計に必要な中核技術について深く掘り下げました。

最終更新 2024/11/11 6:58
zhaotianff
読了目安 2 分
カテゴリ
.NET
タグ
.NET C# アーキテクチャ設計 ステガノグラフィ

概要

最近、エクスプローラーの背景機能を実装する際に、情報をDLLに渡す必要がありました。

主に画像のフィット感や透明度などの比較的シンプルなパラメータを渡すものです。通信方法は複数ありますが、練習用の機能なので、これまで使ったことのない方法を試してみたいと思いました。

以前の記事で、画像ファイルにデータを埋め込む2つの方法を含むデジタルウォーターマーク技術を紹介しました。

https://www.cnblogs.com/zhaotianff/p/17222056.html

そこで今回も、これらのデータを画像ファイルに直接書き込み、DLLで読み取ることにしました。

ネットで調べたところ、JPGファイルに独自データを書き込む比較的簡単な方法が確かにありました。

しかも、この方法は理論上、サイズ制限なくデータを書き込めます。

余談ですが、どのような形式のファイルでも、標準的なフォーマットがあります。通常はファイルヘッダーやファイルボディなどがあり、ファイル構造を理解すれば、元のファイル構造を壊さずにヘッダーに独自データを書き込むことは理論的に可能です。

ただし、このプロセスには多少の時間がかかります。

今回は直接NVISO Labs の既存の方法を使用しました。必要な方への共有として紹介します。

実装原理

まず、16進エディタで通常のJPGファイルを開きます。

最初の2バイトは FF D8 です。

FF D8 => JPEGデータストリームの開始マーカー

JPEGデータストリームの開始マーカーを見つけたら、その後に「コメント」マーカーを挿入できます。

FF FE => これは「コメント」マーカーであり、JPEGデコーダーもこれを無視します。これらのマーカーが、データを挿入しても有効な画像を維持する方法です。

FF FEの直後には2バイトが続き、「コメント」内容のサイズを示します。

JPGファイルに HelloWorld を書き込むとします。「HelloWorld」は10バイトなので、FF FE の後に以下を書き込みます。

00 0A(10バイト) 48 65 6C 6C 6F 57 6F 72 6C 64

合計14バイトで、FF FE の2バイトのヘッダー、00 0A の2バイトのサイズ、10バイトの内容が含まれます。

したがって、16進エディタで FF D8 の後に14バイトを挿入します。

次にデータを埋め込みます。以下のようになります。

ファイルを保存すると、JPGファイルは正常に開けます。

コード実装

ここではC#を例にします。他の言語でも実装方法はほぼ同じです。今回はopacityとstretchのデータを書き込んでいます。

private void WriteImageInfoToFile(string filePath, double opacity, int stretch)
{
    // ファイルデータを読み込む
    var buffer = System.IO.File.ReadAllBytes(filePath);

    // JPGファイルかどうか判定
    if (buffer[0] == 0xFF && buffer[1] == 0xD8)
    {
        // 元のデータを6バイト拡張
        var newBuffer = new byte[buffer.Length + 6];

        // JPGファイル開始マーカー FF D8 をコピー
        Array.Copy(buffer, 0, newBuffer, 0, 2);

        // データ設定
        // コメントマーカー
        newBuffer[2] = 0xFF;
        newBuffer[3] = 0xFE;
        // サイズ 0x02
        newBuffer[4] = 0;
        newBuffer[5] = 0x02;
        // データ
        newBuffer[6] = (byte)nOpacity;
        newBuffer[7] = (byte)stretch;

        // 元画像の残りデータを新しいバッファにコピー
        Array.Copy(buffer, 2, newBuffer, 7, buffer.Length - 2);

        // ファイルに書き込む
        System.IO.File.WriteAllBytes(filePath, newBuffer);
    }
}

読み取り時も同様の規則で読み取れば問題ありません。

参考資料

https://blog.nviso.eu/2020/07/13/how-to-embed-secret-data-in-jpeg-files/

さらに探索

関連読書

その他の記事
同じカテゴリ / 同じタグ 2026/04/22

各OSバージョンの.NETサポート状況(250707更新)

仮想マシンとテストマシンを使用して、各OSバージョンの.NETサポート状況を確認します。OSインストール後、対応するランタイムをインストールし、Stardustエージェントを実行できることを確認します(合格条件)。

続きを読む
同じカテゴリ / 同じタグ 2026/02/07

AOTの使用経験のまとめ

プロジェクト作成当初から、新機能を追加したり新しい構文を使用したりした場合には、すぐにAOT公開テストを実施するという良い習慣を身につけるべきです。

続きを読む