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

如何为时间戳签名启用LTV?

张嘉
2023-03-14

我正在使用iText 5.5.3来签署PDF文档。我需要这些文件是时间戳和LTV启用。我按照说明使用addLtv方法(代码示例5.9,Lowagie白皮书第137页)。我得到一个带有2个签名的PDF,这是正常的:第一个是我自己的签名,第二个是文档级时间戳。

但是,Acrobat告诉我我的签名启用了LTV,但时间戳签名没有:

图片来自Acrobat Pro XIhttp://img15.hostingpics.net/pics/727285so2.jpg

这是因为时间戳证书的撤销信息没有嵌入到文档中:

缺少吊销信息1http://img15.hostingpics.net/pics/491507so2a.jpg

缺少吊销信息2http://img15.hostingpics.net/pics/312720so2b.jpg

根据我的理解,addLtv方法应该获得所需的所有撤销信息,并将其嵌入到文档中。这是正确的,还是我必须“手动”获取并嵌入这些信息?

共有2个答案

叶元凯
2023-03-14

我所做的是通过请求两个时间戳(使用第一个时间戳提取LTV数据并更新DSS,使用第二个时间戳实际为文档添加时间戳),在为文档添加时间戳之前为时间戳嵌入LTV数据:

  1. 从TSA请求虚拟时间戳令牌
  2. 提取并验证此令牌的信任链
  3. 在文档DSS中为链中的证书添加OSP回复和CRL
  4. 现在请求文档的第二个时间戳(包括更新的DSS),并用它来给PDF加盖时间戳
  5. 验证两个时间戳由同一个证书签名(对于不太可能的情况,TSA使用不同的证书)

从tsa令牌中提取签名证书:

        IDigest messageDigest = tsaClient.GetMessageDigest();
        byte[] tsImprint = new byte[messageDigest.GetDigestSize()];
        messageDigest.DoFinal(tsImprint, 0);
        byte[] tsToken;
        try {
            tsToken = tsaClient.GetTimeStampToken(tsImprint);
        } catch(Exception e) {
            throw new GeneralSecurityException(e.Message);
        }
        Asn1Sequence asn1Seq = Asn1Sequence.GetInstance(tsToken);
        ContentInfo sigData = ContentInfo.GetInstance(asn1Seq);
        TimeStampToken token = new TimeStampToken(sigData);
        IX509Store tokenCerts = token.GetCertificates("COLLECTION");
        List<X509Certificate> signingCerts = new List<X509Certificate>();
        foreach(X509Certificate cert in tokenCerts.GetMatches(token.SignerID)) {
            signingCerts.Add(cert);
        }
        // now perform LTV steps for signingCerts[0] ...
孔鸿云
2023-03-14

这是该问题涉及的示例代码:

public void addLtv(String src, String dest, OcspClient ocsp, CrlClient crl, TSAClient tsa) throws IOException, DocumentException, GeneralSecurityException
{
    PdfReader r = new PdfReader(src);
    FileOutputStream fos = new FileOutputStream(dest);
    PdfStamper stp = PdfStamper.createSignature(r, fos, '\0', null, true);
    LtvVerification v = stp.getLtvVerification();
    AcroFields fields = stp.getAcroFields();
    List<String> names = fields.getSignatureNames();
    String sigName = names.get(names.size() - 1);
    PdfPKCS7 pkcs7 = fields.verifySignature(sigName);
    if (pkcs7.isTsp())
    {
        v.addVerification(sigName, ocsp, crl,
            LtvVerification.CertificateOption.SIGNING_CERTIFICATE,
            LtvVerification.Level.OCSP_CRL,
            LtvVerification.CertificateInclusion.NO);
    }
    else
    {
        for (String name : names)
        {
            v.addVerification(name, ocsp, crl,
                LtvVerification.CertificateOption.WHOLE_CHAIN,
                LtvVerification.Level.OCSP_CRL,
                LtvVerification.CertificateInclusion.NO);
        }
    }
    PdfSignatureAppearance sap = stp.getSignatureAppearance();
    LtvTimestamp.timestamp(sap, tsa, null);
}

此代码标识PDF中最近填写的签名字段,并检查它是文档时间戳还是常用签名。

如果它是文档时间戳,则代码仅为此文档时间戳添加验证信息。否则,代码将为所有签名添加验证信息。

(这背后的假设工作流程是首先对文档进行多次签名(用于认证和/或批准),然后文档进入LTV周期,添加验证信息和文档时间戳,但不再进行常规签名。您的工作流程可能会有所不同,因此您的程序逻辑也会有所不同。(

只有在完成所有这些之后,才会添加新的文档时间戳。

对于最终添加的时间戳,没有向PDF中明确添加验证信息(如果来自同一TSA的文件时间戳已短时间连续应用,则先前时间戳中包含的验证信息可能适用)。这就是为什么Adobe Reader/AcROBAT通常不考虑这个文档时间戳启用LTV的原因。

如果您也需要此最终文档时间戳的验证信息,只需将此方法(与上述方法相同,只是不添加文档时间戳)应用于具有文档时间戳的文件:

public void addLtvNoTS(String src, String dest, OcspClient ocsp, CrlClient crl) throws IOException, DocumentException, GeneralSecurityException
{
    PdfReader r = new PdfReader(src);
    FileOutputStream fos = new FileOutputStream(dest);
    PdfStamper stp = new PdfStamper(r, fos, '\0', true);
    LtvVerification v = stp.getLtvVerification();
    AcroFields fields = stp.getAcroFields();
    List<String> names = fields.getSignatureNames();
    String sigName = names.get(names.size() - 1);
    PdfPKCS7 pkcs7 = fields.verifySignature(sigName);
    if (pkcs7.isTsp())
    {
        v.addVerification(sigName, ocsp, crl,
            LtvVerification.CertificateOption.SIGNING_CERTIFICATE,
            LtvVerification.Level.OCSP_CRL,
            LtvVerification.CertificateInclusion.NO);
    }
    else
    {
        for (String name : names)
        {
            v.addVerification(name, ocsp, crl,
                LtvVerification.CertificateOption.WHOLE_CHAIN,
                LtvVerification.Level.OCSP_CRL,
                LtvVerification.CertificateInclusion.NO);
        }
    }
    stp.close();
}

为什么iTextaddtlv示例不(一定)创建支持LTV的PDF,是因为它更接近ETSI在PAdES规范中提出的LTV最佳实践,而不是Adobe的LTV最佳实践。

根据ETSI TS 102 778-4 V1。1.2(2009-12)采用LTV的PDF文件的结构如图2所示。

通过添加进一步的DSS信息来验证前一个最后一个文档的时间戳以及新文档的时间戳,可以进一步延长保护的生命期,使其超过应用的最后一个文档的时间戳的生命期。图3说明了这一点。

另一方面,根据Adobe(2013年1月,他们的PDF传道者Leonard Rosenthol在iText邮件列表上撰文)的说法,

启用LTV意味着验证文件所需的所有信息(减去根证书)都包含在其中。所以你的这个说法是真的。

PDF已正确签名,并包含所有必要的证书、每个证书的有效CRL或OSCP响应

但是,由于该语句为真的唯一方法是DSS的存在,因此必须启用LTV的DSS才能显示。不需要时间戳(常规或文档级别)。

由于这种分歧,根据ETSI,PDF文档与LTV通常由Adobe软件呈现,以具有一个不启用LTV的文档时间戳。

另见

  • 在iText中启用LTV
 类似资料:
  • 我试图签署一个pdf与时间戳和LTV启用,以便它是这样显示在Adobe Reader: 在英语中,它意味着“签名包括嵌入的时间戳”和“签名启用了LTV”。下面是我使用的代码: 基于此答案,我需要一种方法将TSA证书的CRL获取到,但是。。如何获得TSA证书?我是否需要向TSA发出请求并读取响应,然后将其添加到?注意,这已经在。请注意,我使用的是免费的TSA服务器。 更新 因为它是一个免费的TSA服

  • 我尝试使用外部Web服务对pdf进行数字签名。此Web服务包含用户证书,用户可以使用他们的凭据和一次性密码生成的代码访问该证书。 旁注:web服务应该期望pdf摘要(哈希),但奇怪的是,它却接受整个文件。 无论如何,实现如下: pdf已成功签名,但使用Adobe Reader并检查签名字段时,似乎缺少可信时间戳,如图所示: 看起来,来自远程服务的响应是一个签名对象,我只需要将其嵌入到PDF文件中。

  • 我在使用可信时间戳创建Bouncy Castle的有效CMS签名时遇到了问题。签名创建工作正常(我想将签名包含到PDF文件中),签名是有效的。但是在我将可信时间戳包含到签名的无符号属性表后,签名仍然有效,但是读者报告签名包括嵌入的时间戳,但它是无效的。这让我相信,哈希I时间戳不是正确的,但我似乎无法弄清楚它的问题。 签署代码: 代码: : 谢谢你的帮助! 示例文件: 签名PDF 未签名的PDF 用

  • 这个问题与另一个问题相连。 由于我想完全验证添加到PAdES签名(过期和撤销)中的时间戳,我还需要将crl文件或创建时间戳时捕获的TSA证书的ocsp响应添加到签名中。 据我所知,iText 5.4.1似乎没有提供此功能。特别是通过 com.itextpdf.text.pdf.security.TSAClientBouncyCastle和 com.itextpdf.text.pdf.securit

  • 问题内容: 我在使用受信任的时间戳与Bouncy Castle创建有效的CMS签名时遇到问题。签名创建工作良好(我想将签名包括到PDF文件中),签名有效。但是,当我在签名的未签名属性表中添加可信时间戳后,签名仍然保持有效,但是Reader会报告 该签名包括嵌入式时间戳,但是无效 。这使我相信,哈希时间戳是不正确的,但是我似乎无法弄清楚问题出在哪里。 签名代码: 该代码: : 谢谢你的帮助! 示例文

  • 问题内容: 当我尝试自签名时,如下所示。 它给出如下警告: 没有提供-tsa或- tsacert,并且这个jar没有时间戳记。如果没有时间戳,则用户可能无法在签署者证书的到期日期(2014-05-08)或以后的任何吊销日期之后验证此jar。 请帮助解决问题。 问题答案: 最近的Java 7提供了(礼貌吗?)关于已经存在十年的警告。 Trusted Timestamping在Java 5(2004)