これについて:
「これは、署名された PDF が本物であることを確認するだけでなく、記録にある署名されていない PDF と同じであることを確認したいからです」
サーバーで取得したドキュメントが本物であることを知りたいだけだとします。
署名済み文書を作成する場合、ファイルの一部のみに署名するか、文書全体に署名するかを選択できます。次に、「ドキュメント全体」の署名を使用できます。サーバーに返されたドキュメントが「本物」である場合 (つまり、署名の検証が成功したことを意味します)、記録されているドキュメントと同じであることは間違いありません。
PDF 署名には、承認署名と認証署名の 2 種類があることに注意してください。ドキュメントDigital Signatures in PDF from Adobe から:
(...) 承認署名。同意、承認、または受諾を示すために誰かが文書に署名します。認証済みドキュメントとは、ドキュメントの使用準備が整ったときに、作成者によって適用された認証署名を含むドキュメントです。発信者は、許可される変更を指定します。許可されている 3 つの変更レベルのいずれかを選択します。
- 変更なし
- フォーム記入のみ
- フォームの記入とコメント
サーバー上にある特定の署名付き文書を、データベース上の署名されていない同等の文書と照合するとします。
文書の識別については、個別に処理することをお勧めします。ドキュメントを開くことができると、そのすべてのページの圧縮解除されたコンテンツの連結からハッシュ (たとえば md5) を作成し、それを元のドキュメントの別の同様のハッシュと比較できます (一度生成して保存することができます)。データベースで)。
私がこのようにする理由は、ドキュメントで使用された署名の種類から独立しているためです。PDF ファイルでフォーム フィールドが編集されたり、注釈が追加されたり、新しい署名が作成されたりしても、ページの内容は変更されず、常に同じままです。
iText を使用している場合は、メソッドPdfReader.getPageContentを使用してページ コンテンツのバイト配列を取得し、その結果を使用して MD5 ハッシュを計算できます。
Java のコードは次のようになります。
PdfReader reader = new PdfReader("myfile.pdf");
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
int pageCount = reader.getNumberOfPages();
for(int i=1;i <= pageCount; i++)
{
byte[] buf = reader.getPageContent(i);
messageDigest.update(buf, 0, buf.length);
}
byte[] hash = messageDigest.digest();
さらに、署名なしで送信され、署名されて戻ってきたファイルをサーバーが受信した場合、署名はファイルのすべてではなく一部のみを参照している可能性があります。このシナリオでは、署名ダイジェストだけではファイルを特定できない可能性があります。
PDF仕様から(私のアカウントの太字のセクション):
署名は、ドキュメント内のデータ(またはデータの一部) のダイジェストを計算し、そのダイジェストをドキュメントに保存することによって作成されます。 PDF ファイルの一部:
- シグネチャ ディクショナリのByteRangeエントリで示される、ファイル内のバイト範囲に対してバイト範囲ダイジェストが計算されます。通常、この範囲はファイル全体であり、シグネチャ ディクショナリは含まれますが、シグネチャ値自体 (Contents エントリ) は含まれません。
- オブジェクト ダイジェスト (PDF 1.5) は、参照されたオブジェクト (通常はルート オブジェクト) からメモリ内のオブジェクトのサブツリーを選択的にウォークすることによって計算されます。結果のダイジェストは、それがどのように計算されたかに関する情報とともに、署名参照ディクショナリ (...) に配置されます。