トラブルシューティング:暗号化と権限フラグ
スコープと境界
「スコープと境界」という見出しのセクションこのページの各エントリでは、エンジンが NextPDF\Exception\EncryptionException および NextPDF\Security\Exception\DecryptionFailedException として発生させる復号失敗と、PDF 権限フラグの境界を扱います。
最も一般的な誤解を避けるため、まず境界を示します。暗号化ディクショナリ内の PDF 権限フラグは、作成者の意図を記録するものです。これらは、このライブラリによって強制されるアクセス制御メカニズムではありません。フラグを無視するリーダーは、引き続きコンテンツの印刷、コピー、変更を行えます。フラグは強制ではなく、協調的なリーダーへの要求として扱ってください。
エントリ: 暗号化操作が失敗する
「エントリ: 暗号化操作が失敗する」という見出しのセクション- 症状。
EncryptionExceptionが、Encryption operation "<op>" failed using algorithm "<algorithm>"という形式のメッセージで発生します。 - 考えられる原因。 暗号操作を実行できなかった状態です。通常は、OpenSSL 拡張が存在しないか正しく設定されていない、無効な鍵マテリアル、または暗号境界での無効な IV サイズが原因です。
- 証拠 / 診断。
getContext()はalgorithmとoperationを返します。operationの値はencrypt、decrypt、key_derivationのいずれかであり、どの段階が失敗したかを示します。 - 解決方法。
- PHP の OpenSSL 拡張がインストールされ、ロードされていることを確認します。
- 対象の
operationフィールドを確認し、失敗している段階を特定します。 - 値が
key_derivationの場合は、パスワードまたは鍵の入力を確認します。 - 呼び出しを再実行します。
- 関連項目。 例外リファレンス。
エントリ: 構造的な理由で復号が失敗する
「エントリ: 構造的な理由で復号が失敗する」という見出しのセクション- 症状。
DecryptionFailedExceptionが、Decryption failed for "<algorithm>": <reason>という形式のメッセージで発生します。 - 考えられる原因。 暗号文が、改ざん以外の理由で処理できなかった状態です。たとえば、暗号文の切り詰め、IV の欠落、または API 境界で渡された誤った鍵などが原因です。評価に十分なマテリアルがなかったため、整合性チェックは実行されませんでした。
- 証拠 / 診断。
getContext()はalgorithmとreasonを返します。DecryptionFailedExceptionは、ソース上でTamperedDataExceptionとは別の例外として文書化されています。この例外は設定エラーまたは転送エラーを示すものであり、改ざんの兆候ではありません。これだけでセキュリティインシデントとして扱わないでください。 - 解決方法。
- まず
reasonを確認し、構造上の欠陥を特定します。たとえばciphertext shorter than IV+tagなどです。 - 暗号文が切り詰められずに転送されたことを確認します。
- 境界で渡された鍵が、ドキュメントの暗号化に使用された鍵であることを確認します。
- 呼び出しを再実行します。
- まず
- 関連項目。 署名とタイムスタンプの失敗。
エントリ: 「改ざんデータ」例外が発生する
「エントリ: 「改ざんデータ」例外が発生する」という見出しのセクション- 症状。
NextPDF\Security\Exception\TamperedDataExceptionが発生します(DecryptionFailedExceptionではありません)。 - 考えられる原因。 整合性チェックは実行されましたが、通りませんでした。これは構造的な復号失敗とは区別されます。整合性を評価するのに十分なマテリアルが存在しており、その検証が成立しなかったということです。
- 証拠 / 診断。 ソースでは 2 つのクラスが対比されています。
DecryptionFailedExceptionは構造的なものであり、セキュリティインシデントではありません。TamperedDataExceptionは、認証されたコンテンツの検証が成立しなかったことを示します。 - 解決方法。
- 入力を信頼できないものとして扱い、復号されたコンテンツを使用しないでください。
- 信頼できるソースからドキュメントを再取得します。
- 既知の正常なソースでも失敗が続く場合は、インシデントレポートのために
getContext()を取得します。
- 関連項目。 署名とタイムスタンプの失敗。
エントリ: 権限フラグが下流のアクションを止めていない
「エントリ: 権限フラグが下流のアクションを止めていない」という見出しのセクション- 症状。 権限フラグを設定して(たとえば、コピーや印刷を不許可にして)ドキュメントを生成したにもかかわらず、リーダーが引き続きコンテンツをコピーまたは印刷できます。
- 考えられる原因。 これは想定された境界であり、欠陥ではありません。Core の暗号化ディクショナリビルダーに渡される権限整数は、このライブラリによって強制力のある制御として適用されることはありません。フラグは助言的なメタデータです。これを尊重しないリーダーが NextPDF によってブロックされることはありません。
- 証拠 / 診断。
src/Security/Encryption/EncryptionDictionaryBuilder.phpはbuildDict(int $permissions, string $fileId)を宣言しており、そのパラメータはignored; retained for forward compatibilityとして文書化されています。このメソッドはunset($permissions, $fileId)で始まります。src/Inspect/PdfPermissions.phpによって公開される権限フラグは、読み取り専用の検査フィールドであり、強制レイヤーではありません。 - 解決方法。
- 印刷、コピー、変更を止めるために権限フラグに依存しないでください。これらは生成側ライブラリによって強制することはできません。
- アクセスを制限する必要がある場合は、ファイル自体の配布を制御するか、PDF の外部でアクセス制御システムを適用してください。
- ツールとして
PdfPermissionsを使用する場合は、既存のドキュメントが宣言しているフラグを報告する目的にのみ使用し、それらのアクションが防止されると主張するためには使用しないでください。
- 関連項目。 署名とタイムスタンプの失敗。
エントリ: PDF/A では暗号化が拒否される
「エントリ: PDF/A では暗号化が拒否される」という見出しのセクション- 症状。 ビルドで PDF/A を有効にし、同時に暗号化を要求すると
NextPDF\Security\Exception\IncompatiblePdfAModeExceptionが発生します。 - 考えられる原因。 PDF/A プロファイルは、トレーラー内の
Encryptキーを禁止しています。エンジンは、呼び出し順序にかかわらずこの組み合わせを拒否します。 - 証拠 / 診断。 PDF/A と PDF/UA のエントリを参照し、引用された条項、
getContext()フィールド、失敗パスのテストを確認してください。 - 解決方法。
- ドキュメントにアーカイブ適合性が必要なのか、暗号化が必要なのかを決定します。
- 不要なプロパティへの呼び出しを削除します。
- パイプラインを再実行します。
- 関連項目。 PDF/A と PDF/UA の検証。
エッジケースと注意点
「エッジケースと注意点」という見出しのセクションDecryptionFailedExceptionとTamperedDataExceptionは異なる意味を持ちます。構造的な失敗なのか、整合性の失敗なのかが異なります。メッセージではなく、クラスで分岐してください。- Core の暗号化ディクショナリビルダーは権限整数を無視します。core パッケージによる権限の強制に依存するビルドは、誤解に基づいています。
PdfPermissionsは、完全な検査深度において暗号化されたドキュメントに対してのみ設定され、宣言されたフラグを反映します。フィールドが設定されていても、そのアクションが防止されることを意味するわけではありません。