Skip to content

Commit

Permalink
Merge pull request #11 from WorldHealthOrganization/feat/generate_dsc
Browse files Browse the repository at this point in the history
feat : generate dsc
  • Loading branch information
ascheibal authored Jul 18, 2024
2 parents ab82a24 + f97999e commit bd8b894
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 30 deletions.
8 changes: 8 additions & 0 deletions scripts/certgen/DN_template.cnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Configuration Template for Certificate Generation
# Modify for your own needs

export OSSL_COUNTRY_NAME="XA"
export OSSL_STATE_NAME="Test State"
export OSSL_LOCALITY_NAME="Geneva"
export OSSL_ORGANIZATION_NAME="WHO"
export OSSL_ORGANIZATIONAL_UNIT_NAME="R&D"
45 changes: 43 additions & 2 deletions scripts/certgen/DSC.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,47 @@
[ext]
OSSL_COUNTRY_NAME = XA
OSSL_STATE_NAME = Test Country XA
OSSL_LOCALITY_NAME = Locality in country XA
OSSL_ORGANIZATION_NAME = Health Ministry of XA
OSSL_ORGANIZATIONAL_UNIT_NAME = FDA
OSSL_COMMON_NAME = Health Administration of XA

[req]
prompt = no
default_md = sha256
distinguished_name = dn

[dn]
C = $ENV::OSSL_COUNTRY_NAME
ST = $ENV::OSSL_STATE_NAME
L = $ENV::OSSL_LOCALITY_NAME
O = $ENV::OSSL_ORGANIZATION_NAME
OU = $ENV::OSSL_ORGANIZATIONAL_UNIT_NAME
CN = $ENV::OSSL_COMMON_NAME

[all]
keyUsage = critical, digitalSignature
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
crlDistributionPoints = URI:http://crl.exampledomain.example/CRL/SCA.crl
extendedKeyUsage = 1.3.6.1.4.1.1847.2021.1.1,1.3.6.1.4.1.1847.2021.1.2,1.3.6.1.4.1.1847.2021.1.3
extendedKeyUsage = 1.3.6.1.4.1.1847.2021.1.1,1.3.6.1.4.1.1847.2021.1.2,1.3.6.1.4.1.1847.2021.1.3

[test]
keyUsage = critical,digitalSignature
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
crlDistributionPoints = URI:http://crl.exampledomain.example/CRL/SCA.crl
extendedKeyUsage = 1.3.6.1.4.1.1847.2021.1.1

[vax]
keyUsage = critical,digitalSignature
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
crlDistributionPoints = URI:http://crl.exampledomain.example/CRL/SCA.crl
extendedKeyUsage = 1.3.6.1.4.1.1847.2021.1.2

[rec]
keyUsage = critical,digitalSignature
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
crlDistributionPoints = URI:http://crl.npkd.nl/CRLs/NLD-Health.crl
extendedKeyUsage = 1.3.6.1.4.1.1847.2021.1.3
36 changes: 20 additions & 16 deletions scripts/certgen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,17 @@ Following [Certificate Preperation](https://worldhealthorganization.github.io/sm

Disclaimer: The script generates self-signed certificates not intended to be used on production environments.

You must adapt the following default certificate parameter in [gen_all_certs.sh](gen_all_certs.sh) to your needs:

```
export OSSL_COUNTRY_NAME="XA"
export OSSL_STATE_NAME="Test State"
export OSSL_LOCALITY_NAME="Geneva"
export OSSL_ORGANIZATION_NAME="WHO"
export OSSL_ORGANIZATIONAL_UNIT_NAME="R&D"
```
You must adapt the configuration file [template.cnf](template.cnf) to your needs:

Then execute the script. It will generate all certificates and keys in a subfolder named by current datetime.

```
cd scripts/certgen
./gen_all_certs.sh
./gen_all_certs.sh template.cnf
```

**Note: keep your private keys safe and secure. Do not share them with anyone.**
=======
## Execution On Windows
Windows plattform you can use [gen_all_certs.ps1](gen_all_certs.ps1) instead.
Please note that you need to have [OpenSSL installed](https://slproweb.com/products/Win32OpenSSL.html) (e.g. Win64 OpenSSL v3.3.0 Light) and added to your PATH environment variable.
Expand All @@ -32,11 +26,7 @@ Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process

# Prepare Folders

Note: keep your private keys safe and secure. Do not share them with anyone.

Copy the generated certificates to the respective folders and change the file names to match the naming convention.
For the case of self-signed TLS certificates, the CA.pem is just a copy of the TLS.pem (check to have keyCertSign in the keyUsage).
The CA.pem should exist, since it is used to verify the TLS client certificate when connecting to the TNG application.
Copy the generated certificates to the respective folders.

# Tagging for taking into use

Expand All @@ -45,6 +35,20 @@ Finally commit push changes and make a signed tag for the version you want to ta
```
git add .
git commit -m "feat(cert): update certificates for onboarding"
GIT_TRACE=1 git tag -s v0.0.1 -m 'onboardingRequest'
git tag -s <YOUR-TAGNAME> -m 'onboardingRequest'
git push --tags
```

# Generate DSCs
After onboarding you probably want to generate and upload your DSCs.
DSC Genration can be performed with the [gen_dsc.sh](gen_dsc.sh) script.
For execution replace \<SUBDIR\> with the path where your SCA.key and SCA.pem reside.
Optionally the purpose of the DSC can be provided with the third parameter. When this is omitted,
then the DSCs will be suitable for test, vaccination and recovery.
```
gen_dsc.sh template.cnf <SUBDIR> [test|vax|rec]
```
# Upload DSCs
For uploading DSCs they must be packend into an CMS and be signed with the Upload Certificate of their issuer.
The resulting output must be base64 encoded and put in the payload of a POST request to the TNG.
A script [upload_dsc.sh](upload_dsc.sh) performs these tasks and may be tailored to your needs.
29 changes: 17 additions & 12 deletions scripts/certgen/gen_all_certs.sh
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
#!/bin/zsh
# valid for 4 years
# this script generates all certificates and keys for the SCA, TLS, and upload
# all certificates are self-signed
# the DN is taken from the configuration file passed as argument
# -----------------------------------------------------------------
# SCA is valid for 4 years
DAYS_CA=1461
# valid for 1 year
# TLS is valid for 1 year
DAYS_TLS=365
# valid for 1 year
# Upload Cert is valid for 1 year
DAYS_UPLOAD=365

# configure the DN
export OSSL_COUNTRY_NAME="XA"
export OSSL_STATE_NAME="Test State"
export OSSL_LOCALITY_NAME="Geneva"
export OSSL_ORGANIZATION_NAME="WHO"
export OSSL_ORGANIZATIONAL_UNIT_NAME="R&D"
#export OSSL_COMMON_NAME="WHO International" # default entry of the corresponding config file will be used
if [ $# -ne 1 ]; then
echo "Usage: $0 DN configuration"
exit 1
fi
source $1

# generate a new directory for each run
subdir=$(date +%Y%m%d%H%M%S)
subdir=${OSSL_COUNTRY_NAME}_$(date +%Y%m%d%H%M%S)
mkdir -p ${subdir}
# generate the certificates and keys for the SCA, TLS, and upload
openssl req -x509 -new -days ${DAYS_CA} -newkey ec:<(openssl ecparam -name prime256v1) -extensions ext -keyout ${subdir}/SCA.key -nodes -out ${subdir}/SCA.pem -config sca.conf
#openssl req -x509 -new -days ${DAYS_CA} -newkey ec:<(openssl ecparam -name prime256v1) -extensions ext -keyout ${subdir}/SCA.key -nodes -out ${subdir}/SCA.pem -config sca.conf
openssl req -x509 -new -days ${DAYS_CA} -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -extensions ext -keyout ${subdir}/SCA.key -nodes -out ${subdir}/SCA.pem -config sca.conf
openssl req -x509 -new -days ${DAYS_TLS} -newkey ec:<(openssl ecparam -name prime256v1) -extensions ext -keyout ${subdir}/TLS.key -nodes -out ${subdir}/TLS.pem -config TLSClient.conf
openssl req -x509 -new -days ${DAYS_UPLOAD} -newkey ec:<(openssl ecparam -name prime256v1) -extensions ext -keyout ${subdir}/UP.key -nodes -out ${subdir}/UP.pem -config uploadCert.conf
#special case to only place CA.pem file for self-signed TLS cert as a copy
cat ${subdir}/TLS.pem > ${subdir}/CA.pem


43 changes: 43 additions & 0 deletions scripts/certgen/gen_dsc.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/zsh
# this script generates digital signing certificates (DSC)
# the DN is taken from the configuration file passed as argument
# the DSC is generated beneath the directory passed as argument, a new on on each run
# as third parameter, the purpose of the DSC can be passed, e.g. test, vax, rec
# for test, vaccination, and recovery. Omitting the third parameter will result in
# a DSC that can be used for all purposes
# -----------------------------------------------------------------

# DSC is valid for 2 years
VAL_DAYS_DSC=730

if [ $# -lt 2 ]; then
echo "Usage: $0 <DN_template.cnf> <subdir> (where <subdir> must contain SCA.pem and SCA.key) [test|vax|rec]"
exit 1
fi
if [ -z $3 ]; then
ext=all
else
ext=$3
fi

subdir=$2
dsc_dir=${subdir}/DSC_$(date +%Y%m%d%H%M%S)
mkdir -p ${dsc_dir}

# source the DN from the given configuration file (DN_template.cnf is an example)
source $1

# First create a new private key and a CSR. Note that the keyoptions are hardcoded to prime256v1 curve.
# Use 'openssl ecparam -list_curves' to get a full list of EC curves.
# To use RSA, replace '-newkey ec' with '-newkey rsa' and substitute the 'ec_paramgen_curve' option with 'rsa_keygen_bits:<keysize>'

#openssl req -newkey ec:<(openssl ecparam -name prime256v1) -keyout ${subdir}/DSC.key -nodes -out ${subdir}/DSC_csr.pem -config DSC.conf # this does only work on Linux/MacOS
openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -keyout ${dsc_dir}/DSC.key -nodes -out ${dsc_dir}/DSC_csr.pem -config DSC.conf

# ...then sign the CSR with the SCA resulting in a DSC
openssl x509 -req -in ${dsc_dir}/DSC_csr.pem -CA ${subdir}/SCA.pem -CAkey ${subdir}/SCA.key -CAcreateserial -days ${VAL_DAYS_DSC} -extensions $ext -extfile DSC.conf -out ${dsc_dir}/DSC.pem

# cleanup the intermediate CSR file
rm ${dsc_dir}/DSC_csr.pem


42 changes: 42 additions & 0 deletions scripts/certgen/upload_dsc.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/bash
# this script uploads the DSC to the TNG DEV
# a given subdir containing the DSC.pem and DSC.key is expected
# optionally, a domain can be passed as second parameter
# -----------------------------------------------------------------

if [ $# -lt 2 ]; then
echo "Usage: $0 <subdir> (where <subdir> must contain UP.pem and UP.key) <DSC DIR> [Domain]"
exit 1
fi
if ! [ -d "$2" ]; then
echo "No DSC DIR specified, second parameter must be a directory"
exit 1
fi
if [ -z $3 ]; then
echo "No domain specified: using DCC" #TODO: change to DDCC when accepted by TNG
domain=DCC
else
domain=$3
fi

subdir=$1
dsc_dir=$2

openssl x509 -outform der -in ${dsc_dir}/DSC.pem -out ${dsc_dir}/DSC.der
openssl cms -sign -nodetach -in ${dsc_dir}/DSC.der -signer ${subdir}/UP.pem -inkey ${subdir}/UP.key -out ${dsc_dir}/DSC_cms.der -outform DER -binary
openssl enc -base64 -in ${dsc_dir}/DSC_cms.der -e -A > ${dsc_dir}/DSC_cms.b64
#openssl x509 -in ${subdir}/DSC.pem -noout -fingerprint -sha256 | sed 's/://g'
payload=$(cat ${dsc_dir}/DSC_cms.b64)

curl --location 'https://tng-dev.who.int/trustedCertificate' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{"cms": "'"${payload}"'", "properties": {}, "domain": "'"${domain}"'"}' \
--key ${subdir}/TLS.key \
--cert ${subdir}/TLS.pem \

#cleanup
rm ${dsc_dir}/DSC.der
rm ${dsc_dir}/DSC_cms.der
rm ${dsc_dir}/DSC_cms.b64

0 comments on commit bd8b894

Please sign in to comment.