無効な署名Javaを与えるPDFBox複数署名

Nov 26 2020

PDFマルチ署名ワークフローの要件がありました。このPDFでは、2人以上が同じドキュメントに署名できるなど、ドキュメントを変更せずに複数回署名されます。PDFに署名を2回追加しようとしていますが、PDFに2回署名した後、最初の署名が無効になります。PDF署名の作成にPDFBoxJavaAPIを使用しました。

PDF作成手順:

  1. 空の署名フィールド名を追加してPDFを作成:元のhello.pdf出力ファイル名hello_tag.pdf実行プログラム> TagPDFSignatureFields.javaを使用して[email protected]および[email protected]
  2. hello_tag.pdfファイルから署名フィールド[email protected]をフェッチして初めて署名する場合、出力ファイル名はhello_signed.pdfです。プログラム> SignAndIdentifySignatureFields.javaを実行します。
  3. hello_signed.pdfファイルから署名フィールド[email protected]をフェッチして2回目の署名を行う場合、出力ファイル名はhello_singed2.pdf実行プログラム> Sign2.javaです。

2番目のステップではpdfは正しく署名されますが、3番目のステップの後、2番目のステップの署名されたバージョンは無効になり、3番目のステップの署名はacrobatリーダーで問題ないことを示します。

参照用のリンクJavaソースコードとPDFサンプルを見つけてください。Googleドライブリンクpdf_multi_signs_pdfbox_java

どんな助けでもいただければ幸いです。

回答

3 mkl Nov 27 2020 at 01:26

要するに、あなたのコードには多くの問題があります。2番目の署名を追加した後にAdobeReaderが最初の署名を無効としてマークする原因となる問題は、実際にはTagPDFSignatureFields、無効な重複ページツリーエントリを作成する準備ステップにあります。Adobe Readerは現在文句を言っていませんが、他の問題も修正する必要があります。

問題の詳細...

重複するページエントリ

ではTagPDFSignatureFields、あなたの方法addEmptySignFieldのように起動します:

private void addEmptySignField(String[] args) throws Exception, IOException {
    // Create a new document with an empty page.
    try (PDDocument document = PDDocument.load(new File(args[0]));)
    {
        PDPage page = document.getPage(0);
        document.addPage(page);

ここでは、の最初のページを取得し、documentすぐにそのページをdocument再度追加します。これにより、ファイル内のページルートツリーノードは次のようになりますhello_tag.pdf

2 0 obj
<<
/Type /Pages
/Count 2
/Kids [6 0 R 6 0 R]
>>
endobj 

つまり、ページツリーには同じページオブジェクトが2回含まれていますが、Adobe Readerはこれを受け入れませんが、内部で修復します。署名されたドキュメントの場合、AdobeReaderはこれについて漠然と警告します。

また、現在のバージョン(2020.013.20066など)では、2回署名されたファイルのAdobe Readerは、最初の署名が壊れているとマークすることさえあります。以前のバージョン(例:2019.012.20040)ではそうしませんでした。おそらくこれは、シャドウアタックが公開された後の検証コードの強化の影響です。

余談ですが、署名されたドキュメントの操作(フォームへの入力、再署名など)によって古い署名が破損する場合は、元のドキュメントにすでに問題があるかどうかも常に確認してください。署名されたドキュメントに適用された変更が許可されているかどうかのチェックは、内部で修正されているため表示されないエラーに非常に敏感です。

無効な部分フィールド名

あなたは、フィールド名として、電子メールアドレスを使用[email protected]して[email protected]、あなたの例の場合:

signatureField.setPartialName("[email protected]");
...
signatureField1.setPartialName("[email protected]");

TagPDFSignatureFields方法addEmptySignField

これらの部分フィールド名は無効です。部分フィールド名にピリオド文字( '。')を含めることはできません。

将来のバージョンのPDFBoxは、これを防止しようとします。PDFBOX-5028を参照してください。

署名時のデフォルトのリソースとデフォルトの外観の設定

署名中に、AcroFormディクショナリのデフォルトのリソースとデフォルトの外観を設定します。

acroForm.setDefaultResources(resources);
...
acroForm.setDefaultAppearance(defaultAppearanceString);

SignAndIdentifySignatureFieldsおよびSign2メソッドaddEmptySignField

それ自体は悪いことではありませんが、すでにそのようなエントリがある以前に署名されたファイルに対してこれを行い、以前とは異なる値に設定すると、以前の署名が無効になる可能性があることに注意してください。ここで回答された問題を参照してください。

必要のないPDFバージョンの設定

申し立てられたPDFバージョンのドキュメントを変更しようとしました。

document.setVersion(1.0f);

SignAndIdentifySignatureFields方法addEmptySignField

document.setVersion(2.0f);

Sign2方法addEmptySignField

ドキュメント自体にはすでに1.5以上のバージョンが必要であるため、最初の命令は無視されますが、2番目の命令は実際にドキュメントのPDFバージョンを2.0に設定するため、古いビューアで問題が発生する可能性があります。

..。

おそらくもっと多くの問題があります。最初の署名を修復するのに十分な最初の問題である重複ページエントリをすでに修正していることに気付く前に、私はこれらの問題を最初に発見しただけです...