Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

130 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Table of Contents

Overview

This tool allows you to generate TRIAL (test) certificates for the PKIoverheid G4 hierarchies yourself. It generates a complete hierarchy of certificates resembling a chosen G4 hierarchy. For more information on these hierarchies, please refer to the PKIoverheid CPS, Section 1.1.

G4 TRIAL end entity certificates for testing purposes can be acquired free of charge from the following organisation(s); however, when certificates are issued on physical tokens, a fee may apply.

Please note: only the PKIoverheid Trust Service Providers issue production PKIoverheid certificates. For more information see PKIoverheidcertificaat aanvragen (in Dutch).

To generate G4 TRIAL certificates yourself, there are two options:

  • To validate your own (local) technical setup, download this repository and create the full hierarchies yourself;
  • To use for integration testen ("ketentesten") and you intend to issue many TRIAL certificates (perhaps to suppliers) you may request a "fauxTSP" CA certificate for the common G4 TRIAL hierarchies. Please contact us to discuss in detail.

For the G3 certificate hierarchy some PKIoverheid TSPs offer TRIAL certificates. However, the G4 hierarchies consists of many different types of certificates, increasing implementation costs for TSPs. Therefore it was deemed most effective for users to be able to generate their own test certificates using a publicly available tool.

Target audience

Software developers creating applications either using PKIoverheid certificates, or validating signatures created with PKIoverheid certificates, will be the primary audience of the PKIoverheid TRIAL certificates. However, organizations using commercial off the shelf (COTS) software in combination with PKIoverheid certificates or signatures created using them, may also wish to test their software stack with the PKIoverheid TRIAL certificates.

Major changes from G3 to G4

There have been a number of changes from G3 to G4, which you need to be aware of. In depth technical changes are described in the PKIoverheid CPS and Certificate Policy/Programme of Requirements PKIoverheid, while the functional changes are:

  • Instead of one certificate public root (G3) and one private root (G1), the PKIoverheid G4 consists of multiple Certificate Roots, depending on its trust type (Public, Mandated (eIDAS) and Private). Since Privately trusted roots may be used separately within a specific domain, several Privately trusted Certificate Roots are created. Relying parties should only trust the appropriate Certificate Roots. Please see https://cert.pkioverheid.nl/ for details;
  • Many more certificate types are available for the G4 than G3, the certificate issuers' Common Names reflect this accordingly;
  • Intermediate CAs are based upon Subject Type (Natural Persons, Legal Entities or Devices), rather than a validation type, for example the G3's "Organisatie Persoon";
  • No OCSP Service is offered for any of the G4 Root, Domain and TSP certificates. TSPs may still implement OCSP Services if desired;
  • G3 certificates used a limited number of Policy OIDs, this has been expanded significantly for the G4. This allows the relying party to pinpoint exactly which type of certificate and validation was performed;
  • G4 makes a distinction between Authenticity and Authentication certificates, while G3 only defined Authenticity for both use cases. Confidentiality and Authenticity usages for certificates are deemed an edge case and is disabled by default in the G4 TRIAL;
  • Previously two variants existed of G1 Private Services Server certificate (OID: 2.16.528.1.1003.1.2.8.6). One containing one or more domain names and one without. This has been changed in G4. A "G4 Private Other Generic Legal Persons Organization Validated Authentication" does not contain any domains and is used only for clientAuth. A "G4 Private TLS Generic Devices Organization Validated Server" contains one or more domains and can be used for both clientAuth and serverAuth.
  • G3 certificates were allowed to have IP addresses as Subject Alternate Names (SAN). The G4 prohibits this.
  • Signature algorithm RSASSA‐PKCS1‐v1_5 has been designated as legacy by the ECCG Agreed Cryptographic Mechanisms Guideline and is replaced by RSASSA-PSS. This algorithm is used for Certificate Signing Requests (CSR), certificates and CRLs. This may have an impact if TLS 1.2 is used.

Certificate profiles

The PKIoverheid G4 hierarchies offer many different types of certificates, each for a different purpose. Please refer to the factsheet Wees voorbereid de nieuwe generatie pkioverheidcertificaten komen eraan (Dutch) or New generation of PKIoverheid Certificates (English) for details.

The included profiles are compliant with:

Differences between production and TRIAL certificates

Please be aware certificates generated by this tooling differ from their production counterparts in some aspects:

  • There is no Certificate Policy document and as such these certificates provide no trust whatsoever.
  • Serial Numbers are not generated using a CSPRNG.
  • Issuer and Subject fields do not mention "Staat der Nederlanden" or any of the participating TSPs. Instead, "TRIAL PKIoverheid", "My TSP" and/or the name of a fauxTSP are used. Nevertheless, relying parties should not rely on Subject and Issuer fields for trust.
  • Validity range for end entity certificates defaults to 397 days, which may be different from production certificates;
  • Policy Identifiers are defined by the differentation model and differ slightly between TRIAL and Production, for example:
    Certificate type TRIAL Production
    System Organization Validation Server 2.16.528.1.1003.1.2.*41*.15.39.11 2.16.528.1.1003.1.2.*44*.15.39.11
  • TRIAL certificate profiles must be indicative of their production counterparts, as such any required qcStatements for production certificates are also included in TRIAL certificates, even if they're undoubtedly false. For example, certificates may claim the private key resides on a Secure Signature Creation Device (SSCD) as indicated by the qcStatement id-etsi-qcs-QcSSCD, which is obviously false for test certificates.
  • To enable testing on a local machine, TRIAL certificates for private TLS may include localhost as SubjectAlternateName (SAN).
  • There may be some minor (non-security) differences between these TRIAL certificates and certificates offered by the different PKIoverheid TSPs. Most notably the value of the subject.commonName field and the ASN.1 encoding of some subject fields may be different.

Limitations

All G4 TRIAL certificates are self issued and must not be used for any production purpose and should only be used for testing purposes.

Currently, only the following G4 Domains have been included:

  • G4 Private TLS Generic Devices
  • G4 Private Other Generic Natural Persons
  • G4 Private Other Generic Legal Persons
  • G4 EUTL Signatures Generic Natural Persons
  • G4 EUTL Signatures Generic Legal Persons

If you require any other G4 Domain, please open a Github issue in this repository.

Usage

First you'll need to install the software. This can be done directly on your host OS, or use a Docker image.

(option 1) Installation locally

  1. Clone this repository locally
  2. You will need Python >=3.10 installed. If not already installed, please follow the instructions for your operating system at https://www.python.org;
  3. To be able to install additional libraries, you will need to install pip. For instructions please refer to https://packaging.python.org/en/latest/tutorials/installing-packages/;
  4. (optional) create and activate a virtualenv, see previous hyperlink;
  5. Install the packages this repository requires:
    pip install -r requirements.txt

(option 2) Docker image

Docker images of this tooling are automatically built and stored on Github Packages. You will need docker installed and configured on your system. To run the tooling, please refer to the example below.

# Create mountpoints
mkdir ca
touch config.yaml

# Pull image
docker pull ghcr.io/pkioverheid/g4-trial:latest

# Create a CA using an ephemeral docker container (see next step)
docker run -it --rm -v $(pwd)/ca:/app/ca -v $(pwd)/config.yaml:/app/config.yaml ghcr.io/pkioverheid/g4-trial:latest python create-ca.py

Quick start

This repository contains examples which allow you a quick look at G4 certificates.

The following commands will create a G4 TRIAL hierarchy for private TLS and one end entity certificate to secure a TLS endpoint on your local machine. If a Docker container is used these commands will vary slightly.

echo 1 | python create-ca.py
python generate-cert.py examples/enrollment/G4-Private-G-TLS-SYS-withOIN.yaml

Private keys are placed in the ca/private directory and certificates are placed into the ca/certs.

Initialization

There are two methods to initialise:

  1. By creating your own hierarchy (recommended for personal and isolated testing), or
  2. By joining the shared TRIAL hierarchy setup by Logius (recommended for integration testing).

Option 1: Create your own hierarchy/hierarchies

  1. If you ran the Quick start, remove the ca directory to start fresh.
  2. Update the URLs where issuing certificates and CRLs will be located after the initialization is complete. The example config.yaml below allows you to host these files on your local machine, but you may host these files on your internal network for internal testing.
    caIssuersBaseUrl: http://localhost:8080/certs
    cRLDistributionPointsBaseUrl: http://localhost:8080/crl
    crlRenewalHours: 48
  3. Create the top three layers of the CA hierarchy for one or more G4 Domains. These are the self-signed Root CA, Domain CA and Issuing (fauxTSP) CA. This command will prompt which for which PKIoverheid G4 domain you'd like to create private keys, certificates and their (empty) Certificate Revocation Lists (CRL).
    python create-ca.py

Option 2: Joining the shared TRIAL hierarchy

If you wish to join one or more shared TRIAL hierarchies, please reach out to us at pkioverheid@logius.nl so we can discuss the required steps.

This method allows you to create certificates operable with other providers of G4 TRIAL certificates.

  1. Determine for which domains you'd like to issue G4 TRIAL certificates;
  2. Locate the respective enrollment file in the enrollment directory:
    • G4 Private TLS Generic Devices: TRIALMyTSPG4PKIoPrivGTLSSYS2025.yaml
    • G4 Private Other Generic Natural Persons: TRIALMyTSPG4PKIoPrivGOtherNP2025.yaml
    • G4 Private Other Generic Legal Persons: TRIALMyTSPG4PKIoPrivGOtherLP2025.yaml
    • G4 EUTL Signatures Generic Natural Persons: TRIALMyTSPG4PKIoEUTLGSigsNP2025.yaml
    • G4 EUTL Signatures Generic Legal Persons: TRIALMyTSPG4PKIoEUTLGSigsLP2025.yaml
  3. Rename the enrollment file to replace "MyTSP" with your organization's name (letters only, no spaces), for example TRIALMyTSPG4PKIoPrivGTLSSYS2025.yaml would be renamed to TRIALMyOrganizationG4PKIoPrivGTLSSYS2025.yaml. This filename will be used to name the private key file and Certificate Signing Request (CSR) and must be unique within the ca and enrollment directory.
  4. Within the enrollment file, replace any occurrence of the string "My TSP" with your organization name (including spaces), for example "My Organization".
  5. Generate the Certificate Signing Requests (CSR) by running the command below and providing the files you edited:
    python create-csr.py <enrollment files>
    Your enrollment will be validated, and when successful a private key and a CSR file will be created. The private key will be located within the ca/private directory while the CSR will be saved to the current directory.
  6. Send the CSR files to pkioverheid@logius.nl;
  7. PKIoverheid will reach out to you, discuss details and send your certificate(s);
  8. Place the certificate file(s) into the directory ca/certs/
  9. Generate a boilerplate revocation file (which currently does not exist) and generate the first CRL for your certificate:
    python generate-crl.py -f revocations/<enrollment filename>

Create end entity certificates

Each end entity certificate requires subject information to be provided separately from the certificate profile. This information is provided using either an "enrollment" YAML file or a Certificate Signing Request (CSR). Please see any of the files in the examples/enrollment directory. The filename will indicate the certificate type. Please see the "G1/G3 to G4 mapping table" on the logius.nl website for information which certificate type you need for your use case.

If you modified the filename of the TSP CA enrollment file in previous steps, for example renaming "MyTSP" to "MyOrganization", you will need to modify the end entity certificate profiles accordingly since it contains a reference to this file. Below is an example how to modify the file for the G4 Private TLS Generic Devices end entity certificate profile specified in G4TRIALEEPrivGTLSSYS2025.yaml:

Old (snippet):

...
issuer: TRIALMyTSPG4PKIoPrivGTLSSYS2025.yaml
...

New (snippet):

...
issuer: TRIALMyOrganizationG4PKIoPrivGTLSSYS2025.yaml
...

Option 1: FauxTSP generates key pairs

When enrollment files are used, the fauxTSP generates the keypair and provides them to the subscriber. Enrollment files will need to be modified for your own use cases. An example enrollment file for G4 Private TLS Generic Devices could be:

---
profile: profiles/G4TRIALEEPrivGTLSSYS2025.yaml
subject:
  C: NL
  CN: Bedrijfsnaam TLS
  O: Bedrijfsnaam
  organizationIdentifier: NTRNL-99999991
  serialNumber: 00000099123456789000
subjectAltNames:
  - example.com
  - www.example.com

The file indicates which certificate profile is to be used, provides subject information and (in this case) two FQDNs to be included in the certificate. This example uses both a KvK registration number in the organizationIdentifier field and a test OIN indicated by the 00000099 prefix in the serialNumber field. For each end entity certificate you want to create, create an appropriate enrollment file with an unique filename and modify it according to your needs. Then run:

python generate-cert.py <one or more enrollment files>

Prior to generating the certificate, the script will validate your enrollment file against the requirements for the selected certificate profile and output any discrepancies. Please note that no validations are performed on the actual contents of each attribute, please refer to the documents listed under Certificate Profiles to determine what information should be included in each field.

The filenames of the newly generated private and public keys will match the filename of the enrollment file. They will be placed in the ca/private and the ca/certs directories, respectively. The command will not overwrite any preexisting files to prevent destruction of private keys.

Option 2: Subscriber provides public key using a Certificate Signing Request (CSR)

A Subscriber usually generates a key pair themselves, encapsulates the public key alongside subject and subjectAlternateNames information into a PKCS #10 CSR. To generate the certificate using the default settings, run:

python sign-cert.py <CSR file>

This will attempt to localize the appropriate certificate profile. If none or multiple are found an error is shown. Use the --profile flag to manually select the certificate profile to use.

Alternatively you can override the information provided in the CSR (except for the public key). Create an enrollment file as described in Option 1 and provide it to sign-cert.py using the --enrollment flag.

Revocations

When CA certificates are created, an associated Certificate Revocation List (CRL) must be created. By default no certificates are revoked. However, to test revocation checking, you may want to generate some certificates and revoke them.

Each CA certificate will have a corresponding file in the revocations directory. For example:

---
revocations:
  - serialNumber: '78:74:17:c2:a6:23:5f:55:57:ac:38:5e:e3:4d:6e:82:b4:fd:07:eb'
    reason: superseded
    date: "2025-08-08 00:00:00"
  - serialNumber: '75:13:8e:39:29:93:c5:23:62:9f:bb:4c:24:dd:28:6b:41:11:52:c7'
    reason: superseded
    date: "2025-08-10 10:02:00"

Only three values are needed per revocation:

  • serialNumber of the certificate must indicated in hexadecimal format separated by colons (openSSL format);
  • reason for revocation must be one listed in Programme of Requirements Section 7.2 CRL profile;
  • date is the date of revocation. For production uses this date is the actual date of revocation, however for the G4 TRIAL this date is unbounded.

After modification of the revocations file, create a new CRL by executing:

python generate-crl.py <revocation file>

Please do not rename the created CRL file(s) as they are referenced by other certificates (see below) and are used to increment the cRLNumber included within each CRL. Publish the CRL file accordingly (see below).

The Programme of Requirements dictates that CRLs must be renewed (regenerated) at least each 48 hours, and this has been set as default. When publishing the CRL, you may wish to setup a cronjob that automatically recreates the CRL. For testing purposes you may change this setting in config.yaml (see below).

Certificate Status Service

If you'd like to host the CA certificates (as specified in the certificate's authorityInfoAccess extension) and CRLs (as specified in the crlDistributionPoints extension) on your local machine, you can start a minimal webserver:

bash start-server.sh

If desired, these files can be hosted using other webservers on other domains (see below).

Customizing

Issuing certificates and CRL locations

If you intend to host the certificates and CRLs on another domain modify the config.yaml file by modifing the caIssuersBaseUrl and cRLDistributionPointsBaseUrl parameters. You must recreate all certificates for these values to be used. An example configuration could be:

caIssuersBaseUrl: http://cert.mydomain.com
cRLDistributionPointsBaseUrl: http://crl.mydomain.com
crlRenewalHours: 48
pdsLocation:
  url: https://www.github.com/pkioverheid/g4-trial
  language: en

The parameter crlRenewalHours indicates the lifespan of a CRL, i.e. the difference between thisUpdate and nextUpdate. The default is 48 hours, but can be modified for testing purposes.

File list

Filename Description
create_ca.py Script to create the top level CA private keys and certificates
create_csr.py Script to create a Certificate Signing Request to be signed by another entity
generate-cert.py Script to create any number of end entity private keys and certificates
generate-crl.py Script to create CRLs for a CA
sign-cert.py Signs a certificate based upon a previously generated CSR
start_server.sh A minimal webserver to host generated certificates and CRLs
ca/private/*.key Generated private keys
ca/certs/*.pem Issued certificates
ca/crl/*.crl CRLs for the generated CA certificates
examples Example files to create end entity certificates and revocation lists

Requirements

  • Python >3.12

Support & Contributing

These files are provided as-is and no warranty or support is given. However, you may create a Github issue to discuss issues and enhancements.

Roadmap

Based on user input, other G4 hierarchies will be added in future releases.

Disclaimer

This project is provided as-is, without any express or implied warranties, including but not limited to merchantability, fitness for a particular purpose, or non-infringement. Use generated self-signed certificate hierarchies is at your own risk, and the maintainers are not responsible for any security issues, misconfigurations, or unintended consequences. External systems, applications and entities must not trust certificates generated by this tooling.

About

Generate TRIAL certificates for the PKIoverheid G4 hierarchies

Resources

Code of conduct

Contributing

Stars

4 stars

Watchers

6 watching

Forks

Releases

Used by

Contributors

Languages