From 3b8a5cba66884d51750ae8752e0fccfee911f3fc Mon Sep 17 00:00:00 2001 From: Felix Dittrich Date: Thu, 30 May 2024 09:36:03 +0200 Subject: [PATCH 1/7] Fix Documentation --- certs/PlaceYourGatewayAccessKeysHere.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certs/PlaceYourGatewayAccessKeysHere.md b/certs/PlaceYourGatewayAccessKeysHere.md index 649a702..295b3c5 100644 --- a/certs/PlaceYourGatewayAccessKeysHere.md +++ b/certs/PlaceYourGatewayAccessKeysHere.md @@ -51,7 +51,7 @@ This will result in a KeyStore (P12) containing the previously generated private ```yaml dgc: did: - didUploadProvider: local-file + didSigningProvider: local-keystore localKeyStore: alias: did-signer password: secure-password From d2ca906660c291824c40c696365f624ec2dafd63 Mon Sep 17 00:00:00 2001 From: Torsten Egenolf Date: Mon, 3 Jun 2024 18:30:53 +0200 Subject: [PATCH 2/7] feat(did): did signing setup --- certs/How-to-setup-did-signing.md | 64 +++++++++++++++++++ certs/PlaceYourGatewayAccessKeysHere.md | 28 -------- certs/generate_did_document.py | 64 +++++++++++++++++++ .../tngkds-backend/templates/deployment.yaml | 16 +++++ .../tngkds/charts/tngkds-backend/values.yaml | 2 +- 5 files changed, 145 insertions(+), 29 deletions(-) create mode 100644 certs/How-to-setup-did-signing.md create mode 100644 certs/generate_did_document.py diff --git a/certs/How-to-setup-did-signing.md b/certs/How-to-setup-did-signing.md new file mode 100644 index 0000000..ed34cac --- /dev/null +++ b/certs/How-to-setup-did-signing.md @@ -0,0 +1,64 @@ +# How to setup signing material for DID Signing + +KDS is able to provide a DID-Document holding the downloaded keys. The DID-Document will be signed by a private key provided in a KeyStore. + +Generate Private Key (Choose another Curve depending your needs) + +``` +openssl ecparam -name prime256v1 -genkey -noout -out did-signer.pem +``` + +Convert PEM-File to KeyStore + +``` +openssl pkcs12 -export -out did-signer.p12 -inkey did-signer.pem -nocerts -passout pass:secure-password -name did-signer +``` + +This will result in a KeyStore (P12) containing the previously generated private key stored with alias "did-signer" and secured with password "secure-password" + +```yaml +dgc: + did: + didSigningProvider: local-keystore + localKeyStore: + alias: did-signer + password: secure-password + path: ./certs/did-signer.p12 +``` + +## How to publish corresponding public key for verification of DID signature + +Generate the public key of the did singer + +``` +openssl ec -in did-signer.pem -pubout -out did-signer-public-key.pem +``` + +Adapt the following environment variables to your needs and generate a did document for your public key. + +| Environment Variable | Description | +| --- | --- | +| `PUBLIC_KEY_FILE` | Path to the public key file (e.g., "./did-signer-public-key.pem") | +| `DID_ID` | Identifier for the DID (e.g., "did:web:raw.githubusercontent.com:WorldHealthOrganization:tng-participants-dev:main:WHO:signing:DID") | +| `DID_CONTROLLER` | Controller for the DID (e.g., "did:web:raw.githubusercontent.com:WorldHealthOrganization:tng-participants-dev:main:WHO:signing:DID") | + +``` +export PUBLIC_KEY_FILE="./did-signer-public-key.pem" +export DID_ID="did:web:raw.githubusercontent.com:WorldHealthOrganization:tng-participants-dev:main:WHO:signing:DID" +export DID_CONTROLLER="did:web:raw.githubusercontent.com:WorldHealthOrganization:tng-participants-dev:main:WHO:signing:DID" +python generate_did_document.py +``` + +Place the generated DID to it's intended location on a host corresponding to the DID ID as defined by [did:web method specification](https://w3c-ccg.github.io/did-method-web/). + +## How to update the did-signer in the environment + +``` +kubectl create secret generic did-signer-secret --dry-run=client --namespace=kds -o yaml --from-file=did-signer.p12 > did-signer-secret.yaml +``` + +Connected to the correct kubernetes context deploy the generated secret + +```(shell) +kubectl apply -f did-signer-secret.yaml +``` diff --git a/certs/PlaceYourGatewayAccessKeysHere.md b/certs/PlaceYourGatewayAccessKeysHere.md index 295b3c5..f181094 100644 --- a/certs/PlaceYourGatewayAccessKeysHere.md +++ b/certs/PlaceYourGatewayAccessKeysHere.md @@ -29,31 +29,3 @@ Create a pkcs12 KeyStore from the TLS.pem and TLS.key: ``` openssl pkcs12 -export -out tls_key_store.p12 -inkey TLS.key -in TLS.pem -passout pass:dgcg-p4ssw0rd -name clientcredentials ``` - -# How to setup signing material for DID Signing - -KDS is able to provide a DID-Document holding the downloaded keys. The DID-Document will be signed by a private key provided in a KeyStore. - -Generate Private Key (Choose another Curve depending your needs) - -``` -openssl ecparam -name prime256v1 -genkey -noout -out did-signer.pem -``` - -Convert PEM-File to KeyStore - -``` -openssl pkcs12 -export -out did-signer.p12 -inkey did-signer.pem -nocerts -passout pass:secure-password -name did-signer -``` - -This will result in a KeyStore (P12) containing the previously generated private key stored with alias "did-signer" and secured with password "secure-password" - -```yaml -dgc: - did: - didSigningProvider: local-keystore - localKeyStore: - alias: did-signer - password: secure-password - path: ./did-signer.p12 -``` diff --git a/certs/generate_did_document.py b/certs/generate_did_document.py new file mode 100644 index 0000000..c02bed1 --- /dev/null +++ b/certs/generate_did_document.py @@ -0,0 +1,64 @@ +import json +import base64 +import os +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric import ec +from cryptography.hazmat.backends import default_backend + +# Get the path to the public key file, did-id and did-controller from the environment variables +public_key_file = os.getenv('PUBLIC_KEY_FILE') +did_id = os.getenv('DID_ID') +did_controller = os.getenv('DID_CONTROLLER') + +# Read the public key from the file +with open(public_key_file, 'rb') as f: + public_key_pem = f.read() + +# Load the public key +public_key = serialization.load_pem_public_key(public_key_pem, backend=default_backend()) + +# Check if the public key is an elliptic curve public key +if isinstance(public_key, ec.EllipticCurvePublicKey): + # Get the x and y coordinates of the public key + x = public_key.public_numbers().x + y = public_key.public_numbers().y + +# Convert the x and y coordinates to base64url format +x = base64.urlsafe_b64encode(x.to_bytes((x.bit_length() + 7) // 8, 'big')).decode().rstrip('=') +y = base64.urlsafe_b64encode(y.to_bytes((y.bit_length() + 7) // 8, 'big')).decode().rstrip('=') + +# Convert the public key to PEM format and encode it in base64 +public_key_pem = public_key.public_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PublicFormat.SubjectPublicKeyInfo +) +public_key_pem_b64 = base64.b64encode(public_key_pem).decode() + +did_document = { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": did_id, + "controller": did_controller, + "verificationMethod": [ + { + "id": did_id + "#%2FrcyDdJNU%2FA%3D", + "type": "JsonWebKey2020", + "controller": did_controller, + "publicKeyJwk": { + "kty": "EC", + "x5c": [ + public_key_pem_b64 + ], + "crv": "P-256", + "x": x, + "y": y + } + } + ] +} + +# Write the DID document to a file +with open('did.json', 'w') as f: + json.dump(did_document, f, indent=4) diff --git a/k8s/helm/tngkds/charts/tngkds-backend/templates/deployment.yaml b/k8s/helm/tngkds/charts/tngkds-backend/templates/deployment.yaml index 828c5e6..cd872b2 100644 --- a/k8s/helm/tngkds/charts/tngkds-backend/templates/deployment.yaml +++ b/k8s/helm/tngkds/charts/tngkds-backend/templates/deployment.yaml @@ -107,6 +107,12 @@ spec: value: "{{ index .Values.did "trust-list-id-prefix" }}" - name: DGC_DID_TRUSTLISTCONTROLLEPREFIX value: "{{ index .Values.did "trust-list-controller-prefix" }}" + - name: DGC_DID_LOCALKEYSTORE_ALIAS + value: {{ .Values.did.localKeyStore.alias | quote }} + - name: DGC_DID_LOCALKEYSTORE_PASSWORD + value: {{ .Values.did.localKeyStore.password | quote }} + - name: DGC_DID_LOCALKEYSTORE_PATH + value: {{ .Values.did.localKeyStore.path | quote }} {{- range $key, $value := .Values.did.virtualCountries }} - name: DGC_DID_VIRTUALCOUNTRIES_{{ $key | toString | upper }} value: "{{ $value }}" @@ -122,6 +128,9 @@ spec: - name: secrets-jks mountPath: /certs readOnly: true + - name: did-signing + mountPath: /didcerts + readOnly: true resources: {{- toYaml .Values.resources | nindent 12 }} {{- with .Values.nodeSelector }} @@ -147,3 +156,10 @@ spec: path: trustanchor_store.jks - key: tng_tls_server_truststore.p12 path: tng_tls_server_truststore.p12 + - name: did-signing + secret: + secretName: did-signer-secret + items: + - key: did-signer.p12 + path: did-signer.p12 + diff --git a/k8s/helm/tngkds/charts/tngkds-backend/values.yaml b/k8s/helm/tngkds/charts/tngkds-backend/values.yaml index c26858c..4fe39f0 100644 --- a/k8s/helm/tngkds/charts/tngkds-backend/values.yaml +++ b/k8s/helm/tngkds/charts/tngkds-backend/values.yaml @@ -158,7 +158,7 @@ did: did-id: did:web:worldhealthorganization.github.io:tng-cdn-dev:v2.0.0 trust-list-path: trustlist trust-list-ref-path: trustlist-ref - did-controller: did:web:def + did-controller: did:web:worldhealthorganization.github.io:tng-cdn-dev:v2.0.0 trust-list-id-prefix: did:web:abc trust-list-controller-prefix: did:web:abc contextMapping: From a1a941f50eaa9b6f391994fdc37aef68fb1f6cee Mon Sep 17 00:00:00 2001 From: Torsten Egenolf Date: Tue, 4 Jun 2024 17:08:40 +0200 Subject: [PATCH 3/7] feat(did): removed not needed x5c (keys only) --- certs/generate_did_document.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/certs/generate_did_document.py b/certs/generate_did_document.py index c02bed1..d41147b 100644 --- a/certs/generate_did_document.py +++ b/certs/generate_did_document.py @@ -48,9 +48,6 @@ "controller": did_controller, "publicKeyJwk": { "kty": "EC", - "x5c": [ - public_key_pem_b64 - ], "crv": "P-256", "x": x, "y": y From bcbec9ff25a5ebbd8aa7b87fa20f39ec26f3f80a Mon Sep 17 00:00:00 2001 From: Torsten Egenolf Date: Tue, 4 Jun 2024 18:36:50 +0200 Subject: [PATCH 4/7] feat(did): docs for padding --- certs/generate_did_document.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/certs/generate_did_document.py b/certs/generate_did_document.py index d41147b..ecf9860 100644 --- a/certs/generate_did_document.py +++ b/certs/generate_did_document.py @@ -24,6 +24,7 @@ y = public_key.public_numbers().y # Convert the x and y coordinates to base64url format +# using base64url without padding as in https://datatracker.ietf.org/doc/html/rfc7515#appendix-C x = base64.urlsafe_b64encode(x.to_bytes((x.bit_length() + 7) // 8, 'big')).decode().rstrip('=') y = base64.urlsafe_b64encode(y.to_bytes((y.bit_length() + 7) // 8, 'big')).decode().rstrip('=') @@ -43,7 +44,7 @@ "controller": did_controller, "verificationMethod": [ { - "id": did_id + "#%2FrcyDdJNU%2FA%3D", + "id": did_id, "type": "JsonWebKey2020", "controller": did_controller, "publicKeyJwk": { From 33d85b5f715cc2c242c74e398681aa5f2610c191 Mon Sep 17 00:00:00 2001 From: Torsten Egenolf Date: Fri, 7 Jun 2024 15:11:20 +0200 Subject: [PATCH 5/7] fix(pr): removed unused public key --- certs/generate_did_document.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/certs/generate_did_document.py b/certs/generate_did_document.py index ecf9860..4215ebe 100644 --- a/certs/generate_did_document.py +++ b/certs/generate_did_document.py @@ -28,13 +28,6 @@ x = base64.urlsafe_b64encode(x.to_bytes((x.bit_length() + 7) // 8, 'big')).decode().rstrip('=') y = base64.urlsafe_b64encode(y.to_bytes((y.bit_length() + 7) // 8, 'big')).decode().rstrip('=') -# Convert the public key to PEM format and encode it in base64 -public_key_pem = public_key.public_bytes( - encoding=serialization.Encoding.PEM, - format=serialization.PublicFormat.SubjectPublicKeyInfo -) -public_key_pem_b64 = base64.b64encode(public_key_pem).decode() - did_document = { "@context": [ "https://www.w3.org/ns/did/v1", From 92c5e1983bb8a1fef08952f7f464140d7ce1b65d Mon Sep 17 00:00:00 2001 From: Torsten Egenolf Date: Fri, 7 Jun 2024 15:23:28 +0200 Subject: [PATCH 6/7] fix(helm): local keystore did signer config as default --- k8s/helm/tngkds/charts/tngkds-backend/values.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/k8s/helm/tngkds/charts/tngkds-backend/values.yaml b/k8s/helm/tngkds/charts/tngkds-backend/values.yaml index 4fe39f0..69c29d4 100644 --- a/k8s/helm/tngkds/charts/tngkds-backend/values.yaml +++ b/k8s/helm/tngkds/charts/tngkds-backend/values.yaml @@ -152,8 +152,12 @@ did: workdir: /tmp/kdsgituploader # oon clonind will checkout e.g. tng-cdn-dev prefix: v2.0.0 #for copy action into git workdir from local file exporter path url: https://github.com/WorldHealthOrganization/tng-cdn-dev - pat: #TODO: set by secret - didSigningProvider: dummy + pat: + didSigningProvider: local-keystore + localKeyStore: + alias: did-signer + password: secure-password + path: ld-proof-verification-method: did:web:dummy.net did-id: did:web:worldhealthorganization.github.io:tng-cdn-dev:v2.0.0 trust-list-path: trustlist From dde1c5521fcdcb7effbbd58d8091bcfd26048e02 Mon Sep 17 00:00:00 2001 From: Torsten Egenolf Date: Mon, 10 Jun 2024 17:31:25 +0200 Subject: [PATCH 7/7] fix(config): removed unused turstlist prefixes --- .../tngkds/charts/tngkds-backend/templates/deployment.yaml | 4 ---- k8s/helm/tngkds/charts/tngkds-backend/values.yaml | 2 -- .../keydistribution/config/KdsConfigProperties.java | 3 --- src/main/resources/application.yml | 2 -- 4 files changed, 11 deletions(-) diff --git a/k8s/helm/tngkds/charts/tngkds-backend/templates/deployment.yaml b/k8s/helm/tngkds/charts/tngkds-backend/templates/deployment.yaml index cd872b2..65307f0 100644 --- a/k8s/helm/tngkds/charts/tngkds-backend/templates/deployment.yaml +++ b/k8s/helm/tngkds/charts/tngkds-backend/templates/deployment.yaml @@ -103,10 +103,6 @@ spec: value: "{{ index .Values.did "trust-list-ref-path" }}" - name: DGC_DID_DIDCONTROLLER value: "{{ index .Values.did "did-controller" }}" - - name: DGC_DID_TRUSTLISTIDPREFIX - value: "{{ index .Values.did "trust-list-id-prefix" }}" - - name: DGC_DID_TRUSTLISTCONTROLLEPREFIX - value: "{{ index .Values.did "trust-list-controller-prefix" }}" - name: DGC_DID_LOCALKEYSTORE_ALIAS value: {{ .Values.did.localKeyStore.alias | quote }} - name: DGC_DID_LOCALKEYSTORE_PASSWORD diff --git a/k8s/helm/tngkds/charts/tngkds-backend/values.yaml b/k8s/helm/tngkds/charts/tngkds-backend/values.yaml index 69c29d4..84da4a4 100644 --- a/k8s/helm/tngkds/charts/tngkds-backend/values.yaml +++ b/k8s/helm/tngkds/charts/tngkds-backend/values.yaml @@ -163,8 +163,6 @@ did: trust-list-path: trustlist trust-list-ref-path: trustlist-ref did-controller: did:web:worldhealthorganization.github.io:tng-cdn-dev:v2.0.0 - trust-list-id-prefix: did:web:abc - trust-list-controller-prefix: did:web:abc contextMapping: "[https://www.w3.org/ns/did/v1]": did_v1.json "[https://w3id.org/security/suites/jws-2020/v1]": jws-2020_v1.json diff --git a/src/main/java/tng/trustnetwork/keydistribution/config/KdsConfigProperties.java b/src/main/java/tng/trustnetwork/keydistribution/config/KdsConfigProperties.java index f4c3e11..1e7b98a 100644 --- a/src/main/java/tng/trustnetwork/keydistribution/config/KdsConfigProperties.java +++ b/src/main/java/tng/trustnetwork/keydistribution/config/KdsConfigProperties.java @@ -101,9 +101,6 @@ public static class DidConfig { private String trustListPath; private String trustListRefPath; - private String trustListIdPrefix; - private String trustListControllerPrefix; - private String ldProofVerificationMethod; private String ldProofDomain; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 24ae187..9d6e802 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -102,8 +102,6 @@ dgc: trust-list-path: trustlist trust-list-ref-path: trustlist-ref did-controller: did:web:def - trust-list-id-prefix: did:web:abc - trust-list-controller-prefix: did:web:abc contextMapping: "[https://www.w3.org/ns/did/v1]": did_v1.json "[https://w3id.org/security/suites/jws-2020/v1]": jws-2020_v1.json