コンテンツにスキップ
getnextpdf.com

Enterprise エディション

電子透かしとステガノグラフィック埋め込み

NextPDF Enterprise は、文字ペア間の間隔に小さく制御された調整を加えることで、隠された暗号化済みペイロードを生成された PDF に埋め込みます。お客様はペイロード(通常は受信者ごとの識別子)とシークレットキーを提供します。エンコーダーは、テキストの自然なカーニングからの知覚できない偏差として、ペイロードを書き込みます。同じキーが与えられれば、対応するデコーダーがペイロードを復元します。このページは挙動レベルです。エンコーダーが何を書き込むか、使用する暗号、そしてこの技術の境界を記載します。

意図された用途は、内部ドキュメントのリーク追跡です。管理されたドキュメントがリークしたとき、復元されたマーカーが受信者のコピーを特定します。これは敵対的ステガノグラフィーではなく、任意の処理を通じた残存を保証するものでもありません。

前提条件はフロントマターに記載されており、前提条件で繰り返されています。

このケイパビリティは NextPDF Enterprisenextpdf/enterprise)に同梱されており、Enterprise ティアのライセンスエンベロープで有効化されます。その資格を持たないデプロイでは、ケイパビリティのクラスはロードされません。ケイパビリティは、ドキュメント生成中に完全にインプロセスで実行されます。ドキュメントコンテンツがホストを離れることはありません。エディションを比較してライセンスを取得

カーニング配列で描画される PDF テキストは、グリフ間に数値的な調整を保持します。エンコーダーは、各調整位置を数ビットのキャリアとして扱います。

  1. 認証付き暗号化と関連データ (AEAD) 暗号(デフォルトでは AES-256-GCM、または ChaCha20-Poly1305)でペイロードを暗号化します。AEAD は機密性と完全性の両方を提供するため、改ざんされたキャリアは、誤ったペイロードを暗黙的に生み出すのではなく、復号に失敗します。
  2. HMAC ベースの鍵導出関数 (HKDF) と SHA-256 を用いて、お客様のシークレットキーとフォントキーから 32 バイトの暗号化鍵を導出します。HKDF は、入力鍵マテリアルから固定長の擬似ランダム鍵を抽出し、それを必要な長さに拡張します。RFC 5869 §2 に従います。
  3. 暗号化ごとに、新鮮なランダムな 12 バイトの初期化ベクトル (IV) を生成します。AES-GCM は、認証の保証を失わないために、所与の鍵に対して IV が一意であることを必要とします。NIST SP 800-38D §5.2.1 に従います。
  4. 暗号化されたバイトをビット列にマッピングし、利用可能な文字ペア位置全体にビットを分散させ、位置ごとに 1 ビットまたは 2 ビットをエンコードします。自然なカーニングに加える偏差は、em の構成可能な割合によって上限が定められます。視覚的に知覚できない程度に十分小さくなります。

デコーダーはこのプロセスを逆転させます。コンテンツストリームからカーニング調整を読み取り、自然なカーニングを差し引き、偏差をビットに量子化し直し、暗号化されたブロブを再組み立てし、同じキーで復号します。キーが誤っているか、キャリアが破壊されている場合、復号は誤ったペイロードではなく何も返しません。

容量はテキスト長に応じて増減します。各文字ペア位置は 1 ビットまたは 2 ビットを保持するため、ペイロードはテキストが提供する位置に収まらなければなりません。ペイロードが容量を超えると、エンコーダーは型付きのオーバーフローエラーを発生させます。

PDF/A 互換モードは、バリデーターの幅許容しきい値を下回るように最大偏差を半分にし、容量を犠牲にしてより厳格な適合性と引き換えにします。

要となる選択は、可視のオーバーレイやメタデータフィールドではなく、カーニングにマーカーを隠すことです。メタデータマーカーは容易に除去でき、可視のスタンプはページを変えてしまいます。カーニング偏差は、その代わりに受信者が保持しなければならないテキストの内部に乗り、知覚されないままです。認証付き暗号化が第二の柱です。改ざんされた、または部分的なキャリアは認証に失敗するため、デコーダーは誤った受信者ではなく何も返しません。鍵は HKDF によってフォントごとに導出され、マーカーを裸の共有シークレットではなくドキュメントのコンテキストに結び付けます。誠実な堅牢性の開示はここから直接導かれます。マーカーは通常の再配布は生き残りますが、意図的なコンテンツストリームの書き換えは生き残りません。したがって、明示された範囲は敵対的ステガノグラフィーではなく、内部リーク追跡です。

設計の背景: Redaction is not a black rectangle

  1. NextPDF Core と Enterprise パッケージをインストールし、アクティブな Enterprise ライセンスを保持します。
  2. カーニングペアのメトリクスを公開するフォントでドキュメントを生成します。エンコーダーはフォントメトリクスから自然なカーニングを読み取ります。
  3. シークレットキーを、ソースからではなく、お客様のシークレットマネージャーから提供します。デコードには同じキーが必要です。
  4. 容量と適合性のニーズに基づいて、ビット深度(位置あたり 1 ビットまたは 2 ビット)と、PDF/A 互換性が必要かどうかを決定します。

エンコーディング構成はイミュータブルであり、構築時に検証されます。

  • ビット深度 — 文字ペア位置あたり 1 ビットまたは 2 ビット。深度が高いほど容量は増えますが、偏差は大きくなります。
  • 最大調整比 — em の割合としての偏差の上限。限定された範囲内です。値が大きいほどヘッドルームは増えますが、可視性のリスクがあります。
  • 暗号 — AES-256-GCM(デフォルト)または ChaCha20-Poly1305。どちらも AEAD です。
  • PDF/A 互換性 — 有効にすると、実効的な最大偏差を半分にします。

エンコードとデコードには同じ構成を使用してください。不一致は、ペイロードを復元しません。

  1. お客様のシークレットマネージャーからシークレットキーを読み取ります。
  2. エンコーディング構成(ビット深度、偏差比、暗号、PDF/A フラグ)を構築します。
  3. これからレンダリングするテキストのカーニング調整を、ペイロード、テキスト、フォントキー、フォントメトリクス、シークレットキー、構成を渡して計算します。
  4. テキストランを書き込む際に、返された調整を適用し、生成中にマーカーを埋め込みます。
  5. リークしたコピーを追跡するには、同じフォントキー、フォントメトリクス、シークレットキー、構成を用いて、疑わしいドキュメントのコンテンツストリームに対してデコーダーを実行し、復元されたペイロードを読み取ります。
examples/enterprise/steganography-capacity-guard.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
/**
* Reject a payload that cannot fit the carrier text before encoding.
*
* Each letter-pair position carries $bitDepth bits. Guarding capacity up
* front turns an unencodable payload into a clear caller-side error instead
* of relying on the encoder's overflow exception alone.
*
* @param non-empty-string $payload The bytes to embed (already minimal).
* @param positive-int $textLength The character count of the carrier text.
* @param int<1, 2> $bitDepth Bits encoded per letter-pair position.
*
* @throws \OverflowException When the payload cannot fit the available positions.
*/
function assertPayloadFits(string $payload, int $textLength, int $bitDepth): void
{
$positions = $textLength - 1;
$capacityBytes = \intdiv($positions * $bitDepth, 8);
if (\strlen($payload) > $capacityBytes) {
throw new \OverflowException(\sprintf(
'Payload of %d bytes exceeds carrier capacity of %d bytes.',
\strlen($payload),
$capacityBytes,
));
}
}
examples/enterprise/steganography-decode-guarded.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Enterprise\Security\Steganography\SteganographyDecoder;
use NextPDF\Enterprise\Security\Steganography\SteganographyConfig;
use NextPDF\Typography\FontMetrics;
use Psr\Log\LoggerInterface;
final readonly class LeakTracer
{
public function __construct(private LoggerInterface $logger) {}
/**
* Recover the embedded marker from a suspect document's content stream.
*
* Decoding returns null on a wrong key or a destroyed carrier rather than
* a wrong payload, so the caller treats null as "no marker recovered".
*
* @param string $contentStream The suspect content-stream bytes.
* @param non-empty-string $fontKey The font key used at generation.
* @param FontMetrics $metrics Font metrics with kerning pairs.
* @param string $secretKey The same secret key used to encode.
* @param SteganographyConfig $config The same configuration used to encode.
*
* @return string|null The recovered marker, or null when none is found.
*/
public function trace(
string $contentStream,
string $fontKey,
FontMetrics $metrics,
string $secretKey,
SteganographyConfig $config,
): ?string {
$marker = SteganographyDecoder::decodeFromContentStream(
$contentStream,
$fontKey,
$metrics,
$secretKey,
$config,
);
if ($marker === null) {
$this->logger->info('No steganographic marker recovered from content stream.');
}
return $marker;
}
}
  1. 既知のペイロードを既知のテキストランにエンコードし、同じキーと構成でデコードし直します。復元されたペイロードが一致することを確認します。
  2. 意図的に誤ったキーでデコードし、結果が誤ったペイロードではなく null であることを確認します。これは AEAD の完全性保証が機能している証拠です。
  3. レンダリングされたページを検査し、構成された偏差比において間隔の変化が視覚的に明らかでないことを確認します。
  4. PDF/A 互換性が必要な場合は、出力を PDF/A プロファイルに照らして検証し、幅許容が引っかからないことを確認します。
  • 認証付き暗号化。 ペイロードは AES-256-GCM または ChaCha20-Poly1305 で暗号化されます。改ざんまたは切り詰められたキャリアは、復号時に認証に失敗します。誤ったペイロードを生み出すことはありません。
  • 暗号化ごとの IV。 暗号化ごとに新鮮なランダムな 12 バイトの IV が生成され、NIST SP 800-38D §5.2.1 に従って AES-GCM の一意性要件を満たします。
  • 派生鍵。 暗号化鍵は、お客様のシークレットとフォントキーから HKDF-SHA-256 で導出されます (RFC 5869 §2)。シークレットはお客様のシークレットマネージャーに保管し、いかなる署名シークレットとも同様に扱ってください。
  • マーカーはドキュメントコンテンツです。 埋め込まれたバイトは、ログコンテンツではなく、ページコンテンツの一部です。ペイロードやシークレットキーをログに書き込まないでください。

このページは暗号埋め込みに関するものです。すべての規範的なソースはパラフレーズされており、規範的なテキストは複製されていません。 ### Robustness disclosure

マーカーはカーニング調整に保持されます。印刷と再スキャン、PDF 変換ツール、再線形化、またはカーニングを正規化するあらゆるコンテンツストリームの書き換えによって破壊される可能性があります。この技術は、生成された形式で配布されるドキュメントの内部リーク追跡に最も適しています。これは敵対的ステガノグラフィーではなく、任意の下流処理を生き残るものではありません。脅威モデルに意図的な除去が含まれる場合、これを唯一の管理策として頼らないでください。

  • ペイロードが大きすぎる。 ペイロードがテキスト容量を超えると、エンコーダーは型付きのオーバーフローエラーを発生させます。ペイロードを短くするか、キャリアテキストを長くしてください。
  • キャリアテキストが少なすぎる。 2 文字未満のテキストは、キャリア位置を提供せず、エラーを発生させます。
  • デコード時の誤ったキー。 デコードは null を返します。null を部分的な結果としてではなく、「マーカーが復元されなかった」ものとして扱ってください。
  • 構成の不一致。 エンコードとデコードは、同じビット深度、偏差比、暗号、PDF/A フラグを使用しなければなりません。不一致は、ペイロードを復元しません。

このページは、外部から観測可能な挙動とサポートされている公開 API サーフェスのみを記載します。内部の名前空間パス、ヘルパークラス、メカニズムの表、ランブックのファイル名、チケットのプレフィックスは対象外です。