You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用PDFBox获取数字签名中时间戳令牌的证书信息

使用PDFBox获取PDF签名时间戳令牌的证书信息

核心步骤说明

要提取PDF签名中嵌入的时间戳令牌证书信息,需通过PDFBox解析签名属性,再借助BouncyCastle解析CMS格式的时间戳令牌,具体流程如下:

  1. 加载PDF并获取签名列表
    用PDDocument加载目标PDF文件,通过getSignatureDictionaries()方法获取文档中所有签名对象。

  2. 定位时间戳令牌属性
    签名的扩展属性存储在Prop_Build字典的Prop子字典中,时间戳令牌对应的PKCS#9属性OID为1.2.840.113549.1.9.16.2.14,通过该OID可提取时间戳的字节流数据。

  3. 解析CMS格式时间戳令牌
    时间戳令牌采用CMS(密码消息语法)格式,需用BouncyCastle的CMSSignedData类解析,从中提取证书存储和签名者信息,最终匹配出时间戳对应的证书。

完整代码示例

import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSString;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.util.Store;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.List;

public class TimestampCertExtractor {
    public static void main(String[] args) throws Exception {
        // 加载目标PDF文档
        try (PDDocument document = PDDocument.load(new File("signed_document.pdf"))) {
            List<PDSignature> signatures = document.getSignatureDictionaries();
            
            // 遍历每个签名
            for (PDSignature signature : signatures) {
                COSDictionary sigPropDict = (COSDictionary) signature.getCOSObject().getDictionaryObject("Prop_Build");
                if (sigPropDict == null) continue;
                
                COSDictionary propDict = (COSDictionary) sigPropDict.getDictionaryObject("Prop");
                if (propDict == null) continue;
                
                // 根据OID获取时间戳令牌字节流
                COSBase tsTokenBase = propDict.getDictionaryObject(new COSName("1.2.840.113549.1.9.16.2.14"));
                if (!(tsTokenBase instanceof COSString)) continue;
                
                byte[] tsTokenBytes = ((COSString) tsTokenBase).getBytes();
                CMSSignedData cmsSignedData = new CMSSignedData(tsTokenBytes);
                
                // 提取证书存储和签名者信息
                Store certStore = cmsSignedData.getCertificates();
                SignerInformationStore signerStore = cmsSignedData.getSignerInfos();
                Collection<SignerInformation> signers = signerStore.getSigners();
                
                // 匹配并输出证书信息
                for (SignerInformation signer : signers) {
                    Collection<X509CertificateHolder> certHolders = certStore.getMatches(signer.getSID());
                    for (X509CertificateHolder certHolder : certHolders) {
                        X509Certificate cert = (X509Certificate) CertificateFactory.getInstance("X.509")
                                .generateCertificate(new ByteArrayInputStream(certHolder.getEncoded()));
                        
                        // 输出证书关键信息
                        System.out.println("=== 时间戳证书信息 ===");
                        System.out.println("颁发者DN: " + cert.getIssuerDN());
                        System.out.println("主体DN: " + cert.getSubjectDN());
                        System.out.println("序列号: " + cert.getSerialNumber());
                        System.out.println("有效期起始: " + cert.getNotBefore());
                        System.out.println("有效期截止: " + cert.getNotAfter());
                    }
                }
            }
        }
    }
}

依赖说明

需引入以下依赖(以Maven为例):

<dependencies>
    <dependency>
        <groupId>org.apache.pdfbox</groupId>
        <artifactId>pdfbox</artifactId>
        <version>2.0.32</version> <!-- 建议使用最新稳定版 -->
    </dependency>
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.70</version>
    </dependency>
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcpkix-jdk15on</artifactId>
        <version>1.70</version>
    </dependency>
</dependencies>

内容的提问来源于stack exchange,提问作者Tanmay Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 11:20:54