首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >添加dss字典

添加dss字典
EN

Stack Overflow用户
提问于 2015-06-03 18:45:41
回答 3查看 1.3K关注 0票数 2

我正在使用pdfBox完成一个包含撤销信息的pades文档。目标是文档变为启用了LTV。

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

我的问题是,我如何构造一个具有来自CRL和OCSP的响应的COSDictionary?

代码语言:javascript
复制
InMemoryDocument doc = new InMemoryDocument(getFile());
PDDocument document = PDDocument.loadNonSeq(doc.openStream(), null);

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

cosDictionary.setNeedToBeUpdate(true);

谢谢

EN

回答 3

Stack Overflow用户

发布于 2015-06-10 19:29:45

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

代码语言:javascript
复制
COSDictionary dss = createDssDictionary(certificates, crls, ocspResponses);

使用这些辅助方法:

代码语言:javascript
复制
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字典作为增量更新添加到源文档中,如下所示:

代码语言:javascript
复制
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();
}
票数 2
EN

Stack Overflow用户

发布于 2015-07-28 22:11:52

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

代码语言:javascript
复制
private byte[] addCertificates(byte[] pdfFile) throws IOException, PDFLTVEnablerException {

ByteArrayInputStream stream = new ByteArrayInputStream(pdfFile);
PDDocument document = PDDocument.load(stream);

PDDocumentCatalog catalog = document.getDocumentCatalog();
COSDictionary catalogDictionary = catalog.getCOSDictionary();

COSDictionary dssDictionary = (COSDictionary) catalogDictionary.getDictionaryObject("DSS");
dssDictionary.setNeedToBeUpdate(true);

COSArray certDSS = getTrustedCertificatesChain();

dssDictionary.setItem(COSName.getPDFName("Certs"), certDSS);

catalog.getCOSObject().setNeedToBeUpdate(true);
catalogDictionary.setItem(COSName.getPDFName("DSS"), dssDictionary);

File resultFile = File.createTempFile("dss", null);
FileOutputStream fos = new FileOutputStream(resultFile);
FileInputStream fis = new FileInputStream(resultFile);
fos.write(pdfFile);
try {
    document.saveIncremental(fis, fos);
} catch (COSVisitorException e) {
    logger.debug(e.getMessage());
    throw new PDFLTVEnablerException("Couldn't access PDF DSS dictionary");
}

FileInputStream out = new FileInputStream(resultFile);
byte[] byteArray = IOUtils.toByteArray(out);
resultFile.delete();
document.close();
return byteArray;
}

private byte[] addRevocationInfo(byte[] pdfFile) throws IOException, PDFLTVEnablerException {

ByteArrayInputStream stream = new ByteArrayInputStream(pdfFile);
PDDocument document = PDDocument.load(stream);

PDDocumentCatalog catalog = document.getDocumentCatalog();
COSDictionary catalogDictionary = catalog.getCOSDictionary();

COSDictionary dssDictionary = (COSDictionary) catalogDictionary.getDictionaryObject("DSS");
dssDictionary.setNeedToBeUpdate(true);

COSArray crlsDss = loadCrlsForCerts(pdfFile);

dssDictionary.setItem(COSName.getPDFName("CRLs"), crlsDss);
dssDictionary.setItem(COSName.getPDFName("OCSPs"), new COSArray());

catalog.getCOSObject().setNeedToBeUpdate(true);
catalogDictionary.setItem(COSName.getPDFName("DSS"), dssDictionary);

File resultFile = File.createTempFile("dss", null);
FileOutputStream fos = new FileOutputStream(resultFile);
FileInputStream fis = new FileInputStream(resultFile);
fos.write(pdfFile);
try {
    document.saveIncremental(fis, fos);
} catch (COSVisitorException e) {
    logger.debug(e.getMessage());
    throw new PDFLTVEnablerException("Couldn't access PDF DSS dictionary");

}

FileInputStream out = new FileInputStream(resultFile);
byte[] byteArray = IOUtils.toByteArray(out);
resultFile.delete();
document.close();
return byteArray;
}


private COSArray getTrustedCertificatesChain() throws IOException {

COSArray certs = new COSArray();
certs.setNeedToBeUpdate(true);

List < X509Certificate > trustedCerts = trustedCertsStore.getTrustedCerts();

for (X509Certificate cert: trustedCerts) {
    try {
        COSStream certStream = createStream(cert.getEncoded());
        certs.add(certStream);
    } catch (CertificateException e) {
        logger.error("Could not import trusted certificate: " + e.getMessage());
        throw new IOException("The certificate in the truststore is invalid");
    }
}

return certs;
}

private COSArray loadCrlsForCerts(byte[] pdfFile) throws IOException, PDFLTVEnablerException {
COSArray crls = new COSArray();
crls.setNeedToBeUpdate(true);

List < X509Certificate > trustedCerts = trustedCertsStore.getTrustedCerts();

for (X509Certificate cert: trustedCerts) {
    try {
        X509CRL crl = crlDownloader.verifyCertificateCRLs(cert);
        if (crl != null) {
            COSStream crlStream = createStream(crl.getEncoded());
            crls.add(crlStream);
        }
    } catch (CertificateException e) {
        logger.error("Could not import trusted certificate: " + e.getMessage());
        throw new IOException("The certificate in the truststore is invalid");
    } catch (CertificateVerificationException e) {
        logger.error("Could not import trusted certificate: " + e.getMessage());
        throw new IOException("The certificate in the truststore is invalid");
    } catch (CRLException e) {
        logger.debug("Error downloading crl " + e.getMessage());
        throw new Exception("Couldn't retrive CRL");
    } catch (NamingException e) {
        logger.debug(e.getMessage());
        throw new Exception("Couldn't retrive CRL");
    }
}
return crls;
}

public 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;
}
票数 2
EN

Stack Overflow用户

发布于 2015-06-09 22:21:56

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

我从一个PAdESService类型的对象开始,我的目标是将时间戳添加到PDF中。

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

代码语言:javascript
复制
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中获取决策支持系统字典,并将其用作参数来扩展timsetamp(..)类eu.europa.ec.markt.dss.signature.pdf.PDFTimestampService的函数。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30617875

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档