Skip to content

Latest commit

 

History

History
439 lines (319 loc) · 15.8 KB

README.md

File metadata and controls

439 lines (319 loc) · 15.8 KB

EU Digital COVID Certificate Lib

DevelopmentUsageDocumentationSupportContributeContributorsLicensing

About

This repository contains the source code of the EU Digital COVID Certificate Library.

The DGC Lib contains shared functionality such as encoding, decoding and connecting to the DGCG.

Usage

Include as Maven Dependency in pom.xml

<dependencies>
    <dependency>
        <groupId>eu.europa.ec.dgc</groupId>
        <artifactId>dgc-lib</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </dependency>
    ...
</dependencies>

If you do not need the DCC Gateway Connector feature you can exclude some dependencies by adding an exclusions tag:

<dependencies>
    <dependency>
        <groupId>eu.europa.ec.dgc</groupId>
        <artifactId>dgc-lib</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>*</artifactId>
            </exclusion>
            <exclusion>
                <groupId>io.github.openfeign</groupId>
                <artifactId>*</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    ...
</dependencies>

Authenticating to GitHub Packages

Attention: GitHub does not allow anonymous access to it's package registry. You need to authenticate in order to use the dgc-lib artefact provided by us. Therefore you need to authenticate to GitHub Packages The following steps need to be performed

  • Create PAT with scopes:
    • read:packages for downloading packages
  • Copy/Augment ~/.m2/settings.xml with the contents of settings.xml present in this repository (or in the DGC repository you are trying to build)
    • Replace ${app.packages.username} with your github username
    • Replace ${app.packages.password} with the generated PAT

Development

Build

Whether you cloned or downloaded the 'zipped' sources you will either find the sources in the chosen checkout-directory or get a zip file with the source code, which you can expand to a folder of your choice.

In either case open a terminal pointing to the directory you put the sources in. The local build process is described afterwards depending on the way you choose.

Maven based build

Building this project is done with maven.

mvnw install

Will download all required dependencies, build the project and stores the artifact in your local repository.

Documentation

The following chapter describes the features of dgc-lib and how to use them.

DGCG Connector

The dgc-lib provides a Spring-Boot ready connector for communicating with DGC Gateway. The connector has the following functions:

Trusted Certificate Download

To download certificates from DGCG you just have to inject the DgcGatewayDownloadConnector and call the method getTrustedCertificates. This method will check if a cached version of the downloaded certificates already exists. The maximum age of the cache can be configured via properties. If the cache is too old or does not exist the connector will call the API of DGC Gateway for Trusted Certificates.

The connector will do the following checks on downloaded certificates:

  • TrustAnchor check of downloaded CSCA
  • TrustAnchor check of downloaded Upload Certificates
  • Check that DSC is issued by a trusted CSCA
  • Check that DSC is signed by a trusted Upload Certificate

The validated list will be returned. In order to connect to DGC Gateway and do all the validating stuff the following configuration is required:

dgc:
  gateway:
    connector:
      enabled: true
      endpoint: https://dgcg.example.org
      proxy:
        enabled: false
        host:
        port: -1
      max-cache-age: 300
      tls-trust-store:
        password: dgcg-p4ssw0rd
        path: classpath:tls-truststore.jks
      tls-key-store:
        alias: mtls_private_cert
        password: dgcg-p4ssw0rd
        path: /var/lib/ssl/mtls.jks
      trust-anchor:
        alias: ta_tst
        password: dgcg-p4ssw0rd
        path: /var/lib/ssl/ta.jks
Disable Upload Certificate Check

Because of an error in DGC Gateway the uploader certificate check can fail. Therefore property to disable the uploader certificate check was introduced:

dgc:
  gateway:
    connector:
      disable-upload-certificate-check: false

This is just a workaround. This "feature" will be removed in future releases.

Trusted Certificate Upload

It is also possible to upload new trusted certificates to provide them to other member states. Therefore the DgcGatewayUploadConnector needs to be injected. Certificates can then be send to the gateway by calling the uploadTrustedCertificate with the certificate to upload as parameter. The signing with upload certificate is handled by the connector.

The following properties needs to be set in order to upload trusted certificates.

dgc:
 gateway:
   connector:
     enabled: true
     endpoint: https://dgcg.example.org
     proxy:
       enabled: false
       host:
       port: -1
     max-cache-age: 300
     tls-trust-store:
       password: dgcg-p4ssw0rd
       path: classpath:tls-truststore.jks
     tls-key-store:
       alias: mtls_private_cert
       password: dgcg-p4ssw0rd
       path: /var/lib/ssl/mtls.jks
     upload-key-store:
       alias: upload
       password: dgcg-p4ssw0rd
       path: classpath:upload.p12

Certificates can also be deleted from gateway. The method call is equal to uploading new certificates. Just use deleteTrustedCertificate instead of uploadTrustedCertificate.

ValidationRule Download

To download ValidationRules from DGCG you just have to inject the DgcGatewayValidationRuleDownloadConnector and call the method getValidationRules. This method has the same behaviour as the one for downloading DCC.

The connector will do the following checks on downloaded ValidationRules:

  • TrustAnchor check of downloaded Upload Certificates
  • Check CMS Signature of ValidationRule
  • Check that Rule is signed by trusted Upload Certificate

The validated list will be returned. In order to connect to DGC Gateway and do all the validating stuff the same configuration as for download DCC is required.

ValidationRule Upload

It is also possible to upload new ValidationRules to provide them to other member states. Therefore the DgcGatewayValidationRuleUploadConnector needs to be injected. ValidationRules can then be send to the gateway by calling the uploadValidationRule with one parameter (a string containing the JSON with the Rule). The signing with upload certificate is handled by the connector.

The same properties as for uploading DCC need to be set in order to upload validation rules.

ValidationRules can also be deleted from gateway. The method call is equal to uploading new certificates. Just use deleteValidationRules. Keep in mind that this call will delete all ValidationRules (all versions) with the given ID.

ValueSet Download

To download ValueSets from DGCG you just have to inject the DgcGatewayValueSetDownloadConnector and call the method getValueSets. This method has the same behaviour as the one for downloading DCC.

For ValidationRules there are no content checks possible.

In order to connect to DGC Gateway the same configuration as for download DCC is required.

Signing

Create Signed Certificate CMS Message

To upload a certificate as trusted issuer it needs to be send as a signed CMS message. The CMS message needs to be signed by your previously sent signing certificate.

In order to create such a signed message you need you signing certificate and the corresponding private key. You also need the certificate you want to envelope into the signed message. Both certificates should be in BouncyCastle's X509CertificateHolder format

To create the signed message the following call is required:

String signedMessaged = new SignedCertificateMessageBuilder()
    .withSigningCertificate(signingCert,signingCertPrivateKey)
    .withPayload(inputCert)
    .buildAsString();

This call returns a base64 encoded string with the signed message.

If one of your certificates is in X509Certificate format you can simply convert them using the convert methods from Utils package.

Detached Message

It is also possible to create a detached signature. Just pass the boolean value true to the build() or buildAsString() method.

String detachedSignature = new SignedCertificateMessageBuilder()
    .withSigningCertificate(signingCert,signingCertPrivateKey)
    .withPayload(inputCert)
    .buildAsString(true);

Parse Signed Certificate CMS Message

When a certificate is received it needs to be "unpacked". To do so the SignedCertificateMessageParser can be utilized.

Simply instantiate SignedCertificateMessageParser with the base64 encoded String.

SignedCertificateMessageParser parser = new SignedCertificateMessageParser(inputString);

The constructor accepts different formats as incoming message. Also detached signatures are accepted.

SignedCertificateMessageParser parser = new SignedCertificateMessageParser(payloadByteArray, signatureString);

All combinations of String and byte[] as parameter for signature and payload are possible. Please be aware that the payload will be always base64 encoded (even if it is passed as byte[]).

The parser will immediately parse the message. The result can be obtained from

parser.getParserState();

If the state is SUCCESS the syntax of the message was correct and the certificate could be parsed.

Also the parser checks if the signature of the CMS message was created by the embedded signer certificate. To obtain the result of this check just read the property

parser.isSignatureVerified();

The signer certificate and the containing certificate can be accessed by

parser.getSigningCertificate();
parser.getPayload();

Also a detached signature can be gained from parsed message

parser.getSignature()

Signing and Parsing of other data types

It is also possible to sign and parse CMS messages with other data types. Therefore, implementations of SignedMessageBuilder and SignedMessageParser are required.

The DGC-Lib currently contains Implementations for the following classes:

Data Type Parser Implementation Builder Implementation
java.lang.String SignedStringMessageParser SignedStringMessageBuilder
org.bouncycastle.cert.X509CertificateHolder SignedCertificateMessageParser SignedCertificateMessageBuilder

The usage of Parser and Builder can be seen in the chapter above. Basic usage is equal for all implementations of Parser and Builder.

Utils

Certificate Utils

The Certificate Utils class provides a few methods related to certificate handling. The class can be injected through Spring's Dependency Injection.

Convert Certificate

The convert Certificate can be used to convert a X509Certificate into BouncyCastle's X509CertificateHolder format and vice versa.

import eu.europa.ec.dgc.utils.CertificateUtils;
import org.springframework.beans.factory.annotation.Autowired;

class Convert {

    @Autowired
    CertificateUtils certificateUtils;

    public static void main() {
        X509Certificate x509Certificate = cert; /* your X509Certificate */
        X509CertificateHolder x509CertificateHolder = certificateUtils.convertCertificate(x509Certificate);
    }
}

Calculate Certificate SHA-256 Hash

This method can be used to calculate the SHA-256 hash of X509Certificate (or BouncyCastle's X509CertificateHolder) The result is a String encoded Hex String containing the certificates hash (64 character)

import eu.europa.ec.dgc.utils.CertificateUtils;
import org.springframework.beans.factory.annotation.Autowired;

class Hash {

    @Autowired
    CertificateUtils certificateUtils;

    public static void main() {
        System.out.println(
            certificateUtils.getCertThumbprint(x509Certificate)
        );
    }
}

Calculate Certificate KID

This method can be used to calculate the KID of X509Certificate (or BouncyCastle's X509CertificateHolder) The format of this KID is used in Digital Green Certificate Context.

import eu.europa.ec.dgc.utils.CertificateUtils;
import org.springframework.beans.factory.annotation.Autowired;

class KidTest {

    @Autowired
    CertificateUtils certificateUtils;

    public static void main() {
        System.out.println(
            certificateUtils.getCertKid(x509Certificate)
        );
    }
}

Support and feedback

The following channels are available for discussions, feedback, and support requests:

Type Channel
DGC Gateway issues
DGC Lib issues
Other requests

How to contribute

Contribution and feedback is encouraged and always welcome. For more information about how to contribute, the project structure, as well as additional contribution information, see our Contribution Guidelines. By participating in this project, you agree to abide by its Code of Conduct at all times.

Contributors

Our commitment to open source means that we are enabling -in fact encouraging- all interested parties to contribute and become part of its developer community.

Licensing

Copyright (C) 2021 T-Systems International GmbH and all other contributors

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.

You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0.

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an " AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the LICENSE for the specific language governing permissions and limitations under the License.