長さヘッダープロトコル — 確実な抽出のための32ビットプレフィックス

LSB steganography で隠しデータの先頭に32ビットの長さヘッダーを付与するプロトコルを解説。デコーダーがペイロードの正確な終端を知るための仕組みと実装方法を説明します。

Techniques

詳細な説明

なぜ長さヘッダーが必要か

LSB steganography でメッセージを埋め込むとき、デコーダーは「何ビット分のデータを抽出すればよいか」を知る必要があります。長さヘッダーがなければ、デコーダーは画像全体の LSB を抽出することになり、メッセージの後に続く無関係なビット(元のピクセルの LSB)も含まれてしまいます。

32ビット長さヘッダーの構造

[32ビット: ペイロード長] [ペイロード本体: N ビット]
|← 固定長ヘッダー →|← 可変長データ →|

最初の32ビットは、後続するペイロードのビット数を符号なし整数として格納します。32ビットで表せる最大値は約 4,294,967,295 ビット(約512 MB)であり、実用上のあらゆる画像サイズに対応できます。

エンコード(埋め込み側)

function encodeWithHeader(messageBytes) {
  const messageBits = bytesToBits(messageBytes);
  const lengthBits = new Array(32);
  for (let i = 0; i < 32; i++) {
    lengthBits[i] = (messageBits.length >> (31 - i)) & 1;
  }
  return [...lengthBits, ...messageBits];
}

デコード(抽出側)

function decodeWithHeader(extractedBits) {
  let length = 0;
  for (let i = 0; i < 32; i++) {
    length = (length << 1) | extractedBits[i];
  }
  const messageBits = extractedBits.slice(32, 32 + length);
  return bitsToBytes(messageBits);
}

ヘッダーがない場合の問題

方式 抽出結果
長さヘッダーあり メッセージのみを正確に抽出
長さヘッダーなし メッセージ+余分なゴミビットを抽出、終端が不明
終端マーカー方式 メッセージ本体に終端マーカーと同じパターンが含まれるリスク

終端マーカー方式との比較

一部の実装では、長さヘッダーの代わりに特定のバイト列(例: null バイト8連続)を終端として使用します。しかしこの方式では:

  • メッセージ本体に同じパターンが含まれると誤って終端と判定される
  • バイナリデータを埋め込む場合に null バイトが頻出するため不向き

長さヘッダー方式はこれらの問題を回避し、任意のバイナリデータを正確に扱えます。

オーバーヘッドの影響

32ビット(4バイト)のオーバーヘッドは非常に小さく、640×480 の画像でも全容量の約0.003%にすぎません。このわずかなコストで確実なデータ抽出が保証されます。

ユースケース

独自の steganography ツールやデコーダーを実装する開発者が、このツールと互換性のあるヘッダープロトコルを理解し、正しくペイロードの境界を処理するため。

試してみる — Invisible Watermark

フルツールを開く