iText 7将ltv添加到现有签名

时间:2017-03-20 08:50:01

标签: java itext7

我是iText 7的新手, 我尝试使用addLtv()方法(下面提供的代码)将ltv信息添加到现有签名中...如果我理解正确,此方法将crl或ocsp参数添加到现有签名或时间戳,然后为文档添加时间戳,但pdf文档生成的未启用ltv。但是,如果我首先使用ocsp或crl列表签署文档,我能够生成启用了ltv的签名,这使我相信此问题与某些证书缺失或未正确添加无关。所以addLtv()方法由于某种原因对我不起作用。我希望我有道理:D 任何帮助或建议都非常适合:)

    private void addLtv(String src, String dest, IOcspClient ocsp, ICrlClient crl, ITSAClient tsa) throws Exception {
    PdfReader r = new PdfReader(src);
    FileOutputStream fos = new FileOutputStream(dest);
    PdfDocument pdfDoc = new PdfDocument(new PdfReader(src), new PdfWriter(dest));
    PdfSigner ps= new PdfSigner(r, fos, true);

    LtvVerification v = new LtvVerification(pdfDoc);
    SignatureUtil signatureUtil = new SignatureUtil(pdfDoc);

    List<String> names =   signatureUtil.getSignatureNames();
    String sigName = names.get(names.size() - 1);

    PdfPKCS7 pkcs7 = signatureUtil.verifySignature(sigName);

    if (pkcs7.isTsp()) {
        v.addVerification(sigName, ocsp, crl,
                LtvVerification.CertificateOption.WHOLE_CHAIN,
                LtvVerification.Level.CRL,
                LtvVerification.CertificateInclusion.YES);
    }
    else {
        for (String name : names) {
            v.addVerification(name, ocsp, crl,
                    LtvVerification.CertificateOption.WHOLE_CHAIN,
                    LtvVerification.Level.OCSP,
                    LtvVerification.CertificateInclusion.YES);
            v.merge();
        }
    }
    ps.timestamp(tsa, null);
}

1 个答案:

答案 0 :(得分:0)

您的代码中的概念性问题是,在添加LTV信息后,您希望通过时间戳来完成整个过程。虽然这是您想要使用已经在LTV工作流程中的PDF所要做的事情,但您不希望使用PDF所有签名,您希望Adobe Reader将其声明为&#34; LTV启用&# 34。

(人们可以考虑Adobe的术语&#34;支持LTV&#34;意思是&#34;准备进入LTV工作流程,&#34;即尚未实际进入LTV工作流程LTV工作流程,但包括输入它所需的所有验证信息,无需任何进一步的麻烦。)

您的方法中还有其他问题,例如:您创建了两个单独的对象,这些对象通过dest写入PdfSigner psfos通过PdfDocument pdfDoc创建PdfWriter。最后,你要么只能在文件中找到这些对象中的一个对象的输出,要么找到两者中的混合对象。

因此,这是我的旧iText 5方法addLtvNoTS(从this answer)到iText 7的工作端口:

void addLtvNoTS(InputStream src, OutputStream dest, IOcspClient ocsp, ICrlClient crl, LtvVerification.Level timestampLevel, LtvVerification.Level signatureLevel) throws IOException, GeneralSecurityException 
{
    PdfDocument pdfDoc = new PdfDocument(new PdfReader(src), new PdfWriter(dest), new StampingProperties().useAppendMode());

    LtvVerification v = new LtvVerification(pdfDoc);
    SignatureUtil signatureUtil = new SignatureUtil(pdfDoc);

    List<String> names = signatureUtil.getSignatureNames();
    String sigName = names.get(names.size() - 1);

    PdfPKCS7 pkcs7 = signatureUtil.verifySignature(sigName);

    if (pkcs7.isTsp())
    {
        v.addVerification(sigName, ocsp, crl, LtvVerification.CertificateOption.WHOLE_CHAIN,
                timestampLevel, LtvVerification.CertificateInclusion.YES);
    }
    else
    {
        for (String name : names)
        {
            v.addVerification(name, ocsp, crl, LtvVerification.CertificateOption.WHOLE_CHAIN,
                    signatureLevel, LtvVerification.CertificateInclusion.YES);
        }
    }

    v.merge();
    pdfDoc.close();
}

EnableLtv方法addLtvNoTS

如您所见,我为时间戳和签名方法参数设置了LtvVerification.Level值。

这是因为iText的方法LtvVerification.addVerification仅为即时PDF签名和文档时间戳添加LTV信息,而不是针对已嵌入或现在添加的OCSP响应或CRL签名。

通常这没有问题,通常用于签署OCSP响应的证书以指示不需要撤销检查的方式标记,用于签署CRL的证书通常是隐式信任的CA证书本身。

但是,在我的测试签名的情况下,OCSP响应由签名签名,这些签名确实需要撤销检查。为了使事情在没有重要的额外编码的情况下工作,我全部使用了CRL,并为此引入了参数。

实际上,我甚至必须明确地将{CRI URL}提供给CrlClientOnline,因为iText默认只使用证书中的第一个CRL分发点,同时不支持LDAP URL。

底线:您可能还必须围绕当前的iText限制调整代码,或者改进iText代码本身,以便在给定任意有效输入的情况下可靠地生成支持LTV的PDF ...