Skip navigation links
digidoc4j is a library for integrating digital signatures (XAdES/ASiC based) into applications and services built with Java technology.

See: Description

Packages 
Package Description
org.digidoc4j
DigiDoc4J public api
org.digidoc4j.exceptions
Exception classes for DigiDoc4J.
org.digidoc4j.signers  

digidoc4j is a library for integrating digital signatures (XAdES/ASiC based) into applications and services built with Java technology.

The development of digidoc4j is organized by Estonian Information System Authority and currently executed by AS Sertifitseerimiskeskus. For inquiries about participating in the development please e-mail martin.paljak at ria.ee

This document provides the following information on digidoc4j:

- Supported functionality
- Architecture
- API overview
- Utility program overview

 

Supported functionality

This section gives overview of the main functional features offered by digidoc4j. For more detailed information about the functions (including functionality that is planned for later releases), see the digidoc4j project's Pivotal Tracker.

The digidoc4j utility program digidoc4j-util*.jar can be used for testing a subset of the supported functionality, the program is accessible from the digidoc4j download area.

Creating and handling signature containers

digidoc4j enables handling signature containers compliant to ETSI TS 102 918 standard called Associated Signature Containers (ASiC). By default, the digidoc4j implementation uses containers in BDOC 2.1 format, which is a subset of ASiC standard.

Note: additionally, an older DIGIDOC-XML 1.3 container format is supported via JDigiDoc base library.

The main use cases regarding signature containers are:

  1. Creating a new container
  2. Adding and removing data files
  3. Extracting data files from container
  4. Using temporary cache files for storing the data file's contents in file system
  5. Adding and removing signatures
  6. Input/output operations with containers

See also: org.digidoc4j.ContainerBuilder and Container

Creating and handling digital signatures

digidoc4j enables handling digital signatures based on ETSI TS 101 903 standard called XML Advanced Electronic Signatures (XAdES). By default, the digidoc4j implementation uses signatures in BDOC 2.1 format, which is a subset of XAdES standard.

Note: additionally, an older XAdES-based DIGIDOC-XML 1.3 signature format is supported via JDigiDoc base library.

The main use cases regarding digital signatures are:

  1. Creating the signature's XAdES-based XML contents
  2. Adding meta-data to the signature: e.g. signature creation location and signer's role
  3. Calculating the hash to be signed - e.g. for calculating the raw signature value with a plug-in in browser
  4. Calculating the raw RSA signature value
  5. Adding a raw signature value that is calculated in an external system (e.g. with plugin when signing in browser) to the signature's XML content. Note that this is currently supported only by DDoc.
  6. Adding long term validation data according to the signature profile: either time-mark or time-stamp and OCSP confirmation*

* There are two XAdES-LT level compliant signature profiles supported:

  1. LT - XAdES-LT signature with time-stamp - long term validation data is added to the signature in the form of a RFC3161 compliant time-stamp and RFC6960 compliant OCSP confirmation. The profile can be used in case of BDOC 2.1 format.
  2. LT_TM - XAdES-LT signature with time-mark - long term validation data is added to the signature in the form of a time-mark (RFC6960 compliant OCSP confirmation with a special nonce value). The profile can be used in case of BDOC 2.1 and DIGIDOC-XML 1.3 formats.

See also: org.digidoc4j.SignatureBuilder, Signature, ContainerBuilder and Container

Validating signature container and all of its contents

The signature validation process is based on ETSI TS 102 853 standard called Signature validation procedures and policies.

The main use cases regarding validation are:

  1. Validating a single digital signature. See also: org.digidoc4j.Signature.validate
  2. Validating a signature container and all of its contents. See also: org.digidoc4j.Container.validate
  3. Generating validation report in XML format.
  4. Enabling configuration of signature validation policies according to ETSI TR 102 038 standard XML format for signature policies.

See also: org.digidoc4j.ValidationResult

Using TSL lists as trust anchors

TSL (Trust Service status List) list is a signed XML document that provides information about the status of trust services. The format is based on ETSI 119 612 standard.

digidoc4j uses TSL lists for checking the trustworthiness of the certificates that are used in the signature. The European Commission's TSL list is used as the List Of Trusted List (LOTL) (accessible from: https://ec.europa.eu/information_society/policy/esignature/trusted-list/tl-mp.xml).

The main use case regarding TSL lists usage is:

  1. Using TSL lists for checking the trustworthiness of the signer's certificate, OCSP service and time-stamping service certificates during signature creation and validation processes.
Supported cryptographic tokens
  1. PKCS#12 token (software token)
  2. PKCS#11 token (hardware token)

See also: org.digidoc4j.SignatureToken, org.digidoc4j.signers.PKCS12SignatureToken and org.digidoc4j.signers.PKCS11SignatureToken

 

Architecture

Component diagram

The component diagram above depicts the high level components of digidoc4j library, their internal and external interfaces.

The components in the diagram are divided into notional packages according to their owner:

  1. RIA - Estonian Information System Authority
  2. EC - European Commission

The components are further described in the following table:

Component Description Owner
digidoc4j

Open source software library for integrating digital signatures (XAdES/ASiC based) into applications and services built with Java technology.

 

RIA
digidoc4j utility program

Small command line application that enables accessing the main functionality of digidoc4j library via a command line interface. Used for testing purposes. Can also be used as a source for sample client code for using digidoc4j API. Can be downloaded from digidoc4j download area.

 

RIA
JDigiDoc

Open source Java software library that enables handling documents in BDOC 2.1 and DIGIDOC-XML 1.3 formats and encryption/decryption in ENCDOC-XML 1.0 (CDOC) format.

See also:
- Home page of the project: http://id.ee/index.php?id=35783
- JDigiDoc Programmer's Guide: http://id.ee/public/SK-JDD-PRG-GUIDE.pdf

 

RIA
DSS

Digital Signature Service - open source Java framework created in order to assist EU Member States with the implementation of the Decision 2011/130/EU. Supports several forms AdES digital signatures and ASiC signature containers.

See also:
- Home page of the project: https://joinup.ec.europa.eu/asset/sd-dss/description
- Download area: https://joinup.ec.europa.eu/software/sd-dss/release/all


European Commission
TSL repository

Repository for the European Commission's central TSL list with links to the locations where the trusted lists are published as notified by EU Member States, accessible from https://ec.europa.eu/information_society/policy/esignature/trusted-list/tl-mp.xml.

See also:
- Standard document: ETSI 119 612
- Overview of EU TSL principles: EU Trusted Lists of Certification Service Providers

 

European Commission
OCSP service

RFC2560/RTF6960 based OCSP service. Also offered by SK for Estonian and a number of foreign certificates.

 

Any OCSP service provider
Time-stamping service

RFC3161-based time-stamping service. Also offered by SK.

 

Any time-stamping service provider

 

 

API overview

The digidoc4j source code's compliance to Java development best practices is periodically checked with automated code review, executed with Checkstyle configuration file checkstyle.xml that is included in the digidoc4j source package.

The Checkstyle source code analyzer enables to ensure that the code has been written according to "Code conventions for the Java programming language" and has been documented according to JavaDoc best practices, described in "How to write doc comments for the JavaDoc tool".


Sample of using digidoc4j API

In the following subsections, a sample BDOC 2.1 signature creation use case is implemented with digidoc4j API classes and methods.

Configuration

It is possible switch between testing and production environment by using Configuration class or digidoc4j.mode system property. Default environment is production. More detailed configuration can be modified in the digidoc4j.yaml file.

Configuration configuration = new Configuration(Configuration.Mode.TEST);

The example above creates a configuration with test environment for using test OCSP, Time Stamp etc servers. The same can be achieved by setting the system property digidoc4j.mode with value "TEST".

It is a good idea to use only a single configuration object for all the containers so the operation times would be faster. For example, TSL is cached within a configuration object and TSL loading is a time consuming operation.

The default configuration object is a singelton, meaning that all the containers will use the same configuration object (unless specified otherwise). The default singelton configuration object can be accessed by Configuration configuration = Configuration.getInstance();

Creating a container

Container container = ContainerBuilder.
   aContainer("BDOC"). // Supported types are BDOC and DDOC. Default is BDOC
   withConfiguration(configuration). // Configuration settings
   withDataFile("testFiles/legal_contract_1.txt", "text/plain"). // Adding a document from a hard drive
   withDataFile(inputStream, "legal_contract_2.txt", "text/plain"). // Adding a document from a stream
   build();

You can use ContainerBuilder.aContainer() to create a new container builder, populate the builder with data and finally call build() to create the container with the populated data.

In the example above, a container builder is used to create a BDOC container with specific configuration parameters and two data files: one from hard drive (legal_contract_1.txt) and other from input stream (legal_contract_2.txt).

ContainerBuilder.aContainer(String containerType) can be used for creating a container of a particular type. Currently supported types are BDOC and DDOC. Default is BDOC 2.1 if no type is provided.

Adding data files

A data file can be added by reading it from the file system or from an input stream (needed if the data is already in memory, e.g. read from database). The following example shows the case when the file is read from file system:

containerBuilder.withDataFile("<input_file_name_and_path>", "<mime_type>");

Reading and writing containers

A created container can be written to the file system as follows:

container.saveAsFile("<output_file_name_and_path>");

An existing container can be read as follows:

Container container = ContainerBuilder.
   aContainer().
   fromExistingFile("<input_file_name_and_path>").
   build();

Adding signatures

A signature can be added to the container by determining a class that implements communication with the signature token, i.e. a subclass of SignatureToken. Currently, a PKCS#12 software token implementation is provided by digidoc4j in the PKCS12SignatureToken class.

Using a signature token

String privateKeyPath = "testFiles/signout.p12";
char[] password = "test".toCharArray();
PKCS12SignatureToken signatureToken = new PKCS12SignatureToken(privateKeyPath, password);

In the sample above, the PKCS#12 token container's location and password is given as input parameters to the PKCS12SignatureToken class. The private key is stored in the "signout.p12" file and the password is "test".

Creating a new signature

Next we create a new signature with the signature token.

Signature signature = SignatureBuilder.
   aSignature(container).
   withSignatureDigestAlgorithm(DigestAlgorithm.SHA256).
   withSignatureToken(signatureToken).
   invokeSigning();

Finally we add the signature to the container. Signature must be added to the container otherwise the signature remains detached from the container.

container.addSignature(signature);

Signing externally

It is possible to sign the container externally. A typical use case would be signing in the Web using a browser plugin:

  1. Create a container with data files
  2. Calculate a digest of the container to be signed
  3. Sign the digest externally (e.g. via browser plugin)
  4. Finalize the signature with the signature value, OCSP response etc
  5. Add the finalized signature to the container

Getting data to sign

First we need to get the signer's certificate that is used in signing (via browser plugin for example).

X509Certificate signingCert = getSignerCertSomewhere();

Then we need to calculate a digest to be signed externally.

DataToSign dataToSign = SignatureBuilder.
   aSignature(container).
   withSigningCertificate(signingCert).
   withSignatureDigestAlgorithm(DigestAlgorithm.SHA256).
   buildDataToSign();

External signing

Now we have a digest that can be used for external signing. DataToSign class contains DataToSign.getDigestToSign() method for getting digest to be signed. DataToSign.getDigestAlgorithm() method can be used for getting the digest algorithm to be used in the signing process.

byte[] digestToSign = dataToSign.getDigestToSign(); //Get the digest that should be signed
byte[] signatureValue = signDigestSomewhereRemotely(digestToSign, DigestAlgorithm.SHA256); //Sign the digest

Finalizing signature

Next we have to finalize the signature with the signature value (signatureValue) we got from an external signing process.

Signature signature = dataToSign.finalize(signatureValue); //Finalize the signature with OCSP response etc

Finally we add the signature to the container. Signature must be added to the container otherwise the signature remains detached from the container.

container.addSignature(signature);

Using Time Mark signature profile

By default, the Time Stamp signature profile (referred to as "LT") is used in case of BDOC 2.1 documents. It is possible to use use a different signature profile by using signature builder's SignatureBuilder.withSignatureProfile(org.digidoc4j.SignatureProfile) method. For signing a container using the Time Mark profile you need to set the signature profile as in the following example:

SignatureBuilder signatureBuilder = SignatureBuilder.
   aSignature(container).
   withSignatureProfile(SignatureProfile.LT_TM); // Signature profile is Time Mark

Signer role and production place

We can add signer roles and production place to signature by using SignatureBuilder.

SignatureBuilder signatureBuilder = SignatureBuilder.
   aSignature(container).
   withCity("San Pedro").
   withStateOrProvince("Puerto Vallarta").
   withPostalCode("13456").
   withCountry("Val Verde").
   withRoles("Manager", "Suspicious Fisherman");

The example above the signer is from the city of San Pedro, in the state of Puerto Vallarta, with postal code 13456 and from country called Val Verde. The signer's roles are Manager and Suspicious Fisherman.

Validation

Validation process of a container and all of its contents can be initiated as follows:

ValidationResult result = container.validate();

Possible validation errors can be handled as follows:

if (!result.isValid() ) {
   for (DigiDoc4JException error : result.getErrors()) {
     System.out.println(error.getMessage());
   }
}

Exception handling

digidoc4j uses a generic exception class org.digidoc4j.exceptions.DigiDoc4JException that is a subclass of java.lang.RuntimeException.

DigiDoc4JException also wraps any possible exceptions that are thrown by the base libraries of digidoc4j.

The DigiDoc4JException class itself is subclassed to enable better handling of a number of the most critical exceptions. See also package org.digidoc4j.exceptions.

 

 

Utility program overview

The digidoc4j utility program is a command line tool that allows easy usage of several API's.

Setting up the utility

The utility is distributed as a zip file with the name digidoc4j-util-*.zip (where * is the actual version number). Unzip the file to a directory of your choice. From that directory you can now run it:

java -jar digidoc4j-util.jar

Sample of using the digidoc4j utility

In the following subsection some examples are provided for using the utility.

Creating a container

A valid BDOC container contains at least one document and is signed. To create such a container:

java -jar digidoc4j-util.jar -in "<output_file_name_and_path>" -add "<input_file_name_and_path>" "<mime_type>" -pkcs12 "<pkcs12_token_file>" "<pkcs12_token_password>"

Using the time-mark signature profile

To sign a container using the time-mark protocol you need to specify the signature profile using the -profile option LT_TM:

java -jar digidoc4j-util.jar -in "<output_file_name_and_path>" -add "<input_file_name_and_path>" "<mime_type>" -profile LT_TM -pkcs12 "<pkcs12_token_file>" "<pkcs12_token_password>"

Creating multiple signed containers

To create signatures of all the files within a directory, you need to specify the input directory containing data files, and output directory where the signed containers will be saved.

java -jar digidoc4j-util.jar -inputDir "<input_directory_path>" -mimeType "<mime_type (optional)>" -outputDir "<output_directory_path>" -pkcs11 "<pkcs11_module_path>" "<pkcs11_token_pin_password>" "<pkcs11_slot_index>"

Validation

The utility performs validation when specifying the -v option. The output shows all signatures and their statuses as well as all errors:

java -jar digidoc4j-util.jar -in "<input_file_name_and_path>" -v

In order to see validation warnings in addition to the errors you must specify the -w option:

java -jar digidoc4j-util.jar -in "<input_file_name_and_path>" -v -w

Verbose

For all tasks more details can be obtained using the -verbose option as in the next example:

java -jar digidoc4j-util.jar -in "<input_file_name_and_path>" -v -verbose

Skip navigation links