Skip to content

Latest commit

 

History

History
375 lines (256 loc) · 20.5 KB

advanced-dss-java-concepts.adoc

File metadata and controls

375 lines (256 loc) · 20.5 KB

1. Advanced DSS java concepts

1.1. ServiceLoader

DSS incorporates modules that are loaded in the run time based on the chosen configuration and the input data via a ServiceLoader. This provides a flexibility for an end-user to work only with selected modules and a possibility to expand DSS with custom implementations.

In order to provide a chosen implementation(s) to ServiceLoader, a file listing all the desired implementations should be created in the resource directory META-INF/services with a name matching the implemented interface. When merging sources (e.g. creating a Fat JAR module), the files can be lost/overwritten, and should be configured manually (all the required implementations shall be listed).

It is also possible to customize the order of the used implementation, but creating a corresponding file in META-INF/services directory within your project.

Note
If a DSS module(s) implementing a required interface(s) is added to your project’s dependency list, the implementation shall be loaded automatically.

The following modules are provided with independent implementations:

  • DSS Utils;

  • DSS CRL Parser;

  • DSS PAdES.

Warning
At least one implementation shall be chosen.

1.1.1. DSS Utils

The module dss-utils offers an interface with utility methods to operate on String, Collection, I/O, etc. DSS framework provides two different implementations with the same behaviour :

  • dss-utils-apache-commons: this module uses Apache Commons libraries (commons-lang3, commons-collection4, commons-io and commons-codec);

  • dss-utils-google-guava: this module uses Google Guava (recommended on Android).

If your integration includes dss-utils, you will need to select an implementation. For example, to choose the dss-utils-apache-commons implementation within a Maven project you need to define the following:

pom.xml
<dependency>
    <groupId>eu.europa.ec.joinup.sd-dss</groupId>
    <artifactId>dss-utils-apache-commons</artifactId>
</dependency>

1.1.2. DSS CRL Parser

DSS contains two ways to parse/validate a CRL and to retrieve revocation data. An alternative to the X509CRL java object was developed to face memory issues in case of large CRLs. The X509CRL object fully loads the CRL in memory and can cause OutOfMemoryError.

  • dss-crl-parser-x509crl: this module uses the X509CRL java object.

  • dss-crl-parser-streams: this module offers an alternative with a CRL streaming.

If your integration requires dss-crl-parser, you will need to choose your implementation. For example, to choose the dss-crl-parser-streams implementation within a Maven project you need to define the following:

pom.xml
<dependency>
    <groupId>eu.europa.ec.joinup.sd-dss</groupId>
    <artifactId>dss-crl-parser-stream</artifactId>
</dependency>

1.1.3. DSS PAdES

DSS allows generation, augmentation and validation of PAdES signatures with two different frameworks: PDFBox and OpenPDF (fork of iText). The dss-pades module only contains the common code and requires an underlying implementation :

  • dss-pades-pdfbox: PAdES implementation based on Apache PDFBox. Supports drawing of custom text, images, as well as text+image, in a signature field.

  • dss-pades-openpdf: PAdES implementation based on OpenPDF (fork of iText). Supports drawing of custom text OR images in a signature field.

DSS permits to override the visible signature generation with these interfaces:

  • eu.europa.esig.dss.pdf.IPdfObjFactory;

  • eu.europa.esig.dss.pdf.visible.SignatureDrawerFactory (selects the SignatureDrawer depending on the SignatureImageParameters content);

  • eu.europa.esig.dss.pdf.visible.SignatureDrawer.

A new instance of the IPdfObjFactory can be created with its own SignatureDrawerFactory and injected in the padesService.setPdfObjFactory(IPdfObjFactory). By default, DSS uses an instance of ServiceLoaderPdfObjFactory. This instance checks for any registered implementation in the classpath with the ServiceLoader (potentially a service from dss-pades-pdfbox, dss-pades-openpdf or your own(s)).

1.1.3.1. DSS PDFBox

DSS allows switching between two implementations of the PDFBox framework: default (original) and native.

  • Native Drawer: A native implementation of PDFBox Drawer, allowing a user to add a vector text, image or combination of text and image to a visible signature field. The native implementation embeds the provided custom text to the inner PDF structure, that makes the text selectable and searchable, but also clearer and smoother in comparison with the raster implementation.

  • Default Drawer: The original drawer implemented on the PDFBox framework, supports displaying of custom text, images, but also text and image combination in a signature field. The implementation does not include the provided custom text to the inner PDF structure, instead of it, the drawer creates an image representation of the provided text, which is added to the signature field (i.e. the text is not selectable and not searchable).

By default, DSS uses the "Native Drawer" as the PDFBox implementation. In order to switch the implementation, that allowed at runtime, you have to set a new instance for PdfObjFactory as following:

Runtime PDF Object Factory changing
link:../../../test/java/eu/europa/esig/dss/cookbook/example/sign/SignPdfPadesBVisibleTest.java[role=include]

Or create a new file META-INF/services/eu.europa.esig.dss.pdf.IPdfObjFactory within project’s resources, defining the desired implementation (see ServiceLoader for more information).

1.1.3.2. DSS OpenPDF

This implementation is based on the OpenPDF framework. DSS provides two drawers using the implementation:

  • TextOnlySignatureDrawer - to draw a vector text information within a signature field. The text information is selectable and searchable.

  • ImageOnlySignatureDrawer - to draw an image within a signature field.

Warning
DSS provides a limited support of OpenPDF framework, therefore not all features are supported (e.g. text+image drawing).

1.1.4. MimeType

With a help of ServiceLoader, DSS provides a possibility of creation custom mimetype values in addition to the default enumerations defined within MimeTypeEnum class.

In case a support of new mimetype(s) or file extension(s) is required, a new class defining the new values shall be created implementing the MimeType interface and an implementation of MimeTypeLoader handling the logic of new values processing.

See an example of a class mimetypes implementation below:

Custom MimeType implementation example
link:../../../test/java/eu/europa/esig/dss/cookbook/example/CustomMimeTypeLoader.java[role=include]

In order to make the class accessible by ServiceLoader and visible for DSS, a new file with name eu.europa.esig.dss.enumerations.MimeTypeLoader shall be created within META-INF/services directory of your project containing the name of the MimeTypeLoader implementation:

Content of META-INF/services/eu.europa.esig.dss.enumerations.MimeTypeLoader file for CustomMimeTypeLoader class
eu.europa.esig.dss.cookbook.example.CustomMimeTypeLoader

This will load firstly the created class (CustomMimeTypeLoader.java) and after other available implementations (i.e. MimeTypeEnumLoader with default mimetypes).

1.2. Multithreading

DSS can be used in multi-threaded environments but some points need to be considered like resources sharing and caching. All operations are stateless and this fact requires to be maintained. Some resources can be shared, others are proper to an operation.

For each provided operation, DSS requires a CertificateVerifier object. This object is responsible to provide certificates and accesses to external resources (AIA, CRL, OCSP, etc.). At the beginning of all operation, CertificateSources and RevocationSources are created for each signature / timestamp / revocation data. Extracted information are combined with the configured sources in the CertificateVerifier. For these reasons, integrators need to be careful about the CertificateVerifier configuration.

1.2.1. Resource sharing

The trusted certificates can be shared between multiple threads because these certificates are static. This means they don’t require more analysis. Their status won’t evolve. For these certificates, DSS doesn’t need to collect issuer certificate and/or their revocation data.

In opposition, the adjunct certificates cannot be shared. These certificates concern a specific signature/validation operation. This parameter is used to provide missing certificate(s). When DSS is unable to build the complete certificate path with the provided certificates (as signature parameters or embedded within a signature), it is possible to inject certificates that are not present. These certificates are not necessarily trusted and may require future "modifications" like revocation data collection, etc.

1.2.2. Caching

In case of multi-threading usage, we strongly recommend caching of external resources. All external resources can be cached (AIA, CRL, OCSP) to improve performances and to avoid requesting too much time the same resources. FileCacheDataLoader and JdbcCacheCRLSource can help you in this way.

See section [CachingUseCases] of the Annex for complete examples of caching revocation data, certificates and trusted lists.

1.3. JAXB modules

1.3.1. General

DSS provides the following JAXB modules with a harmonized structure :

  • dss-policy-jaxb - defines validation policy JAXB model;

  • dss-diagnostic-jaxb - defines Diagnostic Data JAXB model;

  • dss-detailed-report-jaxb - defines Detailed Report JAXB model;

  • dss-simple-report-jaxb - defines Simple Report JAXB model;

  • dss-simple-certificate-report-jaxb - defines Certificate Simple Report JAXB model.

All modules share the same logic and have the following structure (where *** is a model name):

dss-***-jaxb
/src/main/java
eu.europa.esig.dss.***
  • ***.java - wrapper(s) which eases the JAXB manipulation

  • …​

  • ***Facade.java - class which allows marshalling/unmarshalling of jaxb objects, generation of HTML/PDF content, etc.

  • ***XmlDefiner.java - class which contains the model definition (XSD, XSLT references, ObjectFactory)

  • /jaxb - generated on compile time

    • Xml***.java - JAXB model

    • …​

/src/main/resources
/xsd
  • ***.xsd - XML Schema (XSD) for the Detailed Report model

  • binding.xml - XJC instructions to generate the JAXB model from the XSD

/xslt
  • /html

    • ***.xslt - XML Stylesheet for the HTML generation

  • /pdf

    • ***.xslt - XML Stylesheet for the PDF generation

In the main classes, a Facade is present to quickly operate with the JAXB objects (e.g. marshall, unmarshall, generate the HTML/PDF, validate the XML structure, etc.).

DetailedReportFacade usage
link:../../../test/java/eu/europa/esig/dss/cookbook/example/snippets/SignedDocumentValidatorTest.java[role=include]

An XmlDefiner is also available with the access to the embedded XML Schemas (XSD), the XML Stylesheets (XSLT) to be able to generate the HTML or the PDF content (for DSS specific JAXB) and the JAXB Object Factory.

DetailedReportXmlDefiner usage
link:../../../test/java/eu/europa/esig/dss/cookbook/example/snippets/SignedDocumentValidatorTest.java[role=include]

1.3.2. Creating a trusted list

It is possible to programmatically create or/and edit an XML Trusted List using the JAXB module.

Below is an example of how to use JAXB modules to create a trusted list (not complete solution):

Creation of a trusted list
link:../../../test/java/eu/europa/esig/dss/cookbook/example/snippets/CreateTLSnippet.java[role=include]

And an example how to modify an existing Trusted List (e.g. change its version):

Edit a trusted list
link:../../../test/java/eu/europa/esig/dss/cookbook/example/snippets/CreateTLSnippet.java[role=include]

1.3.3. Validating XSD conformity

You can also use JAXB modules not only for the content creation or changing, but also in order to verify the conformity of an XML document against its XSD schema.

For example, in order to validate a XAdES signature conformance against 1.3.2 XSD schema, you can use the corresponding class XAdES319132Utils:

Validating XSD conformity
link:../../../test/java/eu/europa/esig/dss/cookbook/example/sign/SignXmlXadesBPropertiesTest.java[role=include]

1.3.4. Report stylesheets

The report modules (namely: dss-simple-report-jaxb, dss-simple-certificate-report-jaxb and dss-detailed-report-jaxb) contain XSLT style sheets each for final reports generation:

  • Bootstrap 4 XSLT for HTML report;

  • PDF XSLT for PDF report.

Note
Since DSS 5.9 only Bootstrap 4 XSLT is provided within the framework for HTML report generation.

In order to generate a report with a selected style sheet you need to call a relevant method in a Facade class (see classes definition above):

HTML report generation
link:../../../test/java/eu/europa/esig/dss/cookbook/example/snippets/StylesheetSnippet.java[role=include]

Otherwise, in case you need to customize the transformer, you can create a report by using an XmlDefiner:

Custom report generation
link:../../../test/java/eu/europa/esig/dss/cookbook/example/snippets/StylesheetSnippet.java[role=include]

1.3.5. Diagnostic data stylesheets

The dss-diagnostic-jaxb module contains an XSLT stylesheet that creates an SVG image from an XML document in order to visually represent the signature at validation time.

SVG generation
link:../../../test/java/eu/europa/esig/dss/cookbook/example/snippets/SVGGenerationSnippet.java[role=include]

1.4. XML securities

The framework allows custom configuration of XML-related modules for enabling/disabling of XML securities (e.g. in order to use Xalan or Xerces).

Warning
We strongly do not recommend disabling of security features and usage of deprecated dependencies. Be aware: the feature is designed only for experienced users, and all changes made in the module are at your own risk.

The configuration is available for the following classes:

  • javax.xml.parsers.DocumentBuilderFactory with a DocumentBuilderFactoryBuilder - builds a DOM document object from the obtained XML file and creates a new org.w3c.dom.Document;

  • javax.xml.transform.TransformerFactory with a TransformerFactoryBuilder - loads XML templates and builds DOM objects;

  • javax.xml.validation.SchemaFactory with a SchemaFactoryBuilder - loads XML Schema;

  • javax.xml.validation.Validator with a ValidatorConfigurator - configures a validator to validate an XML document against an XML Schema.

All the classes can be configured with the following methods (example for TransformerFactory):

XMLSecurities configuration
link:../../../test/java/eu/europa/esig/dss/cookbook/example/snippets/XMLSecuritiesConfigTest.java[role=include]

The javax.xml.parsers.DocumentBuilderFactory, that allows XML files parsing and creation of DOM org.w3c.dom.Document object, can be configured with the following methods:

Note
Since DSS 5.9 the configuration of javax.xml.parsers.DocumentBuilderFactory has been moved from DomUtils to a new singleton class DocumentBuilderFactoryBuilder.
DocumentBuilderFactory configuration
link:../../../test/java/eu/europa/esig/dss/cookbook/example/snippets/XMLSecuritiesConfigTest.java[role=include]

The class XmlDefinerUtils is a singleton, therefore all changes performed on the instance will have an impact to all calls of the related methods.

See section [Alerts] in chapter Annex for more information on alerts.

1.5. PDF Memory Usage Setting

Since DSS 6.2 it is possible to configure the memory usage on PDF reading. The feature is useful on document signing or validation, when a smart memory usage is crucial, for instance when processing big PDF files.

The configuration can be done using a PdfMemoryUsageSetting class, as shown below:

PdfMemoryUsageSetting configuration
link:../../../test/java/eu/europa/esig/dss/cookbook/example/snippets/PAdESWithIPdfObjFactoryConfiguration.java[role=include]
Note
PdfMemoryUsageSetting is only supported in methods within PAdESService and PDFDocumentValidator.

1.6. DSS Resources Handler

Since version 5.11, DSS provides a possibility to configure a way temporary objects are created within the core code.

DSSResourcesHandler is responsible for implementation of created temporary objects during the execution, e.g. in memory or in a temporary file.

Note
DSSResourcesHandler is only supported in methods within PAdESService (i.e. signature creation, extension, screenshot generation, etc.) and ZipUtils (ASiC generation).

The DSSResourcesHandler interface provides the following methods:

  • createOutputStream() - creates a new OutputStream, to be used as a data buffer; and

  • writeToDSSDocument() - writes the created earlier OutputStream to a corresponding DSSDocument implementation.

The DSSResourcesHandler implements Closable interface, therefore it is able to remove temporary objects when closing or exiting the try block.

In order to create a DSSResourcesHandler an implementation of DSSResourcesHandlerBuilder should be used. DSS provides the following implementations of DSSResourcesHandlerBuilder interface:

  • InMemoryResourcesHandlerBuilder - creates a ByteArrayOutputStream to be used as a data buffer (e.g. storing a signed PDF) and produces InMemoryDocument containing the byte array of a created document.

  • TempFileResourcesHandlerBuilder - creates a temporary File in the local filesystem, storing in it the temporary data and produces a FileDocument as an output, when applicable. The implementation removes the temporary files when the file is not required outside the method or when finishing JVM.

Note
InMemoryResourcesHandlerBuilder is used by default in DSS, working with data in memory.

To define the resources handler for PAdES processing, the corresponding DSSResourcesHandlerBuilder has to be provided to an instance of IPdfObjFactory used within a PAdESService. An example below demonstrates a signature creation using in temporary file processing:

PAdES signing using temporary files
link:../../../test/java/eu/europa/esig/dss/cookbook/example/sign/SignPdfWithTempFileTest.java[role=include]
Warning
Based on the implementation, certain objects are still have to be processed in memory (e.g. with PdfBox or iText document readers).

Since DSS 6.1 a DSSResourcesHandler may also be used for ASiC creation, allowing to configure direct ASiC creation within a FileSystem as below:

ASiC creation using temporary files
link:../../../test/java/eu/europa/esig/dss/cookbook/example/sign/SignASiCEWithXAdESWithTempFileTest.java[role=include]

1.7. ZIP Utils

For parsing and creation of ZIP archives a special class ZipUtils is provided. This is a singleton class, and its behavior can be customized using an implementation of ZipContainerHandler interface. An implementation of ZipContainerHandler can be provided in runtime and the defined class will be used on all calls of ZipUtils across DSS’s code

By default, an instance of SecureContainerHandler is used, allowing to parse ZIP container securely, by reporting a presence of a ZIP-bomb (see 42.zip) and/or malicious documents within a given archive.

Below you can find the configuration available in SecureContainerHandler:

SecureContainerHandler for ZipUtils configuration
link:../../../test/java/eu/europa/esig/dss/cookbook/example/sign/SignOneFileWithASiCSBTest.java[role=include]