当前位置: 首页 > 知识库问答 >
问题:

如何签署PDF嵌入时间戳和LTV启用?

郭元凯
2023-03-14

我试图签署一个pdf与时间戳和LTV启用,以便它是这样显示在Adobe Reader:

在英语中,它意味着“签名包括嵌入的时间戳”和“签名启用了LTV”。下面是我使用的代码:

PrivateKey pk = // get pk from an encrypting certificate created using encrypting file system
Certificate[] chain = ks.getCertificateChain(alias);

PdfReader reader = new PdfReader(src);
FileOutputStream fout = new FileOutputStream(dest);
PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');

PdfSignatureAppearance sap = stp.getSignatureAppearance();

ExternalSignature signature = new PrivateKeySignature(pk, "SHA-512", "SunMSCAPI");
TSAClient tsc = null;
String url = // TSA URL
tsc = new TSAClientBouncyCastle(url, null, null, 4096, "SHA-512");

List<CrlClient> crlList = new ArrayList<>();
crlList.add(new CrlClientOnline(chain));

ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(sap, digest, signature, chain, crlList, null, tsc, 0, CryptoStandard.CMS);

基于此答案,我需要一种方法将TSA证书的CRL获取到CrlList,但是。。如何获得TSA证书?我是否需要向TSA发出时间戳查询请求并读取响应,然后将其添加到CrlList?注意,这已经在MakeSignature中完成了。当它调用sgn时,signDetached。getEncodedPKCS7。请注意,我使用的是免费的TSA服务器。

更新

因为它是一个免费的TSA服务器,我只需要在Adobe可信证书中添加TSA服务器证书,现在它可以工作了。但是,我已经做了另一个测试使用智能卡签署文档,这是我得到的(我已经将根证书添加到Adobe中的受信任证书):

签名详情:

签名证书详细信息:

基于此链接,启用LTV意味着验证文件(减去根证书)所需的所有信息都包含在PDF中。因此,如果PDF签名正确,并且包含所有必要的证书和每个证书的有效CRL或OSCP响应,并且如果PDF包含CRL和OCSP上的签名,而不仅仅是签名证书,则PDF将启用LTV。看起来我满足了所有这些要求,还是我遗漏了什么?如果是这样的话,我如何知道缺少什么才能获得支持LTV的pdf?

共有1个答案

郭意
2023-03-14

首先,基于@mkl注释,我将TSA服务器证书添加到Adobe可信证书,以便消息

签名包含嵌入的时间戳,但无法验证

成为

签名包括嵌入的时间戳

而要解决

签名未启用LTV,将在(...)

我注意到使用

List<CrlClient> crlList = new ArrayList<>();
crlList.add(new CrlClientOnline(chain));

有一些CRL(一些证书有多个分发点)没有被添加-使得pdf LTV没有启用。为了解决这个问题,我这样做:

// long term validation (LTV)
List<CrlClient> crlList = new ArrayList<>();

for(Certificate cert : chain) {
    X509Certificate c = (X509Certificate)cert;
    List<String> crls = this.getCrlDistributionPoints(c);
    if(crls != null && !crls.isEmpty()) {
        crlList.add(new CrlClientOnline(crls.toArray(new String[crls.size()])));
    }
}

private List<String> getCrlDistributionPoints(final X509Certificate cert) throws Exception {
    final byte[] crldpExt = cert.getExtensionValue(X509Extension.cRLDistributionPoints.getId());
    if (crldpExt == null) {
        final List<String> emptyList = new ArrayList<String>();
        return emptyList;
    }
    ASN1InputStream oAsnInStream = null;
    ASN1InputStream oAsnInStream2 = null;
    List<String> crlUrls = new ArrayList<String>();

    try { 
        oAsnInStream = new ASN1InputStream(new ByteArrayInputStream(crldpExt));
        final ASN1Object derObjCrlDP = oAsnInStream.readObject();
        final DEROctetString dosCrlDP = (DEROctetString) derObjCrlDP;
        final byte[] crldpExtOctets = dosCrlDP.getOctets();
        oAsnInStream2 = new ASN1InputStream(new ByteArrayInputStream(crldpExtOctets));
        final ASN1Object derObj2 = oAsnInStream2.readObject();
        final CRLDistPoint distPoint = CRLDistPoint.getInstance(derObj2);
        for (final DistributionPoint dp : distPoint.getDistributionPoints()) {
            final DistributionPointName dpn = dp.getDistributionPoint();
            // Look for URIs in fullName
            if (dpn != null) {
                if (dpn.getType() == DistributionPointName.FULL_NAME) {
                    final GeneralName[] genNames = GeneralNames.getInstance(dpn.getName()).getNames();
                    // Look for an URI
                    for (int j = 0; j < genNames.length; j++) {
                        if (genNames[j].getTagNo() == GeneralName.uniformResourceIdentifier) {
                            final String url = DERIA5String.getInstance(genNames[j].getName()).getString();
                            crlUrls.add(url);
                        }
                    }
                }
            }
        }
    } catch(IOException e) {
        throw new Exception(e.getMessage(), e);
    } finally {
        IOUtils.closeQuietly(oAsnInStream);
        IOUtils.closeQuietly(oAsnInStream2);
    }

    return crlUrls;
}
 类似资料:
  • 我正在使用iText 5.5.3来签署PDF文档。我需要这些文件是时间戳和LTV启用。我按照说明使用addLtv方法(代码示例5.9,Lowagie白皮书第137页)。我得到一个带有2个签名的PDF,这是正常的:第一个是我自己的签名,第二个是文档级时间戳。 但是,Acrobat告诉我我的签名启用了LTV,但时间戳签名没有: 图片来自Acrobat Pro XIhttp://img15.hostin

  • 我对这个话题很陌生。我已经用PKCS#12数字证书签署了一份PDF文档。在Adobe Reader中,当我打开签名面板时,我可以看到“签名已启用LTV”。读了这篇文章,我无法真正理解是否需要应用时间戳。如果没有,我如何验证应用签名的时间?或者我应该添加什么样的验证信息?

  • 我是iText的新手。我想签署一个PDF并添加LTV到它。签署PDF是好的但当我想添加LTV到PDF时,它不显示我的OCSP和时间戳证书的CRL信息。首先,我想描述一下我是如何签约的。-我的证书链:签名证书,签名证书根,时间戳证书,时间戳证书根。(我忘了锁链上有什么东西吗?) 要签名PDF,我使用的是: 之后,我将为签名和时间戳添加LTV。 谢谢你。

  • 我不确定我是否理解文档时间戳的用途。据我所知,这用于在最后一个文档时间戳到期之前添加另一个DSS+时间戳,以扩展文档的签名生存期。 这是否意味着,如果添加没有时间戳,文档在原始证书过期后将不再启用LTV?但那会使LTV的目的落空。

  • 据我所知有两种方法 添加DSS字典 在签名时在签名中嵌入CRL或OCSP响应 DSS方法似乎是可行的,Adobe将签名识别为启用了LTV。第二种方法更适合我们的应用程序,所以我仍在努力让它工作。我在向签名添加OCSP响应时遇到了问题,所以我只尝试添加证书和CRL。如果我错了,请纠正我,但据我所知,CRL或OCSP响应都应该添加到签名中。不需要两者兼而有之吗?我收集签名证书及其根证书,还有TSA证书

  • 我能够使用PDFBox1.8.5对PDF文档进行数字签名,多亏了PDFBOX中提供的这个出色的示例。 https://github.com/apache/pdfbox/blob/1.8/examples/src/main/java/org/apache/pdfbox/examples/signature/createSignature.java 签名此示例时,请使用本地计算机的日期/时间(第175