2013-06-17 4 views
1

Я подписываю документ, используя Itext. У меня есть этот метод:Невозможно добавить ltv в документ PDF. Ошибка

public static void sign(String src, String dest, Certificate[] chain,PrivateKey pk, String digestAlgorithm, String provider,CryptoStandard subfilter, TSAClient tsa) 
{ 

     // Creating the reader and the stamper 
     PdfReader reader = new PdfReader(src); 
     FileOutputStream os = new FileOutputStream(dest); 
     PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0'); 

     // Creating the appearance 
     PdfSignatureAppearance appearance = stamper.getSignatureAppearance(); 
     appearance.setVisibleSignature(new Rectangle(10, 20, 100, 200), 1, "sig"); 

     // Creating the signature 
     ExternalDigest digest = new BouncyCastleDigest(); 
     ExternalSignature signature = new PrivateKeySignature(pk, 
     digestAlgorithm, provider); 
     MakeSignature.signDetached(appearance, digest, signature, chain, null,null, tsa, 0, subfilter); 


     // ALREADY SIGNED. ADD LTB NOW. 
     CrlClient crlClient = new CrlClientOnline("http://crl.mycrl.com/mycrl.crl"); 
     OcspClient ocspClient=new OcspClientBouncyCastle();    
    addLtv(DEST, DEST2, ocspClient, crlClient, tsa); 

    } 

и я подпишу:

sign(SRC, String.format(DEST, 1), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "For Testing", " location", tsa); 

все работает. PDF подписанный колодец.

но тогда я не могу добавить ltv. Я использую код из IText документации:

public static void addLtv(String src, String dest, OcspClient ocsp, CrlClient crl, 
     TSAClient tsa) throws IOException, DocumentException, 
     GeneralSecurityException { 

    PdfReader r = new PdfReader(src); 
    FileOutputStream fos = new FileOutputStream(dest); 

    PdfStamper stp = PdfStamper.createSignature(r, fos, '\0', null, true); 
    LtvVerification v = stp.getLtvVerification(); 

    AcroFields fields = stp.getAcroFields(); 

    List<String> names = fields.getSignatureNames(); 
    String sigName = names.get(names.size() - 1); 

    PdfPKCS7 pkcs7 = fields.verifySignature(sigName); 

    if (pkcs7.isTsp()) { 
      v.addVerification(sigName, ocsp, crl, 
       LtvVerification.CertificateOption.SIGNING_CERTIFICATE, 
       LtvVerification.Level.OCSP_CRL, 
       LtvVerification.CertificateInclusion.NO); 
    } 

    else { 
     for (String name : names) { 
      v.addVerification(name, ocsp, crl, 
        LtvVerification.CertificateOption.WHOLE_CHAIN, 
        LtvVerification.Level.OCSP_CRL, 
        LtvVerification.CertificateInclusion.NO); 
     } 
    } 
    PdfSignatureAppearance sap = stp.getSignatureAppearance(); 
    LtvTimestamp.timestamp(sap, tsa, null); 
} 

Редакцией: все работает, но на линии LtvTimestamp.timestamp (живица, АСП, нуль); у меня есть эта ошибка: исключение в потоке «основного» java.io.IOException: Не хватает места

это моя PDF: https://www.dropbox.com/s/o05rw6ubiuslm4j/DOC_SIGNED.pdf

Exception in thread "main" java.io.IOException: Not enough space 
at com.itextpdf.text.pdf.security.LtvTimestamp.timestamp(LtvTimestamp.java:103) 
at ge.digital.signature.DocumentSigner.DigitalSignature.addLtv(MySignature.java:132) 
at ge.digital.signature.DocumentSigner.DigitalSignature.main(MySignature.java:163) 
+1

У вас есть трассировка стека из этого исключения? – mkl

+0

есть. Я обновил свой пост. –

+0

Исключение в теме "main" java.io.IOException: Недостаточно места at com.itextpdf.text.pdf.security.LtvTimestamp.timestamp (LtvTimestamp.java:103) at ge.digital.signature.DocumentSigner.DigitalSignature.addLtv (MySignature.java:132) на ge.digital.signature.DocumentSigner.DigitalSignature.main (MySignature.java:163) –

ответ

3

Это IOException происходит, когда пространство, зарезервированное в формате PDF для интеграции метки времени недостаточно. Таким образом, вы должны изменить метод экземпляра TSAClienttsa, вы вызываете свой метод sign, чтобы вернуть более крупную оценку размера метки времени.

В случае TSAClientBouncyCastle реализации TSAClient, например, вы можете сделать его возвращать произвольные оценки вместо стандартного 4096 если вы используете конструктор с четырьмя аргументами:

public TSAClientBouncyCastle(String url, String username, String password, int tokSzEstimate) 

Некоторые предпосылки: При интегрировании подпись или временный штамп документа в PDF, вы сначала готовите PDF с пробелом заданного размера, а затем вычисляете хэш всего, кроме этого пробела, затем подписываете или помещаете этот хэш и, наконец, объединяете сгенерированную подпись или время штамп в этот промежуток, например

enter image description here

(Это /ByteRange запись является частью подписанного контента. Таким образом, один не может увеличить разрыв.) После

Таким образом, вы должны использовать некоторую оценку размера сгенерированную подпись или отметку времени перед ее поколением.

В случае временных отметок документов, эта оценка обеспечивается TSAClient методом getTokenSizeEstimate.

PS: Для получения еще более подробной информации см this answer, документ Adobe Digital Signatures in a PDF (из которого я скопировал приведенный выше рисунок), а спецификация PDF ISO 32000-1: 2008 была доступна here by Adobe.

+0

спасибо. Ok, getTokenSizeEstimate() Получает оценку размера маркера метки времени. но как я должен установить этот размер оценки в моем pdf? –

+0

Вы не устанавливаете его в формате PDF. Вы меняете реализацию 'TSAClient', чтобы получить более точную оценку. К сожалению, вы не указали, какую реализацию 'TSAClient' вы используете, вы используете только знак' tsa' в '(SRC, String.format (DEST, 1), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, «Для тестирования», «location», tsa) .' – mkl

+0

Теперь я реализую свой TSAClient. Я переопределяю все методы. и я это изменить: @Override \t общественного ИНТ getTokenSizeEstimate() { \t \t возвращение 10000; \t} сейчас он работает. теперь он работает :-) –

Смежные вопросы