添加dss字典

时间:2015-06-03 10:45:41

标签: java pdf pdf-generation pdfbox

我使用pdfBox完成带有撤销信息的pades文档。目标是文档变为LTV。

我正在使用的文档有1个签名和一个时间戳。我已经获得了必要的crl / ocsp令牌。

我的问题是如何构建一个有CRL和OCSP响应的COSDictionary?

InMemoryDocument doc = new InMemoryDocument(getFile());
PDDocument document = PDDocument.loadNonSeq(doc.openStream(), null);

COSDictionary cosDictionary = document.getDocumentCatalog().getCOSDictionary();
...

cosDictionary.setNeedToBeUpdate(true);

由于

3 个答案:

答案 0 :(得分:2)

假设您有必要的证书,CRL和OCSP响应可用作字节数组,您可以使用PDFBox将它们添加到文档安全存储中:

COSDictionary dss = createDssDictionary(certificates, crls, ocspResponses);

使用这些辅助方法:

COSDictionary createDssDictionary(Iterable<byte[]> certificates, Iterable<byte[]> crls, Iterable<byte[]> ocspResponses) throws IOException
{
    final COSDictionary dssDictionary = new COSDictionary();
    dssDictionary.setNeedToBeUpdate(true);
    dssDictionary.setName(COSName.TYPE, "DSS");

    if (certificates != null)
        dssDictionary.setItem(COSName.getPDFName("Certs"), createArray(certificates));
    if (crls != null)
        dssDictionary.setItem(COSName.getPDFName("CRLs"), createArray(crls));
    if (ocspResponses != null)
        dssDictionary.setItem(COSName.getPDFName("OCSPs"), createArray(ocspResponses));

    return dssDictionary;
}

COSArray createArray(Iterable<byte[]> datas) throws IOException
{
    COSArray array = new COSArray();
    array.setNeedToBeUpdate(true);

    if (datas != null)
    {
        for (byte[] data: datas)
            array.add(createStream(data));
    }

    return array;
}

COSStream createStream(byte[] data) throws IOException
{
    RandomAccessBuffer storage = new RandomAccessBuffer();
    COSStream stream = new COSStream(storage);
    stream.setNeedToBeUpdate(true);
    final OutputStream unfilteredStream = stream.createUnfilteredStream();
    unfilteredStream.write(data);
    unfilteredStream.flush();
    return stream;
}

您可以将此类DSS字典作为增量更新添加到源文档中,如下所示:

try (   InputStream source = ...;
        FileOutputStream fos = new FileOutputStream(resultFile);
        FileInputStream fis = new FileInputStream(resultFile);
        )
{
    byte[] inputBytes = IOUtils.toByteArray(source);

    PDDocument pdDocument = PDDocument.load(new ByteArrayInputStream(inputBytes));
    PDDocumentCatalog catalog = pdDocument.getDocumentCatalog();
    catalog.getCOSObject().setNeedToBeUpdate(true);
    catalog.getCOSDictionary().setItem(COSName.getPDFName("DSS"), dss);

    fos.write(inputBytes);
    pdDocument.saveIncremental(fis, fos);
    pdDocument.close();
}

答案 1 :(得分:2)

再次分析代码后,我在证书编码中发现了一些错误。我认为这是文件腐败的原因。 我用来将链证书添加到DSS字典的代码。我重用了你的代码。 再次感谢。

import scala.pickling.Defaults._
import scala.pickling.json._
import java.awt.geom.Point2D

import Point2DPickler._

val dpoint = new Point2D.Double(1d, 2d)

scala> val json = dpoint.pickle
json: pickling.json.pickleFormat.PickleType =
JSONPickle({
  "$type": "java.awt.geom.Point2D.Double",
  "x": {
    "$type": "scala.Double",
    "value": 1.0
  },
  "y": {
    "$type": "scala.Double",
    "value": 2.0
  }
})

scala> val dpoint2 = json.value.unpickle[java.awt.geom.Point2D.Double]
dpoint2: java.awt.geom.Point2D.Double = Point2D.Double[1.0, 2.0]

答案 2 :(得分:1)

实际上我没有直接使用PDFbox。

我从PAdESService类型的对象开始,我的目标是为PDF添加时间戳。

我已经构建了这样的DSS字典:

private PdfDict createDSSDictionary() throws IOException, CertificateEncodingException {

final PdfDict dssDictionary = factory.newDict("DSS");

for (X509Certificate x509Certificate : certs) {
    PdfStream stream = factory.newStream(x509Certificate.getEncoded());
    certArray.add(stream);
}

if (certArray.size() > 0) {
    dssDictionary.add("Certs", certArray);
}

if (crlArray.size() > 0) {
    dssDictionary.add("CRLs", crlArray);
}

if (ocspArray.size() > 0) {
    dssDictionary.add("OCSPs", ocspArray);
}
return dssDictionary;
}

此方法仅显示Certs流的构造,OCSP和CRL的过程类似。

然后是丑陋的部分。

我已经更改了班级eu.europa.ec.markt.dss.parameter.SignatureParameters。 我添加了参数PdfDict,其中包含我想在PDF中插入的DSS字典(DSS从上一个函数返回)。

然后在课堂上eu.europa.ec.markt.dss.signature.pades.PAdESLevelBaselineLT  我从signatureParameters获取DSS字典并将其用作参数来扩展类eu.europa.ec.markt.dss.signature.pdf.PDFTimestampService的timsetamp(..)函数