Trust Model
A verifier has to answer one question: did this credential really come from an issuer I am willing to believe?
It answers it from the credential itself. Credentials are signed, and the signature carries the issuer's X.509
certificate chain in the JOSE x5c header. The verifier reads the chain out of the credential, so it needs no
network lookup and no contact with the issuer at verification time.
How an issuer is resolved
When the verifier receives a presentation, it parses the certificate chain in the credential's x5c header and
checks the issuer's signature against the public key of the leaf certificate.
Without an x5c header, the verifier cannot resolve the issuer and verification fails.
What gets validated
A signature that checks out only tells you the credential was signed by whoever holds that certificate's private key. It does not tell you that you recognize them. Establishing that second thing is what trust anchors are for.
Every credential gets
PKIX path validation: the verifier builds a path from the presented leaf
certificate up to one of the roots in
issuerTrustAnchors and rejects the credential if no valid path
exists. This applies to SD-JWT and mdoc alike.
Anchors are deployment-wide: they decide which issuers this verifier accepts at all. A single
verification query can narrow that further
with a trusted_authorities entry, accepting only credentials issued under a named certificate authority. That is
a filter on top of the anchors, not a substitute for them.
issuerTrustAnchors is a required setting, so this step always runs. If the directory holds no anchors, no path
can be built and every credential is rejected.
One limit applies: chains are limited to 10 certificates, and a longer x5c
chain is rejected before validation begins.
Validity periods are checked, so an expired certificate anywhere in the path fails it.
The verifier's own identity
Trust runs in both directions. Before a wallet hands over a presentation, it may want to know which verifier is asking.
The verifier signs its authorization requests with its own key and certificate, and derives its OID4VP client_id
from that certificate:
client_id = "x509_hash:" + base64url( sha256( DER-encoded leaf certificate ) )
Deriving the identifier this way is what makes the check possible at all: because the client_id is a hash of
the certificate, a verifier cannot claim an identity it does not hold the key for. A wallet that wants to limit
which verifiers it will answer therefore can — it validates the certificate chain in the request's x5c header
against its own trusted roots, verifies the request signature, and confirms that the hash in client_id matches
the certificate it just validated.
Whether a wallet does so is its own decision. OID4VP leaves it to the wallet, so this is a capability wallets may use rather than a step a verifier can require, and wallets differ. The Partisia ID Wallet accepts any verifier; a wallet built for a closed ecosystem may instead refuse every verifier outside it.
So a verifier presenting a self-signed certificate is accepted by wallets that do not check, and by wallets configured to accept that certificate — and refused by the rest. A self-signed pair is what the quickstart generates, and it is fine for local testing. For a deployment facing wallets you do not operate, your certificate needs to chain to a root they already trust. See Going to production.
Configuring your own keys and certificates
Both services take the same signing block: a private key file and an ordered, leaf-first list of certificate
files, which become the x5c header they emit.
"signing": {
"keyFile": "conf/signing-key/verifier-localhost.key",
"certificateFiles": ["conf/signing-key/verifier-localhost.pem"]
}
See Signing certificates for generating these and for what changes when you move off self-signed certificates.
What's Next
- Signing certificates: Generate and configure your own pair.
- Issuer trust anchors: Decide which issuers your verifier accepts.
- OID4VP presentation protocol: The wire-level detail of the request signing and validation described above.