Python で PDF セキュリティ署名を追加する方法

Python で PDF セキュリティ署名を追加する方法

Aspose.PDF の Python 用 FOSS には、既に署名された PDF を対象に、特定の改ざんパターン(署名のサインバイト範囲の後に意味のあるバイトが付加される)を検出する署名破損検知機能が含まれています。このリスクはインクリメンタルに更新された PDF ファイルに固有です。本ガイドでは、SignaturesCompromiseDetector と CompromiseCheckResult クラスを使用して、このチェックを Python ワークフローに組み込む方法を示します。新しいデジタル署名の作成や適用はライブラリの別の部分で扱われており、ここでは扱いません。ライブラリは以下のコマンドでインストールします。

ステップバイステップガイド

ステップ 1: パッケージをインストールする

Aspose.PDF の FOSS パッケージをインストールします:

git clone https://github.com/aspose-pdf-foss/Aspose-PDF-FOSS-for-Python.git
cd Aspose-PDF-FOSS-for-Python
pip install -e .

SignaturesCompromiseDetector をインポートし、確認メッセージを出力してインストールを検証します:

from aspose_pdf import SignaturesCompromiseDetector
print("aspose-pdf-foss-for-python is ready.")

ステップ 2: 必要なクラスをインポートする

from aspose_pdf import CompromiseCheckResult, SignaturesCompromiseDetector

ステップ 3: 署名リストを公開するオブジェクトを準備する

SignaturesCompromiseDetector は PDF を自ら解析しません — そのコンストラクタは signatures 属性を持つ任意のオブジェクトを受け入れます: 署名エントリのリストで、各エントリは valid、byte_range、および reference_data を保持しています。 PdfSignature — シンプルで直接インスタンス化できるクラス — はその形状に一致するため、独自のドキュメントオブジェクトに接続する前にチェックの動作を確認するのに便利です:

from types import SimpleNamespace
from aspose_pdf import PdfSignature

with open("signed.pdf", "rb") as handle:
    pdf_bytes = handle.read()

signature = PdfSignature(
    name="Signature1",
    contents=b"...",  # PKCS#7 signed-data blob from the signature dictionary
    byte_range=[0, 1024, 1040, len(pdf_bytes) - 1040],
    reference_data=pdf_bytes,
)

signed_document = SimpleNamespace(signatures=[signature])

signed_document を、同じ形状の signatures リストを公開するようになった自分のドキュメントオブジェクトに差し替えてください — その属性を持つオブジェクトであれば何でも機能します。


ステップ 4: コンプロマイズチェックを実行する

from aspose_pdf import SignaturesCompromiseDetector

detector = SignaturesCompromiseDetector(signed_document)
result = detector.check()

print(result.compromised)                # bool
print(result.has_compromised_signatures)  # bool -- same value as compromised
print(result.signatures_coverage)         # int -- number of signatures inspected
print(result.reasons)                     # list[str] -- human-readable findings

check() は signed_document.signatures 内のすべての署名を走査し、各署名の署名済みバイト範囲の後に付加された未署名コンテンツがないか調べます。CompromiseCheckResult は結果を要約します: compromised と has_compromised_signatures は同じ真偽値を2つの名前で報告し、signatures_coverage は検査された署名の数を示し、reasons は見つかった各問題に対する人間が読める説明を一覧します。


ステップ 5: 署名がないドキュメントを処理する

空の、または存在しない signatures リストはエラー状態ではありません — チェックすべきものが何もないドキュメントと同様に報告されます:

from types import SimpleNamespace
from aspose_pdf import SignaturesCompromiseDetector

unsigned_document = SimpleNamespace(signatures=[])
detector = SignaturesCompromiseDetector(unsigned_document)
result = detector.check()

print(result.compromised)  # False
print(result.reasons)      # ["unsigned document"]

SignaturesCompromiseDetector(None) を渡す — コンストラクタのデフォルト — は同じように動作します。

一般的な問題と対策

compromised is False 署名後に編集されたことが分かっている PDF に対して

SignaturesCompromiseDetector は、署名のサインされたバイト範囲の後に追加された未署名バイトを特に探します — これは素朴なインクリメンタル更新改ざんで典型的なパターンです。完全な暗号署名検証は行いません。そのためには、個々の PdfSignature オブジェクトに対して validate() を呼び出してください。

compromised and has_compromised_signatures 冗長に見える

これらは同じ値です: compromised は has_compromised_signatures を返す計算プロパティです。コード内で読みやすい方の名前を使用してください。

ドキュメントに何もない場合、例外は発生しません signatures 属性が全くない

SignaturesCompromiseDetector は、signatures 属性がない、または document=None のドキュメントを、署名なしドキュメントと同様に扱います — check() は例外を発生させるのではなく、has_compromised_signatures=False と reasons=["unsigned document"] を含む結果を返します。

不正な PdfSignature フラグが立てられません

check() は、byte_range が4要素のリストでない、または reference_data が bytes/bytearray でない署名を、例外を発生させたり「compromised」と報告したりする代わりにスキップします。形状が間違っている署名はチェックから黙って除外され、フラグは付けられません。

この検出器と署名作成を混同すること

SignaturesCompromiseDetector と CompromiseCheckResult は、ドキュメントにすでに存在する署名のみを検査します — 新しい署名を作成、適用、または埋め込む手段はありません。

よくある質問

ここで「compromised」と見なされる条件は正確には何ですか?

署名のサインバイト範囲の後に PDF に付加された意味のある非空白バイト — ただし、検出器がすでに考慮している 2 つの例外があります: それらのバイトを自らカバーする後続の署名またはタイムスタンプ、そして注釈などの新しいコンテンツを重ねず、検証材料(例: /DSS)のみを追加するインクリメンタル更新。

これで署名自体の暗号的有効性が検証されますか?

いいえ。SignaturesCompromiseDetector は署名されたバイト範囲周辺の改ざんパターンをチェックします。暗号的有効性は別のチェックで、PdfSignature.validate() を通じて利用できます。

signatures_coverage は何を教えてくれますか?

チェックが実際に検査した、渡されたドキュメント内の署名の数です — クリーンな結果を信頼する前に、検出器が期待した署名を確認できたかどうかを判断するのに役立ちます。

複数の署名があるドキュメントを一度にチェックできますか?

はい。check() は signed_document.signatures のすべてのエントリを反復し、すべてをカバーする単一の集約 CompromiseCheckResult を返します。

通常の使用時に自分で PdfSignature オブジェクトを構築する必要がありますか?

いいえ — ステップ3の PdfSignature 構築は、検出器の動作を直接調査するためのものです。実際のワークフローでは、ドキュメント読み込みコードがすでに生成するオブジェクトをそのまま渡せばよく、signatures の PdfSignature 形状のエントリのリストを公開している限り問題ありません。

参照

 日本語