Skip to main content
Version: 0.7

Verifiable credentials

A verifiable credential is a set of claims about a subject, such as a name or a date of birth, signed by the party that makes the claims. Anyone who receives it can check that the claims came from that party and weren't changed. This page explains the model and the terms the rest of the docs use, and links to the section that covers each part.

Issuer, holder and verifier​

Three roles take part:

  • The issuer signs a credential and gives it to the holder. A government issuing an ID or a university issuing a diploma are issuers.
  • The holder receives the credential, stores it and decides when to share it.
  • The verifier asks the holder for credentials and checks them.

The issuer doesn't take part when the holder presents a credential. The verifier only needs the issuer's public key, which it gets from a DID or an X.509 certificate (see Trust).

These docs use holder for the role, as the Credo APIs do (agent.openid4vc.holder), and wallet for the application that takes the holder role for a person, such as a mobile wallet app.

A Credo agent can take any of these roles, and one agent can take more than one. Issuers and verifiers usually run on a server with Node.js. A holder usually runs in a mobile wallet built with React Native, but it can also be a cloud wallet on a server.

Credentials and presentations​

The issuer creates a credential. When the holder shares it, they create a presentation: the credential, or the parts of it the verifier asked for, plus proof that the holder is the one it was issued to. A presentation is bound to the verifier's request, usually through a nonce, so it can't be replayed to another verifier.

Exchange protocols and credential formats​

Credo separates two things:

  • An exchange protocol defines how the parties talk: how an issuer offers a credential, how the holder requests it, how a verifier asks for a presentation. Credo supports OpenID4VC (OpenID4VCI for issuance, OpenID4VP for presentation), DIDComm (Issue Credential and Present Proof) and the ISO mdoc presentation protocols (in person over BLE or NFC, and online through the Digital Credentials API).
  • A credential format defines what a credential looks like and how it's signed: SD-JWT VC, mdoc, W3C Verifiable Credentials and AnonCreds.

Several formats work over more than one protocol, and you can sign, store and verify a credential without any protocol. That's why the docs are split the same way: Protocols covers the flows, Credential formats covers what you can do with a format on its own, and pages such as SD-JWT VC with OpenID4VC combine the two.

FormatOpenID4VCDIDCommISO mdoc
SD-JWT VCYesNoNo
mdocYesNoYes
W3C VCYesYesNo
AnonCredsNoYesNo

Not every W3C data model and signature type works over both OpenID4VC and DIDComm. See Supported standards for the full matrix. Getting started recommends a protocol and format to start with.

Key binding​

Most credentials are bound to a key that the holder controls. The issuer puts the holder's public key (or a DID that resolves to it) in the credential, and the holder signs each presentation with the private key. Someone who copies the credential can't present it without that key. AnonCreds binds credentials to a link secret instead of a key.

In Credo the holder's keys live in a key management service (KMS). See Key management.

Selective disclosure​

Selective disclosure lets the holder share some claims of a credential and keep the rest private:

  • SD-JWT VC and mdoc: the issuer signs a salted hash of each claim, and the holder reveals only the claims the verifier asks for.
  • AnonCreds: the holder creates a zero-knowledge proof, which can also prove a predicate, such as being over 18, without revealing the date of birth.
  • W3C VCs: those secured with SD-JWT (data model 2.0) work like SD-JWT VC. Those signed as a plain JWT or with a Linked Data proof are always shared as a whole.

Revocation and status​

An issuer may need to revoke a credential, or suspend it for a while. With a status list, the issuer publishes a list with one entry per credential, and each credential points to its entry. The verifier fetches the list and checks the entry. Credo supports Token Status Lists for SD-JWT VC and mdoc. AnonCreds uses its own revocation registries, and the holder proves the credential isn't revoked as part of the presentation (see AnonCreds).

Trust​

A valid signature only proves who signed a credential. The verifier still has to decide whether it trusts that issuer. Credo identifies issuers in two ways:

  • DIDs: the issuer's key is published in a DID document, on a ledger, a web server, or in the DID itself. See DIDs and DIDComm.
  • X.509 certificates: the issuer signs with a certificate that chains up to a root certificate the verifier trusts. mdoc always works this way, and SD-JWT VC often does.

You tell Credo which issuers to trust per verification, or with a callback on the agent. See Trusted issuers.