SiGa - Signature Gateway

June 9, 2026 ยท View on GitHub

Co-funded by the European Union

SiGa - Signature Gateway

Signature Gateway is a web service for creating and signing ASIC-E containers and validating both ASIC-E and BDOC containers with XAdES signatures.

Note

Looking for the Digital Signature Gateway service?
Documentation is available here.

Prerequisites:

For building and running SiGa you need Java 17.

External services used by SiGa

  • Signature Validation Service for validating signatures.
  • MID REST service for signing with Mobile-ID (if enabled in configuration).
  • Smart-ID service for signing with Smart-ID (if enabled in configuration).
  • TimeStamping service (based on configuration)
  • (AIA) OCSP service (based on configuration)
  • LOTL and national TSL services

SiGa component model

SiGa component model

How to build

SiGa project compiles into a JAR (Java archive) or WAR (Web application archive) file. The former one includes embedded Tomcat, while the latter one requires a separate servlet container to run.

Building JAR with embedded Tomcat

./mvnw clean install

Building WAR for a separate servlet container

./mvnw clean install -Pwar

How to deploy

SiGa Deployment diagram

SiGa deployment diagram

In addition to a JAR or WAR file containing compiled SiGa, Apache Ignite version 2.17.0 is required for session management.

Running Apache Ignite

Ignite servers must be up and running prior to SiGa startup. Ignite servers must be configured the same way as the Ignite client embedded in SiGa. An example Ignite configuration file can be seen here. Additionally, the following options must be added to the JVM_OPTS parameter in Ignite's setenv.sh file:

--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED
--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED
--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
--add-opens=java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED
--add-opens=java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED
--add-opens=java.base/java.io=ALL-UNNAMED
--add-opens=java.base/java.nio=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED
--add-opens=java.base/java.util.concurrent=ALL-UNNAMED
--add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED
--add-opens=java.base/java.util.concurrent.locks=ALL-UNNAMED
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.time=ALL-UNNAMED

For general instructions, refer to the official documentation to configure and run Ignite.

Running SiGa

Running SiGa with embedded Tomcat

  • Make application.properties available anywhere in the host system.
  • Set $JAVA_OPTS environment variable with the required options (see more on Ignite Getting Started guide). Replace the path of application.properties in the following command to point to your own file.
    export JAVA_OPTS="-Dspring.config.location=file:/path/to/application.properties\
      --add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED\
      --add-opens=java.base/jdk.internal.misc=ALL-UNNAMED\
      --add-opens=java.base/sun.nio.ch=ALL-UNNAMED\
      --add-opens=java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED\
      --add-opens=java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED\
      --add-opens=java.base/java.io=ALL-UNNAMED\
      --add-opens=java.base/java.nio=ALL-UNNAMED\
      --add-opens=java.base/java.util=ALL-UNNAMED\
      --add-opens=java.base/java.util.concurrent=ALL-UNNAMED\
      --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED\
      --add-opens=java.base/java.util.concurrent.locks=ALL-UNNAMED\
      --add-opens=java.base/java.lang=ALL-UNNAMED\
      --add-opens=java.base/java.time=ALL-UNNAMED\
      --add-opens=java.base/sun.security.x509=ALL-UNNAMED\
      --add-opens=java.base/java.security.cert=ALL-UNNAMED\
      -Djdk.tls.client.protocols=TLSv1.2"
    
  • Run JAR file with SiGa webapp and embedded Tomcat (X.X.X denotes the version you are using):
    java $JAVA_OPTS -jar siga-webapp/target/siga-webapp-X.X.X.jar
    

Running SiGa in separate Tomcat installation

At first, Tomcat web servlet container needs to be downloaded. For example, version 8.5.46 could be downloaded with the following command using wget:

wget https://www-eu.apache.org/dist/tomcat/tomcat-8/v8.5.46/bin/apache-tomcat-8.5.46.tar.gz

Unpack it somewhere:

tar -xzf apache-tomcat-8.5.46.tar.gz

Copy the built WAR file containing SiGa into Tomcat's webapps directory and start the servlet container:

cp SiGa/siga-webapp/target/siga-webapp-2.0.1.war apache-tomcat-8.5.46/webapps
./apache-tomcat-8.5.46/bin/catalina.sh run
  • Make application.properties available anywhere in the host system.
  • Depending on your system, it might be required to set the JAVA_HOME environment variable in file /etc/default/tomcat8. For example:
    • JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
  • Create or modify setenv.sh placed inside Tomcat bin directory:
    • export JAVA_OPTS="$JAVA_OPTS -Dspring.config.location=file:/path/to/application.properties"
    • export JAVA_OPTS="$JAVA_OPTS -Dspring.profiles.active=list-of-profiles-to-activate" (see available profiles)

Additionally, the following options must be added to the JAVA_OPTS parameter in the same setenv.sh file (see more on Ignite Getting Started guide):

--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED
--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED
--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
--add-opens=java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED
--add-opens=java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED
--add-opens=java.base/java.io=ALL-UNNAMED
--add-opens=java.base/java.nio=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED
--add-opens=java.base/java.util.concurrent=ALL-UNNAMED
--add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED
--add-opens=java.base/java.util.concurrent.locks=ALL-UNNAMED
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.time=ALL-UNNAMED
--add-opens=java.base/sun.security.x509=ALL-UNNAMED
--add-opens=java.base/java.security.cert=ALL-UNNAMED
-Djdk.tls.client.protocols=TLSv1.2

Available Spring profiles

Profile nameDescription
digidoc4jProdUse DD4J production mode
digidoc4jTestUse DD4J test mode (prefer AIA-OCSP)
digidoc4jPerfUse DD4J test mode (without AIA-OCSP)
mobileIdEnable endpoints for signing with Mobile-ID
smartIdEnable endpoints for signing with Smart-ID
datafileContainerEnable datafile container endpoints*

NB: exactly one of digidoc4jProd, digidoc4jTest and digidoc4jPerf must be active!

* Datafile containers support has not been thoroughly performance tested. Use at your own risk.

SiGa configuration

application.properties

Example application.properties file with DEMO parameters can be seen here. application.properties values must be changed for production mode, as default maven profile does not include it in the build. Common Spring Boot properties are described here.

SiGa Ignite configuration

ParameterMandatoryDescriptionExample
siga.ignite.configuration-locationYLocation of the ignite configuration file./path/to/ignite-configuration.xml
siga.ignite.application-cache-versionYVersion of Ignite cache.v1

Example ignite-configuration.xml file can be seen here.

SiGa DD4J configuration

ParameterMandatoryDescriptionExample
siga.dd4j.configuration-locationYLocation of the DD4J configuration file./path/to/digidoc4j.yaml
siga.dd4j.tsl-refresh-job-cronYCron expression for the scheduled job that refreshes DD4J TSL cache.0 0 3 * * *

More about configuring DD4J here.

SiGa SiVa configuration

ParameterMandatoryDescriptionExample
siga.siva.urlYSignature validation service URL.https://siva-arendus.eesti.ee/V3
siga.siva.trust-storeYSiVa service truststore path.file:/path/to/trust-store.p12 or classpath:path/to/trust-store.p12
siga.siva.trust-store-passwordYSiVa service truststore password.changeit
siga.siva.connection-timeoutNConnection timeout for regular connections in ISO-8601 duration format PnDTnHnMn.nS. The input is truncated to millisecond precision. If not provided, defaults to system default.PT10S
siga.siva.write-timeoutNWrite timeout for regular connections in ISO-8601 duration format PnDTnHnMn.nS. The input is truncated to millisecond precision. If not provided, defaults to system default.PT10S
siga.siva.read-timeoutNRead timeout for regular connections in ISO-8601 duration format PnDTnHnMn.nS. The input is truncated to millisecond precision. If not provided, defaults to system default.PT10S
siga.siva.max-in-memory-sizeNMaximum size of data to be sent to SiVa. If not provided, defaults to 256KB. Note that the default size may not be enough for containers with dozens of signatures.5MB

SiGa MID REST configuration

Applicable if mobileId profile is active.

ParameterMandatoryDescriptionExample
siga.midrest.urlYMID REST service URL.https://tsp.demo.sk.ee/mid-api
siga.midrest.allowed-countriesNMID REST allowed countries.EE, LT
siga.midrest.truststore-pathYMID REST PKCS12 truststore path.mid_truststore.p12
siga.midrest.truststore-passwordYMID REST PKCS12 truststore password.changeIt
siga.midrest.long-polling-timeoutNMID REST session status request long poll value in milliseconds. Defaults to 30000. Supports ISO 8601 Duration format.30000
siga.midrest.connect-timeoutNMID REST client connection timeout in milliseconds. Defaults to 5000. Supports ISO 8601 Duration format.5000
siga.midrest.status-polling-delayNDelay before polling status in milliseconds. Defaults to 6000. Supports ISO 8601 Duration format.6000

NB: MID REST relying party name and UUID are registered per service.

SiGa Smart-ID configuration

Applicable if smartId profile is active.

ParameterMandatoryDescriptionExample
siga.sid.urlYSmart-ID service URL.https://sid.demo.sk.ee/smart-id-rp/v2/
siga.sid.session-status-response-socket-open-timeNSmart-ID session status request long poll value in milliseconds. Defaults to 30000. Supports ISO 8601 Duration format.30000
siga.sid.connect-timeoutNSmart-ID client connection timeout in milliseconds. Defaults to 5000. Supports ISO 8601 Duration format.5000
siga.sid.status-polling-delayNDelay before polling status in milliseconds. Defaults to 6000. Supports ISO 8601 Duration format.6000
siga.sid.allowed-countriesNSmart-ID allowed countries. Defaults to EE, LT, LV.EE, LV, LT
siga.sid.interaction-typeNSmart-ID interaction to be requested to be performed by the Smart-ID app. Supported options: DISPLAY_TEXT_AND_PIN, VERIFICATION_CODE_CHOICE. Defaults to DISPLAY_TEXT_AND_PIN.VERIFICATION_CODE_CHOICE
siga.sid.truststore-pathYSmart-ID PKCS12 truststore pathsid_truststore.p12
siga.sid.truststore-passwordYSmart-ID PKCS12 truststore passwordchangeIt

NB: Smart-ID relying party name and UUID are registered per service.

SiGa MID/SID signature/certificate status request re-processing configuration

MID/SID signature/certificate status requests and signature finalization steps are performed in background process. Following configuration parameters define how these steps are re-processed if exception occurs.

ParameterMandatoryDescriptionExample
siga.status-reprocessing.fixed-rateNFailed signature/certificate status re-processing interval in milliseconds. Default value in milliseconds: 50005000
siga.status-reprocessing.initial-delayNInitial delay on startup before re-processing signature/certificate status requests. Default value in milliseconds: 50005000
siga.status-reprocessing.max-processing-attemptsNMaximum failed processing attempts. Default value: 1010
siga.status-reprocessing.processing-timeoutNMaximum processing time, before request is considered failed and can be re-processed by other SiGa nodes. Used when request processing SiGa node fails or leaves Ignite topology. Default value in milliseconds: 30000 Supports ISO 8601 Duration format.30000
siga.status-reprocessing.exception-timoutNMaximum time from last exception, before request is considered failed and can be re-processed by other SiGa nodes. Used when recoverable exception (e.g. networking) occurs and request can be re-processed. Default value in milliseconds: 5000 Supports ISO 8601 Duration format.5000

SiGa security configuration

ParameterMandatoryDescriptionExample
siga.security.hmac.expirationYMaximum amount of time from signing timestamp after which the request is considered expired, in seconds. Validation takes into account clock skew. Must be greater than or equal to -1.5
siga.security.hmac.clock-skewYMaximum clock skew between SiGa server and service provider machines, in seconds. Must be greater than or equal to 0.2
siga.security.jasypt.encryption-algoYAlgorithm that is used to encrypt service signing key values in service database.PBEWITHSHA-256AND256BITAES-CBC-BC
siga.security.jasypt.encryption-keyYSecret key that is used to encrypt/decrypt service signing key values in service database.encryptorKey
siga.security.prohibited-policies-for-remote-signingNProhibited certificate policy OIDs for remote signing endpoint. Default values: 1.3.6.1.4.1.10015.1.3, 1.3.6.1.4.1.10015.18.1, 1.3.6.1.4.1.10015.17.2, 1.3.6.1.4.1.10015.17.11.3.6.1.4.1.10015.1.3, 1.3.6.1.4.1.10015.17.2

SiGa database configuration

Example changelogs and changesets are provided under siga-auth/src/main/resources/db. To apply a changelog to the database on the application startup, spring.liquibase.change-log property must be set, e.g.:

spring.liquibase.change-log=classpath:db/changelog/db.changelog-master.yaml

Use classpath:db/changelog/db.changelog-master-dev.yaml only for test/dev purposes. This changeset inserts default testing values into services database.

Out-of-the-box, SiGa supports H2 and PostgreSQL databases. H2 is good for development and testing, but in production using PostgreSQL is recommended. An example for configuring SiGa to use PostgreSQL:

spring.sql.init.continue-on-error=false
spring.sql.init.platform=postgresql
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/database
spring.datasource.username=user
spring.datasource.password=password

SiGa monitoring configuration

SiGa exposes monitoring endpoints via Spring Boot Actuator. An example configuration for monitoring-related properties used in the Docker-based demo setup can be found in docker/siga-webapp/application.properties. If SiGa is configured without the example configuration, Spring Boot default values will apply.

Heartbeat endpoint

The heartbeat endpoint returns a simple aggregate health status. Since it delegates to the Spring Boot health endpoint internally, health must also be included for the heartbeat to function. The following configuration should be added to application.properties:

management.endpoints.web.exposure.include=health,heartbeat
management.endpoint.heartbeat.enabled=true

By default, the heartbeat endpoint can be accessed at {host}/actuator/heartbeat. Subject to configured servlet context path and actuator configuration.

Version endpoint

To add the version information endpoint, the following configuration should be added to application.properties:

management.endpoints.web.exposure.include=version
management.endpoint.version.enabled=true

By default, the version information endpoint can be accessed at {host}/actuator/version. Subject to configured servlet context path and actuator configuration.

Prometheus endpoint

SiGa supports metrics collection via Prometheus. To enable the Prometheus metrics endpoint, the following configuration should be added to application.properties:

management.endpoints.web.exposure.include=prometheus

By default, the Prometheus metrics endpoint can be accessed at {host}/actuator/prometheus. Subject to configured servlet context path and actuator configuration.

SiGa database

Data model

SIGA_CLIENT

A table holding all the registered clients that are allowed to use SiGa.

Column nameTypeDescription
idSERIAL (autoincrement primary key)Entry ID
nameVARCHAR(100)Client name
contact_nameVARCHAR(100)Client contact person name
contact_emailVARCHAR(256)Client contact e-mail
contact_phoneVARCHAR(30)Client contact phone
uuidVARCHAR(36)Client UUID
created_atTIMESTAMPClient creation date
updated_atTIMESTAMPClient update date

SIGA_SERVICE

A table holding all the registered services that are allowed to use SiGa.

Column nameTypeDescription
idSERIAL (autoincrement primary key)Entry ID
uuidVARCHAR(36)Service UUID
signing_secretVARCHAR(128)A previously agreed secret that is used to sign all requests sent to SiGa by this service
client_idINTEGERClient ID (foreign key to SIGA_CLIENT)
nameVARCHAR(100)Service name
sk_relying_party_nameVARCHAR(100)MID REST relying party name
sk_relying_party_uuidVARCHAR(100)MID REST relying party UUID
smart_id_relying_party_nameVARCHAR(100)Smart-ID relying party name
smart_id_relying_party_uuidVARCHAR(100)Smart-ID relying party UUID
billing_emailVARCHAR(128)(currently not used by SiGa)
max_connection_countINTEGERAllowed maximum number of active sessions for this service. A value of -1 indicates no limit
max_connections_sizeBIGINTAllowed cumulative maximum data volume* for all active sessions. A value of -1 indicates no limit
max_connection_sizeBIGINTAllowed maximum data volume* for a single session. A value of -1 indicates no limit
inactiveBOOLEANIndicates if the service is active or not
created_atTIMESTAMPService creation date
updated_atTIMESTAMPService update date

* data volume is based on the content length of HTTP POST requests.

SIGA_CONNECTION

A table holding cumulative data volume* per active session.

Column nameTypeDescription
idSERIAL (autoincrement primary key)Entry ID
container_idVARCHAR(36)Container ID (an internal identifier identifying a currently active session)
service_idINTEGERService ID (foreign key to SIGA_SERVICE)
sizeBIGINTCumulative data volume* for this session
created_atTIMESTAMPConnection creation date
updated_atTIMESTAMPConnection update date

* data volume is based on the content length of HTTP POST requests.

SIGA_IP_PERMISSION

A table holding ip permissions for external Siga service (SOAP PROXY)

Column nameTypeDescription
idSERIAL (autoincrement primary key)Entry ID
service_idINTEGERService ID (foreign key to SIGA_SERVICE)
ip_addressVARCHAR(36)Allowed ip address
created_atTIMESTAMPIp permission creation date
updated_atTIMESTAMPIp permission update date

Running SiGa with Docker

For development and testing purposes only!

Preconditions

  1. Java 17
  2. Docker must be installed and running.
  3. The siga-demo-application docker image must be built and available on Docker as siga-demo-application:latest.

First time setup:

  1. Build this project
./mvnw clean install
  1. Build SiGa webapp docker image
./mvnw spring-boot:build-image -pl siga-webapp -DskipTests
  1. Generate application keystores/truststores
./docker/tls/generate-certificates.sh
  1. From your project directory, start up your applications in test mode by running
docker-compose up --build

Now SiGa itself is accessible https://localhost:8443/siga and siga-demo-application https://siga-demo.localhost:9443/ . You can view the logs for all the running containers at http://localhost:11080 .

For updating software:

  1. Build the project with changes
./mvnw clean install
  1. Build SiGa webapp docker image
./mvnw spring-boot:build-image -pl siga-webapp -DskipTests
  1. Run the image
docker-compose up

Using SID mock

By default, dockerized SiGa is using SK Smart-ID DEMO service. To use SID-mock instead run:

docker compose -f docker-compose.yaml -f docker-compose-sid-mock.yaml up -d 

Integration tests

Integration tests for SiGa are available in the following repository: https://github.com/open-eid/SiGa-Tests