Aspose.PDF for Javaを使用して電子署名(MDP署名)
現在、AspAspose.PDF for Javaを使用してPDFファイルに電子署名をするコーディングをしており、MDP署名が良いとのことでMDP署名を実装するためAsposeを使用することになった背景があります。
MDP署名について下記リンクで解説があります。
[署名済みの PDF ファイルを開いた時点で「署名した電子証明書の組織名」と「電子証明書を発行した認証局」を確認できる「証明用署名(MDP 署名)※3」を追加しており、署名パネルを開くことなくデジタル文書の発行組織名と電子証明書を発行した電子認証局を一目で確認することが可能となる。]
(https://japansecuritysummit.org/2022/12/5845/)
MDP署名の実装
Asposeのドキュメントに従って下記のようにコーディングしたところ、ファイルサイズが肥大化する事案が発生した。
public static void SignWithTimeStampServer() {
Document document = new Document(_dataDir + "SimpleResume.pdf");
PdfFileSignature signature = new PdfFileSignature(document);
PKCS7 pkcs = new PKCS7("/home/aspose/pdf-examples/Samples/test.pfx", "Start2020");
DocMDPSignature mdp = new DocMDPSignature(pkcs, 1); // 1は変更不可を意味する
java.awt.Rectangle rect = new java.awt.Rectangle(); // 特に座標指定なし
// 3つの署名タイプのいずれかを作成
signature.sign(1, "署名の理由", "連絡先", "場所", false, rect, mdp);
// 出力PDFファイルを保存
signature.save(_dataDir + "DigitallySignWithTimeStamp_out.pdf");
}
ファイルサイズ肥大化の原因
ここでファイルサイズが肥大化の原因は、ここの"署名の理由", "連絡先", "場所"とある日本語の箇所。
ここは署名時に、署名理由、場所(住所とか)を記載してAcrobatで開いたときに署名タブの詳細で表示される箇所。
この"署名の理由", "連絡先", "場所"3つのいずれかに日本語を入れるとファイルサイズが肥大化する。
どの程度かというと、署名前が400kbから署名後9000kbになる。
ちなみに何も入れなかった場合(""で入れる)、400kb→1000kbほど。
適当な英語の場合でもさほど変わらず、400kb→1000kbほど。
// ここがだめ
signature.sign(1, "署名の理由", "連絡先", "場所", false, rect, mdp);
// 日本語1文字:400kb→9000kb
signature.sign(1, "あ", "", "", false, rect, mdp);
// 英語4文字:400kb→1000kb
signature.sign(1, "test", "", "", false, rect, mdp);
// 空文字:400kb→1000kb
signature.sign(1, "", "", "", false, rect, mdp);
肥大化解消に向けて実施した手順(効果なし)
この問題を解消しようと下記のようにいろいろ試したが、一切効果ありませんでした。
1. 署名時に フォントの埋め込みを防ぐ ことで、サイズ増加を防ぐ。
import com.aspose.pdf.*;
import com.aspose.pdf.facades.PdfFileSignature;
import com.aspose.pdf.forms.PKCS7;
public class SignPdf {
public static void main(String[] args) {
// PDF 読み込み
Document pdfDocument = new Document("input.pdf");
// 電子署名を設定
PdfFileSignature pdfSign = new PdfFileSignature();
pdfSign.bindPdf(pdfDocument);
// **フォント埋め込みを無効化**
pdfSign.setSignatureAppearance(null);
// 署名を追加("あ" を入れる)
pdfSign.sign(1, "あ", "", "", new PKCS7("cert.pfx", "password"));
// PDF を保存
pdfSign.save("signed_output.pdf");
}
}
2. 最適化オプションを使う
OptimizationOptions を使って、署名ときの PDF を 軽量化 する。
import com.aspose.pdf.Document;
import com.aspose.pdf.optimization.OptimizationOptions;
public class OptimizePdfAfterSigning {
public static void main(String[] args) {
// 署名済みの PDF を読み込み
Document pdfDocument = new Document("signed_output.pdf");
// 最適化オプションを設定
OptimizationOptions options = new OptimizationOptions();
options.setRemoveUnusedObjects(true); // 未使用オブジェクト削除
options.setRemoveUnusedStreams(true); // 未使用ストリーム削除
options.setUnembedFonts(true); // // 不要なフォントを削除
options.getImageCompressionOptions().setCompressImages(true); // 画像の圧縮
options.getImageCompressionOptions().setImageQuality(50); // 画像の圧縮の品質
// 最適化を実行
pdfDocument.optimizeResources(options);
// 保存
pdfDocument.save("final_optimized.pdf");
}
}
3. 署名時のフォントを変更する
署名時に使用するフォントを日本語フォントではなく 軽量な英字フォント(例: Helvetica)に変更。日本語フォントを 軽量なフォントに置き換え、サイズ増加を防ぐ。
import com.aspose.pdf.*;
import com.aspose.pdf.facades.PdfFileSignature;
import com.aspose.pdf.forms.PKCS7;
public class SignPdfWithFont {
public static void main(String[] args) {
// PDF を読み込む
Document pdfDocument = new Document("input.pdf");
// 署名の外観を設定
PdfFileSignature pdfSign = new PdfFileSignature();
pdfSign.bindPdf(pdfDocument);
// **署名の外観を軽量フォントに変更**
pdfSign.setSignatureAppearance("Helvetica"); // 日本語フォントを回避
// 署名を追加
pdfSign.sign(1, "あ", "", "", new PKCS7("cert.pfx", "password"));
// 保存
pdfSign.save("signed_output.pdf");
}
}
4. 署名時に PKCS7Detached を使用
署名方式を PKCS7Detached に変更すると、証明書データが PDF に埋め込まれなくなる ため、ファイルサイズが小さくなります。PKCS7 の代わりに PKCS7Detached を使用すると、署名データが最小限の情報だけ含まれるためサイズが減る。
import com.aspose.pdf.forms.PKCS7Detached;
pdfSign.sign(1, "あ", "", "", new PKCS7Detached("cert.pfx", "password"));
以上のことを試しましたが、効果なしです。
PDFBoxに頼るか悩み中
実は、無料ライブラリのPDFBoxでのMDP署名がなかなかできず、Asposeに頼った背景があります。(ただの電子署名まではできたのですが。。。。)
ちなみにPDFBoxでただの電子署名をした際には、400kb→420kb程度の増加でした。
Aspose.PDF for Javaはたぶんバグだと思うんですが、似たような記事が見つかりません。
Aspose.PDF for .NETでは問題なく日本語を設定できます。。。
PDFBoxでのMDP署名を頑張ってみるか、Asposeで粘ってみるか、なかなか悩ましいです。