重新加载后无法将 DSS 添加到已签名的 PDF 中

问题描述 投票:0回答:0

根据我目前的理解,在签署 PDF 时不允许为时间戳证书添加

DSS
(如果是签名时间戳)。因此,我尝试首先签署 PDF,保存它,然后将其重新加载为
PDDocument
,为时间戳证书添加
DSS

下面是我的源代码:

//This saves the signed file to responseStream
ByteArrayInputStream responseStream = new ByteArrayInputStream(outputStream.toByteArray());

//Reloads output PDF as PDDocument to embed DSS for TSA Certificates
PDDocument documentForLTV = PDDocument.load(responseStream);

//New response stream with DSS
ByteArrayOutputStream outputStreamLTV = new ByteArrayOutputStream();

//Adds revocation info and certs for TSA into DSS of PDDocument 
addValidationInformation(documentForLTV, TSACertificates);

documentForLTV.saveIncremental(outputStreamLTV);

//Checking updated DSS. Updated DSS shows TSA certs which are expected to be added.
PDDocumentCatalog docCatalog = documentForLTV.getDocumentCatalog();
COSDictionary catalog = docCatalog.getCOSObject();
COSDictionary dss = validationService.getOrCreateDictionaryEntry(COSDictionary.class, catalog, "DSS");
COSArray certs = validationService.getOrCreateDictionaryEntry(COSArray.class, dss, "Certs");

//final output response. This  outputStreamLTV does not contain the TSA Certs and revocation info.
ByteArrayInputStream responseStreamLTV = new ByteArrayInputStream(outputStreamLTV.toByteArray());

documentForLTV.close();
return responseStreamLTV;

在这里,我使用我的方法

addValidationInformation
将时间戳证书和吊销信息添加到DSS。这是相同的方法,我用它来将签名证书的验证信息添加到
DSS
。在调试时,我可以看到它成功地将时间戳证书添加到 DSS。但我在最终输出的 PDF 中找不到它们。
outputStreamLTV
仅包含签名证书的验证信息。

addValidationInformation方法如下:

public void addValidationInformation(PDDocument document, Certificate[] certificateChain) {

        List<String> ocspResponse = getOcspData(certificateChain);
        List<String> crlResponse = getClrData(certificateChain);
        List<String> certificates = getCertificates(certificateChain);

        PDDocumentCatalog docCatalog = document.getDocumentCatalog();
        COSDictionary catalog = docCatalog.getCOSObject();
        catalog.setNeedsTobeUpdated(true);
        // As mentioned in PDFBox Samples
        COSDictionary dss = getOrCreateDictionaryEntry(COSDictionary.class, catalog, "DSS");
        dss.setNeedsTobeUpdated(true);
        COSDictionary vri = getOrCreateDictionaryEntry(COSDictionary.class, dss, "VRI");
        vri.setNeedsTobeUpdated(true);
        COSArray ocsps = getOrCreateDictionaryEntry(COSArray.class, dss, "OCSPs");
        ocsps.setNeedsTobeUpdated(true);
        COSArray crls = getOrCreateDictionaryEntry(COSArray.class, dss, "CRLs");
        crls.setNeedsTobeUpdated(true);
        COSArray certs = getOrCreateDictionaryEntry(COSArray.class, dss, "Certs");
        certs.setNeedsTobeUpdated(true);

        if (ocspResponse != null) {
            ocspResponse.forEach(ocsp -> {
                byte[] ocspData = b64Decoder.decode(ocsp);
                try {
                    ocsps.add(writeDataToStream(ocspData, document));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }

        if (!ocspResponse.isEmpty()) {
            vri.setItem("OCSP", ocsps);
        }

        //Same for CRL and Certs...

    }

我的其他一些发现是:

  1. 我可以使用 PDFBox 示例
    AddValidationInformation
    this 方法以类似的方式添加时间戳证书和吊销信息。但我更喜欢使用我当前的实现,因为该示例并不完全符合我的要求。此外,他们还会为相同的功能添加重复的代码。
  2. 另外,我用
    PDDocument.save(outputStreamLTV)
    代替
    PDDocument.saveIncremental(outputStreamLTV)
    。输出 PDF 显示所需的 DSS,但签名无效。

请建议我如何使现有代码正常工作以及我缺少什么?将 PDDocument 保存到流中时似乎存在一些问题。 或者这是

PDFBox
一侧的错误,因为我可以在签名之前使用相同的方法
addValidationInformation
添加 DSS,使用对 TSA 的一个虚拟调用来获取证书。

java pdfbox digital-signature
© www.soinside.com 2019 - 2024. All rights reserved.