【问题标题】:Can't add ltv to PDF document. Error无法将 ltv 添加到 PDF 文档。错误
【发布时间】:2013-06-13 11:56:18
【问题描述】:

我正在使用 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);
}

已编辑: 一切正常,但在线 LtvTimestamp.timestamp(sap, tsa, null); 我有那个错误: 线程“主”java.io.IOException 中的异常:空间不足

这是我的 pdf: https://www.dropbox.com/s/o05rw6ubiuslm4j/DOC_SIGNED.pdf

Exception in thread "main" java.io.IOException: Not enough space
at com.itextpdf.text.pdf.security.LtvTimestamp.timestamp(LtvTimestamp.java:103)
at ge.digital.signature.DocumentSigner.DigitalSignature.addLtv(MySignature.java:132)
at ge.digital.signature.DocumentSigner.DigitalSignature.main(MySignature.java:163)

【问题讨论】:

  • 你有那个异常的堆栈跟踪吗?
  • 是的。我已经更新了我的帖子。
  • 线程“主”java.io.IOException 中的异常: ge.digital.signature 的 com.itextpdf.text.pdf.security.LtvTimestamp.timestamp(LtvTimestamp.java:103) 空间不足.DocumentSigner.DigitalSignature.addLtv(MySignature.java:132) 在 ge.digital.signature.DocumentSigner.DigitalSignature.main(MySignature.java:163)

标签: java pdf itext digital-signature digital-certificate


【解决方案1】:

IOException 发生在 PDF 中为集成时间戳保留的空间不足时。因此,您必须更改调用 sign 方法的 TSAClient 实例 tsa 的方法 getTokenSizeEstimate 以返回更大的时间戳大小估计值。

TSAClientTSAClientBouncyCastle 实现的情况下,例如,如果您使用带有四个参数的构造函数,您可以让它返回任意估计值而不是默认的4096

public TSAClientBouncyCastle(String url, String username, String password, int tokSzEstimate)

一些背景知识:将签名或文档时间戳集成到 PDF 中时,您首先准备具有给定大小间隙的 PDF,然后计算除该间隙之外的所有内容的哈希值,然后签名或时间戳该哈希,最后将生成的签名或时间戳整合到该间隙中,例如

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

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

在文档时间戳的情况下,此估计由TSAClient 方法getTokenSizeEstimate. 提供

PS:更多细节请参见。 this answer、Adobe 文档 Digital Signatures in a PDF(我从中复制了上图)和 PDF 规范 ISO 32000-1:2008 提供了 here by Adobe

【讨论】:

  • 谢谢。好的,getTokenSizeEstimate() 获取时间戳令牌大小估计。但是,我应该如何在我的 pdf 上设置这个估计大小?
  • 您没有在 PDF 上设置它。您更改 TSAClient 实现以返回更好的估计。不幸的是,您没有显示您使用哪个TSAClient 实现,您只在sign(SRC, String.format(DEST, 1), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "For Testing", " location", tsa). 中使用了一些tsa
  • 现在我实现了我的 TSAClient。我覆盖了所有方法。我改变了这个:@Override public int getTokenSizeEstimate() { return 10000;它现在可以工作了。现在它可以工作了:-)
  • 对于另一种方法,我使用 TSAClientBouncyCastle 的实现。我称之为实现方法:-)
  • 默认情况下 TSAClientBouncyCastle 返回 4096 作为估计值。这似乎还不够。我建议您使用带有四个参数(String url, String username, String password, int tokSzEstimate)TSAClientBouncyCastle 构造函数并尝试更大的估计值,例如8192.
【解决方案2】:

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

【讨论】:

  • 问题上下文使用 iText。您的答案的上下文是使用 PDFBox。
猜你喜欢
  • 2018-10-05
  • 1970-01-01
  • 2017-11-25
  • 2023-04-05
  • 2014-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多