Development • Usage • Documentation • Support • Contribute • Contributors • Licensing
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.
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>
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 ofsettings.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
- Replace
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.
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.
The following chapter describes the features of dgc-lib and how to use them.
The dgc-lib provides a Spring-Boot ready connector for communicating with DGC Gateway. The connector has the following functions:
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
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.
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
.
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.
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.
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.
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.
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);
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()
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.
The Certificate Utils class provides a few methods related to certificate handling. The class can be injected through Spring's Dependency Injection.
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);
}
}
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)
);
}
}
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)
);
}
}
The following channels are available for discussions, feedback, and support requests:
Type | Channel |
---|---|
DGC Gateway issues | |
DGC Lib issues | |
Other requests |
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.
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.
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.