javaitextdigital-signatureitext7pades

How to PAdES BASELINE LT & LTA in itext using the Java?


I'm working on pdf signatures using itext7 and currently need to support all PAdES signature levels: B-B, B-T, B-LT, B-LTA https://ec.europa.eu/digital-building-blocks/wikis/display/ESIGKB/What+are+the+B-T-LT+and+LTA+levels+of+an+electronic+signature

My problem is how i can create B-LT signature with itext? I have created B-B and B-T with this code:

signer.signDetached(
                new BouncyCastleDigest(),
                customExternalSignature,
                new Certificate[]{clientX509Certificate},
                null,
                null,
                tsaClient,
                0,
                PdfSigner.CryptoStandard.CADES);

Then I wanted add B-LTA level so I have used this code https://github.com/mkl-public/testarea-itext7/blob/master/src/main/java/mkl/testarea/itext7/signature/AdobeLtvEnabling.java to check adding BASELINE-LTA level, but after applying this logic to my signature adobe says that it is BASELINE-LT

enter image description here

This creates two questions:

  1. Is this implementation in AdobeLtvEnabling correct way to add PAdES level B-LT?
  2. Is this proper way to add B-LTA level?
//This method extend B-T signature to B-LT
private byte[] addLt(final byte[] signed) throws IOException, GeneralSecurityException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        try (InputStream resource = new ByteArrayInputStream(signed);
             PdfReader pdfReader = new PdfReader(resource);
             PdfWriter pdfWriter = new PdfWriter(out);
             PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter, new StampingProperties().preserveEncryption().useAppendMode())) {
            AdobeLtvEnabling adobeLtvEnabling = new AdobeLtvEnabling(pdfDocument);
            IOcspClient ocsp = new OcspClientBouncyCastle(null);
            ICrlClient crl = new CrlClientOnline();
            adobeLtvEnabling.enable(ocsp, crl);
        }

        return addLtv(out.toByteArray());
    }

//This method extend B-LT signature to B-LTA
private byte[] addLtv(final byte[] pdf) throws IOException, GeneralSecurityException {
        final ByteArrayOutputStream signedFile = new ByteArrayOutputStream();
        final PdfReader sourceDoc = new PdfReader(new ByteArrayInputStream(pdf));
        final PdfSigner signer = new PdfSigner(sourceDoc, signedFile, STAMPING_PROPERTIES);

        signer.timestamp(tsaClient, null);

        return signedFile.toByteArray();
    }

Solution

  • Looks about right. The only material difference between PAdES-B-LT and PAdES-B-LTA is that the signature validation data needs to be timestamped as well. As such, to go from PAdES-B-LT to PAdES-B-LTA, it suffices to add a document timestamp.

    With iText, that more or less works like this:

    try(InputStream is = ...; // this should contain the PAdES-B-LT output
        PdfReader reader = new PdfReader(is);
        OutputStream os = new FileOutputStream(OUTPUT_DOCUMENT)) {
    
        PdfSigner pdfSigner = new PdfSigner(reader, os, new StampingProperties().useAppendMode());
        // .timestamp(...) is for producing document timestamps
        pdfSigner.timestamp(tsaClient, timeStampFieldName);
    }
    

    See also here for some context: https://dzone.com/articles/7-tips-for-creating-pdf-signatures (ignore the buzzfeedy title...).

    EDIT: If you're looking for a tool to test your PAdES signatures for conformance with the format requirements in the specification, you might want to request access to the ETSI conformance checker: https://signatures-conformance-checker.etsi.org/pub/index.php.