Java Can';t将ltv添加到PDF文档中。错误

Java Can';t将ltv添加到PDF文档中。错误,java,pdf,itext,digital-signature,digital-certificate,Java,Pdf,Itext,Digital Signature,Digital Certificate,我正在用Itext签署文件。我有这样的方法: public static void sign(String src, String dest, Certificate[] chain,PrivateKey pk, String digestAlgorithm, String provider,CryptoStandard subfilter, TSAClient tsa ) { // Creating the reader and the stamper Pdf

我正在用Itext签署文件。我有这样的方法:

public static void sign(String src, String dest, Certificate[] chain,PrivateKey pk, String digestAlgorithm, String provider,CryptoStandard subfilter, TSAClient tsa )
{

        // Creating the reader and the stamper
        PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);
        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');

        // Creating the appearance
        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
        appearance.setVisibleSignature(new Rectangle(10, 20, 100, 200), 1, "sig");

        // Creating the signature
        ExternalDigest digest = new BouncyCastleDigest();
        ExternalSignature signature = new PrivateKeySignature(pk,
        digestAlgorithm, provider);
        MakeSignature.signDetached(appearance, digest, signature, chain, null,null, tsa, 0, subfilter);


        // ALREADY SIGNED. ADD LTB NOW.
        CrlClient crlClient = new CrlClientOnline("http://crl.mycrl.com/mycrl.crl");
        OcspClient  ocspClient=new OcspClientBouncyCastle();              
    addLtv(DEST, DEST2, ocspClient, crlClient, tsa);

    }
我签署:

sign(SRC, String.format(DEST, 1), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "For Testing", " location", tsa);
一切都能正常工作。PDF签名良好

但是,我不能添加ltv。我使用itext文档中的代码:

public static 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中为集成时间戳而保留的空间不足时,会发生
IOException
。因此,您必须更改
TSAClient
实例
tsa
的方法
getTokenSizeEstimate
,调用
sign
方法以返回更大的时间戳大小估计值

TSAClientBouncyCastle
实现
TSAClient
的情况下,例如,如果使用具有四个参数的构造函数,则可以使其返回任意估计值,而不是默认的
4096

public TSAClientBouncyCastle(String url, String username, String password, int tokSzEstimate)
一些背景:在将签名或文档时间戳集成到PDF中时,首先准备具有给定大小间隔的PDF,然后计算除了该间隔之外的所有内容的哈希,然后对该哈希进行签名或时间戳,最后将生成的签名或时间戳集成到该间隔中,例如

(该/ByteRange条目是签名内容的一部分。因此,之后不能扩大差距。)

因此,您必须在生成签名或时间戳之前对其大小进行一些估计

对于文档时间戳,此估计值由
TSAClient
方法
getTokenSizeEstimate.


PS:更多详细信息,请参阅Adobe文档(我从中复制了上图)和PDF规范ISO 32000-1:2008。

如果您未使用
TSAClientBouncyCastle
并且创建了自己的
TSAClient
您必须设置签名的首选大小,创建一个
org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions
类,然后设置类似于
SignatureOptions.setPreferredSignatureSize(8192*2)

的内容,是否有该异常的堆栈跟踪?是的。我已经更新了线程“main”java.io.IOException中的post.Exception:com.itextpdf.text.pdf.security.LtvTimestamp.timestamp(LtvTimestamp.java:103)ge.digital.signature.DocumentSigner.DigitalSignature.addLtv(MySignature.java:132)ge.digital.signature.DocumentSigner.DigitalSignature.main(MySignature.java:163)中的空间不足,谢谢。好的,getTokenSizeEstimate()获取时间戳令牌大小估计值。但是,我应该如何在我的pdf上设置此估计大小?您不能在pdf上设置它。您可以更改
TSAClient
实现以返回更好的估计值。不幸的是,您没有显示您使用的
TSAClient
实现,您只在
sign(SRC,String.format(DEST,1),chain,pk,DigestAlgorithms.SHA256,provider.getName(),CryptoStandard.CMS,“用于测试”,“位置”,tsa)中使用了一些
tsa
现在我实现了我的TSAClient。我覆盖了所有的方法。我改变这个:@Override public int getTokenSizeEstimate(){return 10000;}它现在可以工作了。现在它工作了:-)对于另一个方法,我使用TSAClientBouncyCastle的实现。我称之为实现方法:-)默认情况下,
TSAClientBouncyCastle
4096
作为估计值返回。这似乎还不够。我建议您使用带有四个参数的
(字符串url、字符串用户名、字符串密码、int-tokSzEstimate)的
TSAClientBouncyCastle
构造函数
并尝试更大的估计值,例如
8192。
问题上下文使用的是iText。答案的上下文是使用PDFBox。
public TSAClientBouncyCastle(String url, String username, String password, int tokSzEstimate)