Manage certificates
This guide shows you how to generate self-signed certificates for development and configure production certificates for the Truvity EUDIW Connector. Certificates authenticate the connector to EUDI Wallets and establish your identity as a registered Relying Party.
- A running connector instance, or one you are preparing to deploy. See connector architecture for the deployment model.
- A tool that can generate EC P-256 keys and X.509 certificates (the examples below use
openssl, available by default on macOS and most Linux distributions) - For production: an X.509 access certificate from a Certificate Authority (CA) or member state registrar
Overview
The EUDI ecosystem defines two certificate types for Relying Parties:
- Access certificates are X.509 certificates that authenticate the connector to wallets. The connector includes the access certificate in the
x5cheader of the signed authorization request JWT, as required by the HAIP profile. The wallet verifies your access certificate against trust lists before showing the consent screen to the user. - Registration certificates are signed data objects (JWT or CWT format, not X.509) that prove your organization's registration as a Relying Party with member state authorities. You obtain these through the member state's registration process.
This guide focuses on access certificates, which the connector requires to sign authorization requests. You are responsible for obtaining, renewing, and rotating your access certificate. The connector loads the certificate and private key from the file system (typically Kubernetes secret volumes) at startup.
Time to implement: 30 minutes for test certificates, 1-2 days for production certificates (depending on CA turnaround).
Step 1: Generate self-signed test certificates
Generate a self-signed EC P-256 key pair and X.509 certificate for development. EC P-256 is required because the HAIP profile mandates ES256 for signing authorization request JWTs. You can use any tool that produces PEM-format EC P-256 keys—the example below uses openssl.
# Generate an EC P-256 private key
openssl ecparam -genkey -name prime256v1 -noout \
-out ./certs/access-key.pem
# Generate a self-signed X.509 certificate (valid for 365 days)
openssl req -new -x509 -key ./certs/access-key.pem \
-out ./certs/access-cert.pem \
-days 365 \
-subj "/CN=My Organization/O=My Organization/C=DE"
The commands generate:
- An EC P-256 private key in PEM format
- A self-signed X.509 certificate in PEM format with a one-year expiration
Verify the generated certificate:
openssl x509 -in ./certs/access-cert.pem -text -noout
Configure the connector to load the certificate and key by setting the file paths in the connector's environment variables:
CONNECTOR_CERT_PATH—path to the PEM-encoded X.509 certificate fileCONNECTOR_KEY_PATH—path to the PEM-encoded private key file
For example, if you placed the files in ./certs/:
export CONNECTOR_CERT_PATH=./certs/access-cert.pem
export CONNECTOR_KEY_PATH=./certs/access-key.pem
The connector reads these files at startup.
Step 2: Configure production certificates
For production, obtain an X.509 access certificate from a CA or your member state's registrar.
Obtain the certificate
- Generate a Certificate Signing Request (CSR) using the connector's key pair or your own EC P-256 key. The HAIP profile requires ES256, so the key must use the P-256 curve.
- Submit the CSR to your CA or member state registrar.
- Receive the signed X.509 certificate in PEM format.
Load certificates from Kubernetes secrets
Store the certificate and private key as a Kubernetes secret:
kubectl create secret tls connector-access-cert \
--cert=./certs/access-cert.pem \
--key=./certs/access-key.pem \
-n your-namespace
Mount the secret as a volume in the connector's pod and set the environment variables to point to the mounted paths:
spec:
containers:
- name: connector
env:
- name: CONNECTOR_CERT_PATH
value: /var/secrets/x509/tls.crt
- name: CONNECTOR_KEY_PATH
value: /var/secrets/x509/tls.key
volumeMounts:
- name: x509-certs
mountPath: /var/secrets/x509
readOnly: true
volumes:
- name: x509-certs
secret:
secretName: connector-access-cert
Rotate certificates
When a certificate approaches expiration:
- Obtain a new certificate from your CA or registrar.
- Update the Kubernetes secret with the new certificate and key.
- Restart the connector pod to load the new certificate.
Plan certificate rotation before expiration to avoid service interruption. Wallets reject requests signed with expired certificates.
Testing
- Self-signed certificate generates with
openssland the output files are valid PEM - Connector starts and loads the certificate from the configured path
- Wallet accepts the connector's authorization request (in test environments with trust list overrides)
- Production certificate is recognized by wallets against the member state trust list
Troubleshooting
Connector fails to start with certificate errors
Verify that the certificate and key files are in PEM format and that the key matches the certificate. Run openssl x509 -in cert.pem -noout -text to inspect the certificate and openssl ec -in key.pem -noout to verify the private key is a valid EC key.
Wallet rejects the authorization request
The wallet validates your certificate against the trust list of the relevant jurisdiction. In development, configure the wallet or test environment to trust your self-signed certificate. In production, verify that your CA-issued certificate is included in the member state's trust list.
Certificate expiration
Monitor certificate expiration dates and rotate before they expire. Use openssl x509 -in cert.pem -noout -enddate to check the expiration date.
Next steps
- Get ready for production—complete production readiness checklist
- Getting started—create your first presentation request
Further reading
- Certificates in EUDI—how certificates establish trust in the EUDI ecosystem
- Trust establishment—how wallets verify Relying Party identity
- Connector architecture—system components and security model