Skip to main content

Configure X.509 trust anchor verification

This guide shows you how to configure the Truvity EUDIW Connector to verify that credential issuer certificate chains end at a known trust anchor and that no certificate in the chain has been revoked via a Certificate Revocation List (CRL). In HAIP-compliant ecosystems, SD-JWT VC credentials always include an x5c certificate chain for issuer key resolution. This feature adds trust anchor verification and CRL checking on top of the chain-internal validation that the connector already performs. It is off by default.

Prerequisites
  • A running connector instance, or one you are preparing to deploy
  • Trust anchor certificates obtained from your federation operator in DER or PEM format
Manual provisioning only

Trust anchors are configured statically via environment variables. You must obtain trust anchor certificates from your federation operator and update the configuration manually when they change.

Overview

SD-JWT VC credentials in HAIP-compliant ecosystems always include an x5c certificate chain for issuer key resolution. The connector already validates this chain internally (signatures, validity, extensions). This guide configures the additional step: verifying that the chain terminates at a trust anchor published by your federation, and checking each certificate's revocation status against CRLs.

This guide covers obtaining and encoding trust anchor certificates and configuring the connector. To confirm the feature is working end-to-end, you need a real credential with an x5c chain from a trusted issuer—the testing section describes what to look for in the callback payload when that credential is presented.

Step 1: Obtain trust anchor certificates

Contact your federation operator to obtain the trust anchor certificates for the credential issuers you want to verify. In the EUDI ecosystem, these are typically root CA certificates or federation trust anchor certificates published in a List of Trusted Entities (LoTE). Your federation operator should be able to provide them as PEM or DER files.

If your federation does not yet distribute trust anchor certificates, you cannot use this feature.

Step 2: Encode the certificates

The connector's X509_TRUST_ANCHORS variable expects certificates in base64-encoded DER format. DER is the binary encoding of an X.509 certificate—as opposed to PEM, which is the same data wrapped in -----BEGIN CERTIFICATE----- / -----END CERTIFICATE----- headers and base64-encoded for text transport. You need to strip the PEM headers and re-encode the raw binary as a single base64 string with no line breaks.

If your certificate is already in DER format (a .der or .cer file), skip the first part of the command:

# From PEM: convert to DER, then base64-encode (no line breaks)
openssl x509 -in trust-anchor.pem -outform DER | base64 | tr -d '\n'

# From DER: base64-encode directly
base64 -i trust-anchor.der | tr -d '\n'

The output is a single line of base64 characters with no whitespace. That is the value you set in X509_TRUST_ANCHORS.

If you have multiple trust anchors, encode each certificate separately and join the values with commas:

<base64-cert-1>,<base64-cert-2>

Step 3: Configure the connector

Set the following environment variables on your connector instance:

VariableRequiredDefaultDescription
X509_VERIFY_TRUST_ANCHORYesfalseEnable trust anchor resolution and CRL checking. Set to true to activate.
X509_TRUST_ANCHORSYes (when verification is enabled)""Comma-separated base64-encoded DER trust anchor certificates.
X509_CRL_TIMEOUT_SECONDSNo10HTTP timeout in seconds for CRL fetch requests. Only set this if you need to override the default.

Example configuration:

export X509_VERIFY_TRUST_ANCHOR=true
export X509_TRUST_ANCHORS="<base64-encoded-DER-cert-1>,<base64-encoded-DER-cert-2>"
export X509_CRL_TIMEOUT_SECONDS=10

Restart the connector after setting these variables.

What to expect in the callback

You can only confirm this feature is working by presenting a real credential that includes an x5c certificate chain from an issuer whose trust anchor you have configured. The connector's test wallet does not produce credentials with x5c chains, so you cannot verify this feature in isolation using the standard development setup.

When a credential with a valid x5c chain is presented and trust anchor verification is enabled, the FULFILLED callback payload includes:

{
"status": "FULFILLED",
"state": "abc123",
"credentials": {
"pid_kyc": [{
"signatureIsValid": true,
"supportRevocation": false,
"supportTrustAnchor": true,
"isTrusted": true,
"isCertificateRevoked": false,
"claims": { }
}]
}
}
  • supportTrustAnchor: true—the credential was signed with an x5c certificate chain
  • isTrusted: true—the chain terminated at a configured trust anchor and the last certificate's signature was verified
  • isCertificateRevoked: false—no certificate in the chain was found on a CRL

If X509_VERIFY_TRUST_ANCHOR is false (the default), isTrusted and isCertificateRevoked are both false even when supportTrustAnchor is true. The fields are present but trust and revocation checking was skipped.

Troubleshooting

isTrusted: false—trust anchor not matching

The chain's last certificate did not match any configured trust anchor. The connector first tries Authority Key Identifier (AKI) to Subject Key Identifier (SKI) matching, then falls back to Issuer Distinguished Name matching with signature verification. Verify that the correct trust anchor certificate is encoded in X509_TRUST_ANCHORS. Check that the certificate is in DER format before base64-encoding—encoding a PEM file directly (without the openssl x509 -outform DER conversion step) produces an invalid value.

CRL fetch timeout

The connector could not fetch the CRL within the configured timeout. When a CRL fetch fails, the connector logs a warning and tries the next CRL Distribution Point listed in the certificate. If no valid CRL can be obtained from any distribution point, the certificate is treated as not revoked (fail-open for CRL specifically). Trust anchor resolution itself is fail-closed: if the chain does not end at a configured trust anchor, isTrusted is false. Increase X509_CRL_TIMEOUT_SECONDS if CRL endpoints are slow, or check network connectivity from the connector to the CRL distribution point URLs.

Self-signed certificates in the chain

Self-signed certificates must not appear in the x5c chain. The trust anchor (root CA) is not included in the chain—it is configured separately via X509_TRUST_ANCHORS. If you see trust failures, verify the issuer is not including the root CA in the x5c header.

Next steps

Further reading