2015-06-03 2 views
1

Я использую pdfBox для заполнения документа pades с информацией об отзыве. Цель состоит в том, что документ становится LTV включенным.Добавить dss dictionary

Документ, который я использую, имеет 1 подпись и одну метку времени. У меня есть необходимые токены crl/ocsp.

Мой вопрос в том, как я могу построить COSDictionary, имеющий ответ от CRL и OCSP?

Благодаря

+0

Ваше использование 'InMemoryDocument', кажется, указывает на то, что вы используете соединение sd-dss для EU. Текущая версия разработки 4.5-SNAPSHOT этого проекта использует PDFBox 1.8.8. Я еще не видел чистого способа использования механизма увеличения PDFBox 1.8.x для чего угодно, кроме добавления подписей. Если я правильно вас понимаю, вы хотите добавить информацию, относящуюся к валидации, в словарь DSS, не добавляя метку времени документа. Таким образом, вам потребуется инкрементное обновление. Я боюсь, что нет простого способа сделать это, возможно, вам придется немного улучшить PDFBox. – mkl

+0

yes Я использую sd-dss для расширения документов до уровня LTA. Например, у меня есть документ, который имеет 1 подпись и 1 временную метку от TSA. В этом случае лицо, подписавшее подпись, не включило информацию об отзыве. Таким образом, adobe скажет, что подпись не поддерживает LTV, а временная метка. Мой вопрос заключается в том, как я могу добавить информацию об аннулировании подписки в словарь DSS. – Hugo

+0

Я попытаюсь изучить это в течение долгих выходных, чтобы начать сейчас. Как уже упоминалось выше, я еще не видел простого способа достижения необходимого, то есть постепенного обновления с помощью PDFBox для чего-то другого, кроме подписи. – mkl

ответ

0

На самом деле я не использовал 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, процедура для OCSPs и CRLs аналогично.

Тогда наступает уродливая часть.

Я изменил класс eu.europa.ec.markt.dss.parameter.SignatureParameters. Я добавил параметр PdfDict, содержащий словарь DSS, который я хочу вставить в PDF (DSS возвращается из предыдущей функции).

Тогда в классе eu.europa.ec.markt.dss.signature.pades.PAdESLevelBaselineLT я получаю словарь DSS от signatureParameters и использовать его в качестве параметра для расширения функции timsetamp (..) класса ес. europa.ec.markt.dss.signature.pdf.PDFTimestampService .

+0

Как я вижу, у вас есть сертификаты, CRL и ответы OCSP в этих классах оболочки sd-dss для PDF-словарей и массивов. Как вы сами говорите, вы * не использовали PDFbox напрямую. * С другой стороны, ваш вопрос звучит так, будто вы ищете решение с помощью PDFBox напрямую (или у вас по крайней мере нет проблем с использованием такого решения. предположим, что у вас есть те сертификаты, CRL и ответы OCSP в развернутой форме. – mkl

2

Если у вас есть необходимые сертификаты, CRL, и ответы OCSP доступных в виде байтовых массивов, вы можете добавить их к магазину безопасности Документа, как это с помощью PDFBox:

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

делает использование этих вспомогательных методов:

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

    if (certifiates != null) 
     dssDictionary.setItem(COSName.getPDFName("Certs"), createArray(certifiates)); 
    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(); 
} 
+0

Спасибо, я пробовал этот метод, но в конце концов подписи повреждены. Adobe говорит, что «есть проблема с сигнатурами» – Hugo

+0

Hhmmm, это удивительно. Можете ли вы поделиться образцом с ошибкой? – mkl

+0

Прошу прощения за поздний ответ, сегодня я не в офисе, но завтра я отправлю образец. Спасибо. – Hugo

2

После анализа кода снова я обнаружил некоторые ошибки в кодировке сертификатов. Я думаю, что это стало причиной коррупции в документе. Ниже приведен код, который я использовал для добавления сертификатов цепей в словарь DSS. Я повторно использовал ваш код. Спасибо еще раз.

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; 
} 
+0

Итак, если я правильно понял ваш код, вы получите действительную подпись LTV, не добавляя информацию OCSP в DSS? – Darajan

+1

Да, но я добавляю CRL в словарь DSS. – Hugo