0
votes

I have read many of the questions/answers about how to make a pdf ltv enabled using iText. Neither of them worked for me. I have a steam of pdf and I set a signature field which I then use in order to call signDetached method and sign the pdf. I use:

signer.signDetached(new BouncyCastleDigest(), pks, chain,
 Collections.singleton(crlClient), ocspClient, tsc,0, subfilter);

But nothing happened. I have read that you have to include all the certificates except from root. I add the chain of my private certificat (which I use so as to sign pdf), but I have not found a possible way include TSA's certificate.

I use iText version 7.X.

KeyStore ks = getKeyStore();
        Certificate[] chain = null;
        Enumeration<String> al = ks.aliases();
        for (Enumeration<String> l = al; l.hasMoreElements();) {
            String alias = (String) l.nextElement();
            chain = ks.getCertificateChain(alias);
        }
        PrivateKey pk = (PrivateKey) ks.getKey(ks.aliases().nextElement(), "******".toCharArray());
        IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, BouncyCastleProvider.PROVIDER_NAME);
        OCSPVerifier ocspVerifier = new OCSPVerifier(null, null);
        OcspClientBouncyCastle ocspClient = new OcspClientBouncyCastle(ocspVerifier);
        String url = CertificateUtil.getCRLURL((X509Certificate) chain[0]);
        CrlClientOnline crlClient = new CrlClientOnline(url);
        try {
            signer.signDetached(new BouncyCastleDigest(), pks, chain, Collections.singleton(crlClient), ocspClient, tsc,
                    0, subfilter);

        } catch (Exception ex) {
            System.out.println("Tzizzzzzzzzzzzzzzz" + ex.getCause());
        }

private KeyStore getKeyStore()
            throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
        KeyStore ks = KeyStore.getInstance("pkcs12");
        ks.load(new FileInputStream("tsaPath"), "****".toCharArray());
        ks.load(new FileInputStream("p12Path"), "*******".toCharArray());
        return ks;
    }
2
"I have read many of the questions/answers about how to make a pdf ltv enabled using iText. Neither of them worked for me." - in which way did this answer fail to work for you?mkl
Becasue the signature is still not LTV enabled (Acrobat Reader DC) and at certificate details at Revocation tab it says: The selected certificate is considered valid because it does not appear in a Certificate Revocation List (CRL) obtained on-line. The CRL was signed by "ADACOM Class 1 Consumer Individual Subscriber CA - G2" on 2019/02/12 23:59:09 +02'00' and is valid until 2019/02/13 23:59:09 +02'00'. Click Signer Details to get more information on the source of the revocation information.Lefteris Bab
Please share the PDF before and after applying AdobeLtvEnabling. Some limitations of that class are listed at the bottom of that answer. If one of those limitations is the issue, that class might be improved to lift that limitation.mkl
I will try to show you the file, but I would like to find a pfx file that is not from my company. The self signed pfx don’t have the revoke part. So it is a bit difficultLefteris Bab
Well, if you share a replacement pdf, please make sure that ltv enabling fails with it for the same reasons as it does for your actual signed pdfs.mkl

2 Answers

0
votes

After some hours, I figured out a solution. Just to be clear, that Adobe has it's own truststore, so you have to either use one of their certificate or to use the truststore of windows and configure AC Reader accordingly and add the root certificate there. As all have mention you should include all the certification chain inside your PDF document. You can visit my GitHub project in order to see a working example that signs a PDF document, encrypt it with a private key and make it ltv-enabled, using iText 7 using timepstap from ERMIS.

Making ltv enabled sample:

private void ltvEnable(PdfSigner signer, ByteArrayOutputStream baos, OutputStream os, String name,
            OcspClientBouncyCastle ocspClient, CrlClientOnline crlClient, CustomTSAClient tsc) {
        ByteArrayInputStream signedPdfInput = new ByteArrayInputStream(baos.toByteArray());
        try {
            PdfReader pdfReader = new PdfReader(signedPdfInput);
            PdfDocument document = new PdfDocument(pdfReader.setUnethicalReading(true), new PdfWriter(os),
                    new StampingProperties().useAppendMode());
            LtvVerification ltvVerification = new LtvVerification(document);
            ltvVerification.addVerification(name, ocspClient, crlClient, LtvVerification.CertificateOption.WHOLE_CHAIN,
                    LtvVerification.Level.OCSP_CRL, LtvVerification.CertificateInclusion.YES);
            ltvVerification.merge();
            document.getCatalog().getPdfObject().getAsDictionary(PdfName.DSS).getAsArray(PdfName.Certs)
                    .add(new PdfStream(
                            IOUtils.toByteArray(getClass().getClassLoader().getResourceAsStream("HPARCA_CA.cer"))));
            document.close();
            pdfReader.close();

        } catch (IOException | GeneralSecurityException e) {
            LOG.error("Error while making signature ltv enabled");
        }
    }

Tricky part parameters:

OCSPVerifier ocspVerifier = new OCSPVerifier(null, null);
OcspClientBouncyCastle ocspClient = new OcspClientBouncyCastle(ocspVerifier);
CrlClientOnline crlClient = new CrlClientOnline();
0
votes

It is not possible to LTV enable your example signature in general.

First of all, your signer certificate is not from a CA trusted by Adobe Reader by default, i.e. the CA certificate is neither on the AATL nor on the EUTL. The PDF Reader will never call a signature "LTV-enabled" unless it somehow trusts the signer.

Furthermore, the signer certificate does not have any AIA (Authority Information Access) extension from which signing code could determine locations to retrieve the issuer certificate or revocation information from. The missing information makes automatic retrieval of certificates and of revocation information impossible without further ado.

Even if the CA was trusted, therefore, automatic LTV-enabling still would require custom code.


In the course of comments here (and in communication with iText support) it turned out that the provided example signature was not representative; on the other hand there were other relevant boundary conditions, and you eventually got to a routine creating LTV-enabled signatures in your use case.

Details on this routine can be found in your answer.