首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何为时间戳签名启用LTV?

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

Stack Overflow用户
提问于 2015-01-11 22:45:39
回答 2查看 8.2K关注 0票数 6

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

然而,Acrobat告诉我我的签名是启用LTV的,但是时间戳签名不是:

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

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

丢失撤销信息1 http://img15.hostingpics.net/pics/491507so2a.jpg

丢失撤销信息2 http://img15.hostingpics.net/pics/312720so2b.jpg

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-01-12 16:31:48

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

代码语言:javascript
复制
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 /Acrobat通常不考虑启用此文档时间戳LTV的原因。

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

代码语言:javascript
复制
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();
}

背景

iText addLtv示例不(必然)创建支持LTV的PDF的原因是,它更接近于PAdES规范中提出的LTV最佳实践,而不是PAdES的最佳实践。

根据ETSI TS 10278-4V1.1.2 (2009-12),将LTV应用于其中的文档的结构如图2所示。

通过添加进一步的DSS信息来验证上一个文档时间戳以及一个新的文档时间戳,保护的生命时间可以进一步延长到上一个文档时间戳的寿命之外。如图3所示。

另一方面,根据Adobe (他们的PDF布道者伦纳德·罗森索尔在2013年1月写在iText邮件列表上)的说法,

启用LTV意味着验证文件所需的所有信息(减去根证书)都包含在文件中。所以你的这句话是真的。 PDF正确签名,并包含所有必要的证书,每个证书的有效CRL或OSCP响应,但由于该语句为真的唯一途径是DSS的存在,您必须有支持LTV的DSS才能出现。不需要时间戳(常规或文档级别)。

由于这种差异,根据ETSI,带有LTV的PDF文档通常由Adobe软件提供,以便有一个未启用LTV的文档时间戳。

另请参阅

票数 12
EN

Stack Overflow用户

发布于 2021-02-01 16:35:44

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

  1. 从TSA请求一个虚拟时间戳令牌。
  2. 提取并验证此令牌的信任链。
  3. 将链中证书的OSCP答复和CRLs添加到文档DSS中
  4. 现在为文档(包括更新的DSS)请求第二个时间戳,并使用它为PDF加盖时间戳。
  5. 验证这两个时间戳是否由同一证书签名(对于TSA使用不同证书的可能性不大)

从tsa令牌提取签名证书:

代码语言:javascript
复制
        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] ...

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27892960

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档