我使用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);
由于
答案 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(..)函数