如何使用 Java 為 PDF 簽署並加上時間戳記

當您需要保護合約、發票或任何關鍵文件免於被竄改時,如何簽署 PDF 的安全性就成為首要任務。在本指南中,您將學會如何使用 GroupDocs.Signature for Java 為 PDF 添加數位簽章與受信任的時間戳記。此方法可離線執行,支援最高 500 MB 的檔案,且只需幾行程式碼。

快速回答

如何使用 Java 簽署 PDF?

載入 PDF,使用您的憑證配置 DigitalSignature,可選擇從符合 RFC 3161 的 TSA 附加時間戳記,然後呼叫 sign()。Signature 物件會將已簽署的檔案寫入磁碟,回傳一個 SignResult,告訴您操作是否成功並列出任何警告。這個端對端流程只需幾行 Java 程式碼,且會自動處理雜湊、憑證驗證與時間戳記取得。

為何數位簽章重要(以及為何需要時間戳記)

數位簽章保證 authenticity(簽署者身分)與 integrity(文件未被更改)。加入時間戳記可證明簽章在特定時刻已存在,即使簽署憑證之後過期或被撤銷,仍能提供保護。兩者結合提供不可否認性——對法律、金融與合規工作流程至關重要。

設定 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 檔。手動將其加入專案的 classpath。參閱 GroupDocs.Signature Documentation 取得完整 API 參考。欲取得最新建置,請見 Latest Version & Releases。

Pro tip: Maven 或 Gradle 會自動化版本升級與傳遞相依性,讓您在發布新安全修補程式時節省時間。

取得授權

GroupDocs 提供三種授權選項:

  1. Free trial – 評估所有功能且不會加上浮水印。 Download Trial Version
  2. Temporary license – 30 天完整存取金鑰,供開發使用。
  3. Commercial license – 生產環境就緒,無限制使用。 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);

如何在 Java 中為 PDF 添加數位簽章:逐步說明

此流程為線性步驟:匯入類別、設定檔案路徑、建立 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. 憑證問題

Problem: “Invalid certificate” errors.
Fix: Verify the password with keytool -list -v -keystore your.pfx.

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

2. 時間戳記服務逾時

Problem: Network timeouts when contacting the TSA.
Fix: Test connectivity (curl -I https://freetsa.org/tsr), add retry logic, or configure a fallback TSA.

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

3. 檔案權限問題

Problem: “Access denied” while saving.
Fix: Ensure the output directory exists and the application has write permissions.

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

4. 大型 PDF 記憶體問題

Problem: OutOfMemoryError for big files.
Fix: Increase JVM heap (-Xmx4g) or process files in batches.

5. 簽章位置錯誤

Problem: Signature overlaps existing content.
Fix: Test alignment settings first; for pixel‑perfect placement, use coordinate‑based options.

憑證管理技巧

取得開發用憑證

產生自簽憑證以供測試,使用 Java 的 keytool。

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

憑證最佳實踐

  1. Never hard‑code passwords – use environment variables.
  2. Rotate certificates before they expire.
  3. Store private keys in secure hardware (HSM) for high‑security apps.
  4. Back up certificates in a protected location.
  5. Validate certificates before signing to catch expired or revoked ones.

安全最佳實踐

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. Contract management systems – employees sign NDAs and agreements electronically; timestamps prove exactly when each contract was accepted.
  2. Financial document processing – batch‑sign invoices and purchase orders, providing an immutable audit trail for regulators.
  3. Educational credential verification – universities issue tamper‑proof transcripts that can be instantly validated via a QR‑code link.
  4. Software license management – generate license certificates with a digital signature and timestamp to prevent forgery.
  5. Regulatory compliance (FDA 21 CFR Part 11, etc.) – medical device firms sign SOPs and validation reports; timestamps satisfy non‑repudiation requirements.

效能考量與最佳化

記憶體管理

將大型 PDF 分批處理,及時關閉 Signature 物件,必要時增大堆疊大小。

時間戳記的網路最佳化

使用連線池、實作指數退避重試,並快取時間戳記以加速連續簽署。

批次處理最佳實踐

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

避免產生過多執行緒;5‑10 個同時簽署的執行緒可在效能與 TSA 負載之間取得平衡。

磁碟 I/O 最佳化

使用 SSD 作為暫存檔案,減少讀寫循環,並在每次簽署後清理暫存產物。

故障排除指南

錯誤:「Invalid certificate password」

Solution: Verify the password with 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」

Solution: Test the TSA URL, check firewall rules, and add fallback TSA logic.

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

錯誤:「PDF is already signed」

Solution: Detect existing signatures first; either add a counter‑signature or sign a fresh copy.

錯誤:「Access denied」於儲存時

Solution: Ensure the output directory exists, the app has write rights, and no other process locks the file.

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

Solution: Increase JVM heap, process PDFs in smaller batches, or switch to streaming APIs for very large files.

結論與後續步驟

您現在已了解 如何簽署 PDF 檔案的 Java 實作方式、如何加入受信任的時間戳記,以及如何避免常見陷阱。接下來您可以:

  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 的作業系統上執行。

Last Updated: 2026-09-05
Tested With: GroupDocs.Signature 23.9 for Java
Author: 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);
}