Java とタイムスタンプで PDF に署名する方法

契約書や請求書、重要な文書を改ざんから保護する必要があるとき、PDF に署名する方法は最優先課題となります。このガイドでは、GroupDocs.Signature for Java を使用して PDF にデジタル署名と信頼できるタイムスタンプを追加する方法を紹介します。オフラインで動作し、最大 500 MB のファイルに対応し、数行のコードで実装できます。

クイック回答

Java で PDF に署名する方法は?

PDF を読み込み、証明書で DigitalSignature を構成し、必要に応じて RFC 3161 準拠の TSA からタイムスタンプを添付し、sign() を呼び出します。Signature オブジェクトは署名済みファイルをディスクに書き込み、SignResult を返して操作の成功可否と警告を一覧で示します。このエンドツーエンドのフローは数行の Java コードで実現でき、ハッシュ計算、証明書検証、タイムスタンプ取得を自動で処理します。

デジタル署名が重要な理由(タイムスタンプが必要な理由)

デジタル署名は 真正性(誰が署名したか)と 完全性(文書が変更されていないこと)を保証します。タイムスタンプを追加すると、署名が特定の時点で存在したことが証明され、後で署名証明書が失効または取り消されても保護されます。これにより、法的、金融、規制ワークフローに不可欠な 否認防止 が実現します。

GroupDocs.Signature for Java のセットアップ

統合方法

使用したいビルドツールを選択してください:

Maven ユーザー向け
pom.xml に依存関係を追加します:

以下の Maven 座標は GroupDocs.Signature for Java の最新安定版を取得します。

<dependency>
    <groupId>com.groupdocs</groupId>
    <artifactId>groupdocs-signature</artifactId>
    <version>23.12</version>
</dependency>

Gradle ユーザー向け
build.gradle に行を追加します:

Gradle は Maven Central からライブラリを解決します。

implementation 'com.groupdocs:groupdocs-signature:23.12'

直接ダウンロード(希望する場合)
GroupDocs.Signature for Java releases にアクセスして JAR ファイルをダウンロードしてください。プロジェクトのクラスパスに手動で追加します。完全な API リファレンスは GroupDocs.Signature Documentation を参照してください。最新ビルドについては Latest Version & Releases をご覧ください。

プロのヒント: Maven または Gradle はバージョンアップとトランジティブ依存関係を自動化し、新しいセキュリティパッチがリリースされたときに時間を節約します。

ライセンス取得

GroupDocs は 3 つのライセンスオプションを提供しています:

  1. 無料トライアル – ウォーターマークなしで全機能を評価できます。 Download Trial Version
  2. 一時ライセンス – 開発用の 30 日間フルアクセスキー。
  3. 商用ライセンス – 本番環境対応、無制限使用。 Buy License

質問がある場合は、GroupDocs Forum のコミュニティが活発です。

基本的な初期化

Signature は GroupDocs.Signature の最上位オブジェクトで、メモリ内の単一 PDF ファイルを表します。インスタンスを作成すると、すべての読み書き操作がそれを通じて行われます。

import com.groupdocs.signature.Signature;

String filePath = "YOUR_DOCUMENT_DIRECTORY/sample.pdf";
final Signature signature = new Signature(filePath);

PDF にデジタル署名を追加する Java 手順:ステップバイステップ

プロセスは直線的です:クラスをインポートし、ファイルパスを設定し、Signature オブジェクトを作成し、オプションのタイムスタンプ付きで DigitalSignature を構成し、SignOptions を定義してから署名して保存します。

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

以下のインポートにより、署名設定、位置指定、タイムスタンプ機能にアクセスできます。

import com.groupdocs.signature.Signature;
import com.groupdocs.signature.domain.enums.HorizontalAlignment;
import com.groupdocs.signature.domain.enums.VerticalAlignment;
import com.groupdocs.signature.domain.signatures.PdfDigitalSignature;
import com.groupdocs.signature.domain.structs.TimeStamp;
import com.groupdocs.signature.options.sign.DigitalSignOptions;

ステップ 2: ファイルパスを定義

入力 PDF、証明書(PFX)、出力先のパスを設定します。証明書ファイルはプライベートキーを含むため、安全に保管してください。

String filePath = "YOUR_DOCUMENT_DIRECTORY/sample.pdf";
String certificatePath = "YOUR_DOCUMENT_DIRECTORY/certificate.pfx";
String outputFilePath = "YOUR_OUTPUT_DIRECTORY/digitallySignedTimeStamp.pdf";

ステップ 3: Signature オブジェクトを初期化

Signature はすべての署名操作のエントリーポイントです。作成すると PDF がメモリにロードされ、API がさらに操作できるようになります。

final Signature signature = new Signature(filePath);

ステップ 4: 署名プロパティとタイムスタンプを設定

DigitalSignature は PDF に埋め込まれる暗号シールです。信頼できる機関からタイムスタンプを添付することもできます。

PdfDigitalSignature pdfDigitalSignature = new PdfDigitalSignature();
pdfDigitalSignature.setContactInfo("Contact Information");
pdfDigitalSignature.setLocation("Location Info");
pdfDigitalSignature.setReason("Signing Reason");

// Configure the TimeStamp with URL, User Id, and Password
TimeStamp timeStamp = new TimeStamp("https://freetsa.org/tsr", "User Id", "Password");
pdfDigitalSignature.setTimeStamp(timeStamp);

デモ用に FreeTSA(無料タイムスタンプ機関)を使用します。本番環境では、稼働率と法的効力が保証された商用 TSA を選択してください。

ステップ 5: デジタル署名オプションを設定

SignOptions は証明書、視覚的外観、配置設定をまとめたものです。

DigitalSignOptions options = new DigitalSignOptions(certificatePath);
options.setPassword("YourCertificatePassword"); // Certificate password
options.setSignature(pdfDigitalSignature); // Attach the PdfDigitalSignature object

// Specify signature alignment (where it appears on the page)
options.setVerticalAlignment(VerticalAlignment.Bottom);
options.setHorizontalAlignment(HorizontalAlignment.Right);

ステップ 6: ドキュメントに署名して保存

SignResult は署名操作の結果を提供し、成功ステータスと警告を一覧で示します。

try {
    SignResult signResult = signature.sign(outputFilePath, options);
    System.out.println("Document signed successfully!");
    System.out.println("Output: " + outputFilePath);
} catch (Exception e) {
    throw new RuntimeException("Error during signing process: " + e.getMessage());
}

避けるべき一般的な落とし穴

1. 証明書の問題

問題: “Invalid certificate” エラー。
解決策: keytool -list -v -keystore your.pfx でパスワードを確認してください。

keytool -list -v -keystore certificate.pfx -storetype PKCS12

2. タイムスタンプサービスのタイムアウト

問題: TSA への接続時にネットワークタイムアウトが発生。
解決策: 接続性をテスト(curl -I https://freetsa.org/tsr)、リトライロジックを追加、またはフォールバック TSA を設定してください。

new File(outputFilePath).getParentFile().mkdirs();

3. ファイル権限の問題

問題: 保存時に “Access denied”。
解決策: 出力ディレクトリが存在し、アプリが書き込み権限を持っていることを確認してください。

keytool -genkeypair -alias mykey -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore certificate.pfx -validity 365

4. 大きな PDF のメモリ問題

問題: 大きなファイルで OutOfMemoryError が発生。
解決策: JVM ヒープを増やす(-Xmx4g)か、ファイルをバッチ処理してください。

5. 署名位置の誤り

問題: 署名が既存のコンテンツと重なる。
解決策: まず配置設定をテストし、ピクセル単位の正確な配置には座標ベースのオプションを使用してください。

証明書管理のヒント

開発用証明書の取得

テスト用に Java の keytool で自己署名証明書を生成します。

   String certPassword = System.getenv("CERT_PASSWORD");

証明書のベストプラクティス

  1. パスワードをハードコードしない – 環境変数を使用。
  2. 証明書を期限前にローテーション する。
  3. プライベートキーを安全なハードウェア(HSM)に保管 して高セキュリティアプリに対応。
  4. 証明書を保護された場所にバックアップ する。
  5. 署名前に証明書を検証 し、期限切れや失効を検出する。

セキュリティのベストプラクティス

1. プライベートキーを保護

証明書はプロジェクトディレクトリ外に保管し、環境固有の設定を使用し、エンタープライズ展開では HSM の導入を検討してください。

2. 入力 PDF を検証

署名前に破損、既存の署名、サイズ制限、コンテンツの準拠をチェックしてください。

3. 監査ログを実装

タイムスタンプ、ユーザー、ドキュメント名、ステータスを含めて、すべての署名操作を記録します。

try {
    SignResult result = signature.sign(outputFilePath, options);
    logger.info("Document signed: " + filePath + " by " + signerEmail);
} catch (Exception e) {
    logger.error("Signing failed: " + filePath + " - " + e.getMessage());
    // Handle appropriately
}

4. 信頼できるタイムスタンプ機関を使用

ローカルシステム時刻に依存せず、常に RFC 3161 準拠の TSA からタイムスタンプを取得してください。

5. エラーハンドリングを実装

機密情報を漏らさないように例外を捕捉してください。

try {
    signature.sign(outputFilePath, options);
} catch (Exception e) {
    // Log detailed error internally
    logger.error("Signing error: " + e.getMessage(), e);
    // Return generic error to client
    throw new ApplicationException("Unable to sign document. Please try again.");
}

実際のユースケースとアプリケーション

  1. 契約管理システム – 従業員が NDA や契約書に電子署名し、タイムスタンプで各契約が受諾された正確な時刻を証明します。
  2. 金融文書処理 – 請求書や発注書をバッチ署名し、規制当局向けに改ざん不可能な監査証跡を提供します。
  3. 教育資格検証 – 大学が改ざん防止の成績証明書を発行し、QR コードリンクで即座に検証可能にします。
  4. ソフトウェアライセンス管理 – デジタル署名とタイムスタンプ付きのライセンス証明書を生成し、偽造を防止します。
  5. 規制コンプライアンス(FDA 21 CFR Part 11 など) – 医療機器企業が SOP や検証レポートに署名し、タイムスタンプで否認防止要件を満たします。

パフォーマンス考慮事項と最適化

メモリ管理

大容量 PDF はバッチで処理し、Signature オブジェクトは速やかにクローズし、必要に応じてヒープサイズを増やします。

タイムスタンプのネットワーク最適化

HTTP 接続をプールし、指数バックオフのリトライを実装し、連続署名時にはタイムスタンプをキャッシュします。

バッチ処理のベストプラクティス

// Pseudo‑code: process a list of PDFs in parallel, limiting to 5 concurrent TSA calls

スレッドを過剰に生成しないでください;5〜10 の同時署名がスループットと TSA の負荷のバランスを取ります。

ディスク I/O の最適化

一時ファイルには SSD を使用し、読み書きサイクルを最小限に抑え、署名実行後は一時アーティファクトをクリーンアップします。

トラブルシューティングガイド

エラー: “Invalid certificate password”

解決策: keytool -list -keystore your.pfx でパスワードを確認してください。

ExecutorService executor = Executors.newFixedThreadPool(5);
List<Future<SignResult>> futures = new ArrayList<>();

for (String pdfPath : pdfPaths) {
    futures.add(executor.submit(() -> {
        try (Signature sig = new Signature(pdfPath)) {
            return sig.sign(outputPath, options);
        }
    }));
}

// Wait for all to complete
for (Future<SignResult> future : futures) {
    SignResult result = future.get();
    // Process result
}

executor.shutdown();

エラー: “Timestamp authority not responding”

解決策: TSA の URL をテストし、ファイアウォール設定を確認し、フォールバック TSA ロジックを追加してください。

keytool -list -v -keystore certificate.pfx -storetype PKCS12

エラー: “PDF is already signed”

解決策: まず既存の署名を検出し、カウンター署名を追加するか、新しいコピーに署名してください。

エラー: 保存時の “Access denied”

解決策: 出力ディレクトリが存在し、アプリに書き込み権限があり、他のプロセスがファイルをロックしていないことを確認してください。

TimeStamp timeStamp;
try {
    timeStamp = new TimeStamp("https://freetsa.org/tsr", "", "");
} catch (Exception e) {
    // Fallback to alternative TSA
    timeStamp = new TimeStamp("https://alternate-tsa.com/tsr", "", "");
}

エラー: OutOfMemoryError

解決策: JVM ヒープを増やす、PDF を小さなバッチで処理する、または非常に大きなファイルの場合はストリーミング API に切り替えてください。

File outputFile = new File(outputFilePath);
outputFile.getParentFile().mkdirs(); // Create directories if needed

if (!outputFile.canWrite() && outputFile.exists()) {
    throw new IOException("Cannot write to " + outputFilePath);
}

結論と次のステップ

あなたは PDF に署名 し、信頼できるタイムスタンプを追加し、一般的な落とし穴を回避する方法を学びました。次に取り組むべきことは:

  1. 複数の署名フィールドを追加して、複数当事者の合意に対応する。
  2. GroupDocs.Signature を使用してプログラムで署名を検証する。
  3. 署名の視覚的外観(画像、テキスト、位置)をカスタマイズする。
  4. キューイングと監視を備えた堅牢なバッチ署名サービスを構築する。

よくある質問

Q: デジタル署名と電子署名の違いは何ですか?
A: デジタル署名は暗号アルゴリズムを使用して本人確認と改ざん検出を行うのに対し、電子署名は単に名前を入力したり画像を貼り付けたりするだけの簡易的なものです。

Q: PDF に署名するためにインターネット接続は必要ですか?
A: タイムスタンプサービスのためだけに必要です;暗号署名自体はローカルで実行されます。

Q: 署名済み PDF は後で編集できますか?
A: 変更が加わると署名が破損し、PDF ビューアは文書が変更された旨の警告を表示します。

Q: 署名済み PDF をどのように検証しますか?
A: 多くの PDF リーダーは自動で検証します。プログラムで検証する場合は、GroupDocs.Signature の検証 API を使用してステータス、署名者情報、タイムスタンプの有効性を確認できます。

Q: 署名後に証明書が期限切れになった場合はどうなりますか?
A: 埋め込まれたタイムスタンプが署名が有効だった時点を証明するため、証明書が失効しても法的効力が保たれます。

Q: これをクラウドストレージ(S3、Azure Blob など)で使用できますか?
A: はい。PDF を一時的にダウンロードして署名し、署名後にクラウドに再アップロードします。

Q: ファイルサイズの制限はありますか?
A: ライブラリはメモリに全体を読み込まずに最大 500 MB の PDF を処理できます。より大きなファイルはストリーミング方式が必要です。

Q: 商用利用の場合、GroupDocs.Signature の費用はいくらですか?
A: 料金は導入形態により異なります。最新の価格は GroupDocs の営業担当にお問い合わせください。評価版や一時ライセンスも利用可能です。

Q: Linux サーバーでも動作しますか?
A: 完全に対応しています。GroupDocs.Signature for Java はプラットフォームに依存せず、JRE があればどの OS でも実行できます。

最終更新日: 2026-09-05
テスト環境: GroupDocs.Signature 23.9 for Java
作者: GroupDocs

関連チュートリアル

File outputFile = new File(outputFilePath);
outputFile.getParentFile().mkdirs(); // Create directories if needed

if (!outputFile.canWrite() && outputFile.exists()) {
    throw new IOException("Cannot write to " + outputFilePath);
}