Example usage for org.apache.pdfbox.pdmodel.interactive.digitalsignature PDSignature getSignedContent

List of usage examples for org.apache.pdfbox.pdmodel.interactive.digitalsignature PDSignature getSignedContent

Introduction

In this page you can find the example usage for org.apache.pdfbox.pdmodel.interactive.digitalsignature PDSignature getSignedContent.

Prototype

public byte[] getSignedContent(byte[] pdfFile) throws IOException 

Source Link

Document

Return the signed content of the document.

Usage

From source file:eu.europa.ec.markt.dss.signature.pdf.pdfbox.PdfBoxCMSInfo.java

License:Open Source License

/**
 * @param validationCertPool/*w ww. j  a v a2 s  . com*/
 * @param outerCatalog       the PDF Dict of the outer document, if the PDFDocument in a enclosed revision. Can be null.
 * @param document           the signed PDFDocument
 * @param cms                the CMS bytes (CAdES signature)
 * @param inputStream        the stream of the whole signed document
 * @throws IOException
 */
PdfBoxCMSInfo(CertificatePool validationCertPool, PdfDict outerCatalog, PDDocument document,
        PDSignature signature, byte[] cms, InputStream inputStream) throws DSSException, IOException {
    this.validationCertPool = validationCertPool;
    this.outerCatalog = PdfDssDict.build(outerCatalog);
    this.cms = cms;
    this.location = signature.getLocation();
    this.signingDate = signature.getSignDate() != null ? signature.getSignDate().getTime() : null;
    this.signatureByteRange = signature.getByteRange();
    final COSDictionary cosDictionary = document.getDocumentCatalog().getCOSDictionary();
    final PdfBoxDict documentDict = new PdfBoxDict(cosDictionary, document);
    documentDictionary = PdfDssDict.build(documentDict);
    try {
        if (cms == null) {
            // due to not very good revision extracting
            throw new DSSPadesNoSignatureFound();
        }
        signedBytes = signature.getSignedContent(inputStream);
    } catch (IOException e) {
        throw new DSSException(e);
    }
}

From source file:eu.europa.esig.dss.pades.InfiniteLoopDSS621Test.java

License:Open Source License

/**
 * These signatures are invalid because of non ordered signed attributes
 */// w  w  w.  ja v  a  2s .c  om
@Test
public void manualTest() throws Exception {

    File pdfFile = new File(FILE_PATH);

    FileInputStream fis = new FileInputStream(pdfFile);
    byte[] pdfBytes = IOUtils.toByteArray(fis);

    PDDocument document = PDDocument.load(pdfFile);
    List<PDSignature> signatures = document.getSignatureDictionaries();
    assertEquals(6, signatures.size());

    int idx = 0;
    for (PDSignature pdSignature : signatures) {
        byte[] contents = pdSignature.getContents(pdfBytes);
        byte[] signedContent = pdSignature.getSignedContent(pdfBytes);

        logger.info("Byte range : " + Arrays.toString(pdSignature.getByteRange()));

        IOUtils.write(contents, new FileOutputStream("target/sig" + (idx++) + ".p7s"));

        ASN1InputStream asn1sInput = new ASN1InputStream(contents);
        ASN1Sequence asn1Seq = (ASN1Sequence) asn1sInput.readObject();

        logger.info("SEQ : " + asn1Seq.toString());

        ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(asn1Seq.getObjectAt(0));
        assertEquals(PKCSObjectIdentifiers.signedData, oid);

        SignedData signedData = SignedData
                .getInstance(DERTaggedObject.getInstance(asn1Seq.getObjectAt(1)).getObject());

        ASN1Set digestAlgorithmSet = signedData.getDigestAlgorithms();
        ASN1ObjectIdentifier oidDigestAlgo = ASN1ObjectIdentifier
                .getInstance(ASN1Sequence.getInstance(digestAlgorithmSet.getObjectAt(0)).getObjectAt(0));
        DigestAlgorithm digestAlgorithm = DigestAlgorithm.forOID(oidDigestAlgo.getId());
        logger.info("DIGEST ALGO : " + digestAlgorithm);

        ContentInfo encapContentInfo = signedData.getEncapContentInfo();
        ASN1ObjectIdentifier contentTypeOID = encapContentInfo.getContentType();
        logger.info("ENCAPSULATED CONTENT INFO TYPE : " + contentTypeOID);

        if (!PKCSObjectIdentifiers.id_ct_TSTInfo.equals(contentTypeOID)) { // If not timestamp
            assertEquals(PKCSObjectIdentifiers.data, contentTypeOID);

            ASN1Encodable content = encapContentInfo.getContent();
            logger.info("ENCAPSULATED CONTENT INFO CONTENT : " + content);
            assertNull(content);

            List<X509Certificate> certificates = extractCertificates(signedData);

            ASN1Set signerInfosAsn1 = signedData.getSignerInfos();
            logger.info("SIGNER INFO ASN1 : " + signerInfosAsn1.toString());
            SignerInfo signedInfo = SignerInfo
                    .getInstance(ASN1Sequence.getInstance(signerInfosAsn1.getObjectAt(0)));

            ASN1Set authenticatedAttributeSet = signedInfo.getAuthenticatedAttributes();
            logger.info("AUTHENTICATED ATTR : " + authenticatedAttributeSet);

            Attribute attributeDigest = null;
            for (int i = 0; i < authenticatedAttributeSet.size(); i++) {
                Attribute attribute = Attribute.getInstance(authenticatedAttributeSet.getObjectAt(i));
                if (PKCSObjectIdentifiers.pkcs_9_at_messageDigest.equals(attribute.getAttrType())) {
                    attributeDigest = attribute;
                    break;
                }
            }

            assertNotNull(attributeDigest);

            ASN1OctetString asn1ObjString = ASN1OctetString
                    .getInstance(attributeDigest.getAttrValues().getObjectAt(0));
            String embeddedDigest = Base64.encodeBase64String(asn1ObjString.getOctets());
            logger.info("MESSAGE DIGEST : " + embeddedDigest);

            byte[] digestSignedContent = DSSUtils.digest(digestAlgorithm, signedContent);
            String computedDigestSignedContentEncodeBase64 = Base64.encodeBase64String(digestSignedContent);
            logger.info("COMPUTED DIGEST SIGNED CONTENT BASE64 : " + computedDigestSignedContentEncodeBase64);
            assertEquals(embeddedDigest, computedDigestSignedContentEncodeBase64);

            SignerIdentifier sid = signedInfo.getSID();
            logger.info("SIGNER IDENTIFIER : " + sid.getId());

            IssuerAndSerialNumber issuerAndSerialNumber = IssuerAndSerialNumber
                    .getInstance(signedInfo.getSID());
            ASN1Integer signerSerialNumber = issuerAndSerialNumber.getSerialNumber();
            logger.info("ISSUER AND SN : " + issuerAndSerialNumber.getName() + " " + signerSerialNumber);

            BigInteger serial = issuerAndSerialNumber.getSerialNumber().getValue();
            X509Certificate signerCertificate = null;
            for (X509Certificate x509Certificate : certificates) {
                if (serial.equals(x509Certificate.getSerialNumber())) {
                    signerCertificate = x509Certificate;
                }
            }
            assertNotNull(signerCertificate);

            String algorithm = signerCertificate.getPublicKey().getAlgorithm();
            EncryptionAlgorithm encryptionAlgorithm = EncryptionAlgorithm.forName(algorithm);

            ASN1OctetString encryptedInfoOctedString = signedInfo.getEncryptedDigest();
            String signatureValue = Hex.toHexString(encryptedInfoOctedString.getOctets());

            logger.info("SIGNATURE VALUE : " + signatureValue);

            Cipher cipher = Cipher.getInstance(encryptionAlgorithm.getName());
            cipher.init(Cipher.DECRYPT_MODE, signerCertificate);
            byte[] decrypted = cipher.doFinal(encryptedInfoOctedString.getOctets());

            ASN1InputStream inputDecrypted = new ASN1InputStream(decrypted);

            ASN1Sequence seqDecrypt = (ASN1Sequence) inputDecrypted.readObject();
            logger.info("DECRYPTED : " + seqDecrypt);

            DigestInfo digestInfo = new DigestInfo(seqDecrypt);
            assertEquals(oidDigestAlgo, digestInfo.getAlgorithmId().getAlgorithm());

            String decryptedDigestEncodeBase64 = Base64.encodeBase64String(digestInfo.getDigest());
            logger.info("DECRYPTED BASE64 : " + decryptedDigestEncodeBase64);

            byte[] encoded = authenticatedAttributeSet.getEncoded();
            byte[] digest = DSSUtils.digest(digestAlgorithm, encoded);
            String computedDigestFromSignatureEncodeBase64 = Base64.encodeBase64String(digest);
            logger.info("COMPUTED DIGEST FROM SIGNATURE BASE64 : " + computedDigestFromSignatureEncodeBase64);

            assertEquals(decryptedDigestEncodeBase64, computedDigestFromSignatureEncodeBase64);

            IOUtils.closeQuietly(inputDecrypted);

        }

        IOUtils.closeQuietly(asn1sInput);
    }

    IOUtils.closeQuietly(fis);
    document.close();
}

From source file:eu.europa.esig.dss.pades.signature.PAdESLevelBTest.java

License:Open Source License

@Override
protected void onDocumentSigned(byte[] byteArray) {

    try {/*from www  .j a  va 2  s .co  m*/
        InputStream inputStream = new ByteArrayInputStream(byteArray);

        PDDocument document = PDDocument.load(inputStream);
        List<PDSignature> signatures = document.getSignatureDictionaries();
        assertEquals(1, signatures.size());

        for (PDSignature pdSignature : signatures) {
            byte[] contents = pdSignature.getContents(byteArray);
            byte[] signedContent = pdSignature.getSignedContent(byteArray);

            logger.info("Byte range : " + Arrays.toString(pdSignature.getByteRange()));

            // IOUtils.write(contents, new FileOutputStream("sig.p7s"));

            ASN1InputStream asn1sInput = new ASN1InputStream(contents);
            ASN1Sequence asn1Seq = (ASN1Sequence) asn1sInput.readObject();

            logger.info("SEQ : " + asn1Seq.toString());

            ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(asn1Seq.getObjectAt(0));
            assertEquals(PKCSObjectIdentifiers.signedData, oid);

            SignedData signedData = SignedData
                    .getInstance(DERTaggedObject.getInstance(asn1Seq.getObjectAt(1)).getObject());

            ASN1Set digestAlgorithmSet = signedData.getDigestAlgorithms();
            ASN1ObjectIdentifier oidDigestAlgo = ASN1ObjectIdentifier
                    .getInstance(ASN1Sequence.getInstance(digestAlgorithmSet.getObjectAt(0)).getObjectAt(0));
            DigestAlgorithm digestAlgorithm = DigestAlgorithm.forOID(oidDigestAlgo.getId());
            logger.info("DIGEST ALGO : " + digestAlgorithm);

            ContentInfo encapContentInfo = signedData.getEncapContentInfo();
            ASN1ObjectIdentifier contentTypeOID = encapContentInfo.getContentType();
            logger.info("ENCAPSULATED CONTENT INFO TYPE : " + contentTypeOID);
            assertEquals(PKCSObjectIdentifiers.data, contentTypeOID);

            ASN1Encodable content = encapContentInfo.getContent();
            logger.info("ENCAPSULATED CONTENT INFO CONTENT : " + content);
            assertNull(content);

            List<X509Certificate> certificates = extractCertificates(signedData);

            ASN1Set signerInfosAsn1 = signedData.getSignerInfos();
            logger.info("SIGNER INFO ASN1 : " + signerInfosAsn1.toString());
            SignerInfo signedInfo = SignerInfo
                    .getInstance(ASN1Sequence.getInstance(signerInfosAsn1.getObjectAt(0)));

            ASN1Set authenticatedAttributeSet = signedInfo.getAuthenticatedAttributes();
            logger.info("AUTHENTICATED ATTR : " + authenticatedAttributeSet);

            List<ASN1ObjectIdentifier> attributeOids = new ArrayList<ASN1ObjectIdentifier>();
            int previousSize = 0;
            for (int i = 0; i < authenticatedAttributeSet.size(); i++) {
                Attribute attribute = Attribute.getInstance(authenticatedAttributeSet.getObjectAt(i));
                ASN1ObjectIdentifier attrTypeOid = attribute.getAttrType();
                attributeOids.add(attrTypeOid);
                int size = attrTypeOid.getEncoded().length + attribute.getEncoded().length;
                assertTrue(size >= previousSize);

                previousSize = size;
            }
            logger.info("List of OID for Auth Attrb : " + attributeOids);

            Attribute attributeDigest = Attribute.getInstance(authenticatedAttributeSet.getObjectAt(1));
            assertEquals(PKCSObjectIdentifiers.pkcs_9_at_messageDigest, attributeDigest.getAttrType());

            ASN1OctetString asn1ObjString = ASN1OctetString
                    .getInstance(attributeDigest.getAttrValues().getObjectAt(0));
            String embeddedDigest = Base64.encodeBase64String(asn1ObjString.getOctets());
            logger.info("MESSAGE DIGEST : " + embeddedDigest);

            byte[] digestSignedContent = DSSUtils.digest(digestAlgorithm, signedContent);
            String computedDigestSignedContentEncodeBase64 = Base64.encodeBase64String(digestSignedContent);
            logger.info("COMPUTED DIGEST SIGNED CONTENT BASE64 : " + computedDigestSignedContentEncodeBase64);
            assertEquals(embeddedDigest, computedDigestSignedContentEncodeBase64);

            SignerIdentifier sid = signedInfo.getSID();
            logger.info("SIGNER IDENTIFIER : " + sid.getId());

            IssuerAndSerialNumber issuerAndSerialNumber = IssuerAndSerialNumber
                    .getInstance(signedInfo.getSID());
            ASN1Integer signerSerialNumber = issuerAndSerialNumber.getSerialNumber();
            logger.info("ISSUER AND SN : " + issuerAndSerialNumber.getName() + " " + signerSerialNumber);

            BigInteger serial = issuerAndSerialNumber.getSerialNumber().getValue();
            X509Certificate signerCertificate = null;
            for (X509Certificate x509Certificate : certificates) {
                if (serial.equals(x509Certificate.getSerialNumber())) {
                    signerCertificate = x509Certificate;
                }
            }
            assertNotNull(signerCertificate);

            String algorithm = signerCertificate.getPublicKey().getAlgorithm();
            EncryptionAlgorithm encryptionAlgorithm = EncryptionAlgorithm.forName(algorithm);

            ASN1OctetString encryptedInfoOctedString = signedInfo.getEncryptedDigest();
            String signatureValue = Hex.toHexString(encryptedInfoOctedString.getOctets());

            logger.info("SIGNATURE VALUE : " + signatureValue);

            Cipher cipher = Cipher.getInstance(encryptionAlgorithm.getName());
            cipher.init(Cipher.DECRYPT_MODE, signerCertificate);
            byte[] decrypted = cipher.doFinal(encryptedInfoOctedString.getOctets());

            ASN1InputStream inputDecrypted = new ASN1InputStream(decrypted);

            ASN1Sequence seqDecrypt = (ASN1Sequence) inputDecrypted.readObject();
            logger.info("DECRYPTED : " + seqDecrypt);

            DigestInfo digestInfo = new DigestInfo(seqDecrypt);
            assertEquals(oidDigestAlgo, digestInfo.getAlgorithmId().getAlgorithm());

            String decryptedDigestEncodeBase64 = Base64.encodeBase64String(digestInfo.getDigest());
            logger.info("DECRYPTED BASE64 : " + decryptedDigestEncodeBase64);

            byte[] encoded = authenticatedAttributeSet.getEncoded();
            byte[] digest = DSSUtils.digest(digestAlgorithm, encoded);
            String computedDigestFromSignatureEncodeBase64 = Base64.encodeBase64String(digest);
            logger.info("COMPUTED DIGEST FROM SIGNATURE BASE64 : " + computedDigestFromSignatureEncodeBase64);

            assertEquals(decryptedDigestEncodeBase64, computedDigestFromSignatureEncodeBase64);

            IOUtils.closeQuietly(inputDecrypted);
            IOUtils.closeQuietly(asn1sInput);
        }

        IOUtils.closeQuietly(inputStream);
        document.close();
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
        fail(e.getMessage());
    }
}

From source file:eu.europa.esig.dss.pdf.pdfbox.PdfBoxSignatureService.java

License:Open Source License

private List<PdfSignatureOrDocTimestampInfo> getSignatures(CertificatePool validationCertPool,
        byte[] originalBytes) {
    List<PdfSignatureOrDocTimestampInfo> signatures = new ArrayList<PdfSignatureOrDocTimestampInfo>();
    ByteArrayInputStream bais = null;
    PDDocument doc = null;/*from www.  j a v  a  2  s .  co  m*/
    try {

        bais = new ByteArrayInputStream(originalBytes);
        doc = PDDocument.load(bais);

        List<PDSignature> pdSignatures = doc.getSignatureDictionaries();
        if (CollectionUtils.isNotEmpty(pdSignatures)) {
            logger.debug("{} signature(s) found", pdSignatures.size());

            PdfDict catalog = new PdfBoxDict(doc.getDocumentCatalog().getCOSDictionary(), doc);
            PdfDssDict dssDictionary = PdfDssDict.extract(catalog);

            for (PDSignature signature : pdSignatures) {
                String subFilter = signature.getSubFilter();
                byte[] cms = signature.getContents(originalBytes);

                if (StringUtils.isEmpty(subFilter) || ArrayUtils.isEmpty(cms)) {
                    logger.warn("Wrong signature with empty subfilter or cms.");
                    continue;
                }

                byte[] signedContent = signature.getSignedContent(originalBytes);
                int[] byteRange = signature.getByteRange();

                PdfSignatureOrDocTimestampInfo signatureInfo = null;
                if (PdfBoxDocTimeStampService.SUB_FILTER_ETSI_RFC3161.getName().equals(subFilter)) {
                    boolean isArchiveTimestamp = false;

                    // LT or LTA
                    if (dssDictionary != null) {
                        // check is DSS dictionary already exist
                        if (isDSSDictionaryPresentInPreviousRevision(
                                getOriginalBytes(byteRange, signedContent))) {
                            isArchiveTimestamp = true;
                        }
                    }

                    signatureInfo = new PdfBoxDocTimestampInfo(validationCertPool, signature, dssDictionary,
                            cms, signedContent, isArchiveTimestamp);
                } else {
                    signatureInfo = new PdfBoxSignatureInfo(validationCertPool, signature, dssDictionary, cms,
                            signedContent);
                }

                if (signatureInfo != null) {
                    signatures.add(signatureInfo);
                }
            }
            Collections.sort(signatures, new PdfSignatureOrDocTimestampInfoComparator());
            linkSignatures(signatures);

            for (PdfSignatureOrDocTimestampInfo sig : signatures) {
                logger.debug("Signature " + sig.uniqueId() + " found with byteRange "
                        + Arrays.toString(sig.getSignatureByteRange()) + " (" + sig.getSubFilter() + ")");
            }
        }

    } catch (Exception e) {
        logger.warn("Cannot analyze signatures : " + e.getMessage(), e);
    } finally {
        IOUtils.closeQuietly(bais);
        IOUtils.closeQuietly(doc);
    }

    return signatures;
}

From source file:pdfbox.SignatureVerifier.java

License:Apache License

public Map<String, SignatureResult> extractSignatures(File infile) throws IOException, CertificateException,
        NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException {
    Map<String, SignatureResult> result = new HashMap<>();

    try (PDDocument document = PDDocument.load(infile)) {
        for (PDSignature sig : document.getSignatureDictionaries()) {
            COSDictionary sigDict = sig.getCOSObject();
            COSString contents = (COSString) sigDict.getDictionaryObject(COSName.CONTENTS);

            // download the signed content
            byte[] buf;
            try (FileInputStream fis = new FileInputStream(infile)) {
                buf = sig.getSignedContent(fis);
            }//from  w ww  .j  ava2s  .  c o m

            System.out.println("Signature found");
            System.out.println("Name:     " + sig.getName());
            System.out.println("Modified: " + sdf.format(sig.getSignDate().getTime()));
            String subFilter = sig.getSubFilter();
            if (subFilter != null) {
                switch (subFilter) {
                case "adbe.pkcs7.detached": // COSName.ADBE_PKCS7_DETACHED
                    result.put(sig.getName(), verifyPKCS7(buf, contents, sig));

                    //TODO check certificate chain, revocation lists, timestamp...
                    break;
                case "adbe.pkcs7.sha1": // COSName.ADBE_PKCS7_SHA1
                {
                    // example: PDFBOX-1452.pdf
                    //COSString certString = (COSString) sigDict.getDictionaryObject(
                    //        COSName.CONTENTS);
                    byte[] certData = contents.getBytes();
                    Collection<? extends Certificate> certs = getCertificates(certData);
                    System.out.println("certs=" + certs);
                    byte[] hash = MessageDigest.getInstance("SHA1").digest(buf);
                    result.put(sig.getName(), verifyPKCS7(hash, contents, sig));

                    //TODO check certificate chain, revocation lists, timestamp...
                    break;
                }
                case "adbe.x509.rsa_sha1": // COSName.ADBE_PKCS7_SHA1
                {
                    // example: PDFBOX-2693.pdf
                    COSString certString = (COSString) sigDict.getDictionaryObject(COSName.getPDFName("Cert"));
                    byte[] certData = certString.getBytes();
                    Collection<? extends Certificate> certs = getCertificates(certData);
                    System.out.println("certs=" + certs);

                    //TODO verify signature
                    throw new IOException(subFilter + " verification not supported");
                    //break;
                }
                default:
                    throw new IOException("Unknown certificate type: " + subFilter);
                    //break;
                }
            } else {
                throw new IOException("Missing subfilter for cert dictionary");
            }
        }
    } catch (CMSException | OperatorCreationException ex) {
        throw new IOException(ex);
    }

    return result;
}

From source file:se.tillvaxtverket.ttsigvalws.ttwssigvalidation.pdf.PdfSignatureVerifier.java

License:Open Source License

/**
 * Verifies the signature on a PDF document
 *
 * @param pdfDoc The bytes of a PDF document
 * @param verifyPades If this is set to false, signature validation will
 * ignore any errors in any present PAdES Signed signature certificate data.
 * This should normally always be true. If this is set to true, signature
 * validation will still succeed if PAdES data is absent.
 * @return Signature verification result data.
 * @throws IOException//from   w  ww .ja v  a  2 s . com
 */
public static PdfSigVerifyResult verifyPdfSignatures(SigDocument pdfDoc, boolean verifyPades)
        throws IOException {
    PDDocument doc = PDDocument.load(pdfDoc.getDocInputStream());
    PdfSigVerifyResult result = new PdfSigVerifyResult();
    List<PDSignature> signatureDicts = doc.getSignatureDictionaries();
    for (PDSignature sig : signatureDicts) {
        byte[] signedContent = sig.getSignedContent(pdfDoc.getDocInputStream());
        byte[] sigBytes = sig.getContents(pdfDoc.getDocInputStream());

        CMSSigVerifyResult sigResult = result.addNewIndividualSignatureResult();
        try {
            verifySign(sigBytes, signedContent, sigResult, verifyPades);
        } catch (Exception ex) {
            sigResult.setStatus("Failed with exception: " + ex.getMessage());
        }
    }

    result.consolidateResults();
    return result;
}

From source file:se.tillvaxtverket.ttsigvalws.ttwssigvalidation.pdf.PdfSignatureVerifier.java

License:Open Source License

/**
 * Verifies the signature on a PDF document
 *
 * @param pdfFile The PDF file to verify
 * @param verifyPades If this is set to false, signature validation will
 * ignore any errors in any present PAdES Signed signature certificate data.
 * This should normally always be true. If this is set to true, signature
 * validation will still succeed if PAdES data is absent.
 * @return Signature verification result data.
 * @throws IOException//from  w  ww. j  a  v  a 2s  .c o m
 */
public static PdfSigVerifyResult verifyPdfSignatures(File pdfFile, boolean verifyPades) throws IOException {
    PDDocument doc = PDDocument.load(pdfFile);
    PdfSigVerifyResult result = new PdfSigVerifyResult();
    List<PDSignature> signatureDicts = doc.getSignatureDictionaries();
    for (PDSignature sig : signatureDicts) {
        byte[] signedContent = sig.getSignedContent(new FileInputStream(pdfFile));
        byte[] sigBytes = sig.getContents(new FileInputStream(pdfFile));

        CMSSigVerifyResult sigResult = result.addNewIndividualSignatureResult();
        try {
            verifySign(sigBytes, signedContent, sigResult, verifyPades);
        } catch (Exception ex) {
            sigResult.setStatus("Failed with exception: " + ex.getMessage());
        }
    }

    result.consolidateResults();
    return result;
}