# Standards and conformance

> Every specification IXO Credentials uses, with its version, status and link, exactly what IXO implements from each, where IXO is stricter or narrower, and how IXO Credentials compares with the EU Digital Identity (EUDI) Wallet framework.

This page lists each specification and protocol IXO Credentials builds on, the version it implements, and what it does and does not use from each. Read it to decide whether a wallet, issuer or verifier from outside IXO can work with IXO Credentials, or to check a claim about the system. IXO implements a **profile** of each standard (the IXO Credential Profile v1): one way of doing each thing, applied the same way by every IXO issuer, verifier and wallet.

<Info>
  Versions and statuses were checked against the official sources (IETF Datatracker, the RFC Editor, openid.net, w3.org and the EUDI Wallet repository) on 9 November 2026. The conformance statements come from an independent standards review of the code on 5 November 2026, updated row by row after two rounds of fixes. IXO Credentials makes no other conformance claim.
</Info>

## Summary

| Specification | Version and status | What IXO Credentials uses |
| --- | --- | --- |
| [Selective Disclosure for JWTs (SD-JWT)](https://www.rfc-editor.org/rfc/rfc9901) | RFC 9901, November 2025, Proposed Standard | Compact serialization, disclosures, decoy digests, the Key Binding JWT |
| [SD-JWT-based Verifiable Digital Credentials (SD-JWT VC)](https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/) | Internet-Draft. Implemented against `draft-ietf-oauth-sd-jwt-vc-23`; the current version is `-26` (November 2026), in IESG evaluation | Format `dc+sd-jwt`, the registered claims, key binding through `cnf.jwk`, issuer keys from a DID |
| [OpenID for Verifiable Credential Issuance (OpenID4VCI)](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html) | 1.0, Final, 16 September 2025 | Pre-authorized code flow, credential offer by reference, nonce endpoint, `jwt` key proof, notification endpoint |
| [OpenID for Verifiable Presentations (OpenID4VP)](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html) | 1.0, Final, 9 July 2025 | Signed request object by reference, client identifier prefix `decentralized_identifier`, a DCQL subset, `direct_post.jwt` |
| [Token Status List (TSL)](https://datatracker.ietf.org/doc/draft-ietf-oauth-status-list/) | Internet-Draft `draft-ietf-oauth-status-list-21` (June 2026), approved and in the RFC Editor queue | JWT status list tokens, `status.status_list` in credentials, valid and invalid values |
| [Decentralized Identifiers (DIDs) v1.0](https://www.w3.org/TR/did-1.0/) | W3C Recommendation, 19 July 2022 | DID syntax, DID documents, `authentication` and `assertionMethod` |
| [did:web Method Specification](https://w3c-ccg.github.io/did-method-web/) | W3C Credentials Community Group draft (not a W3C standard) | Identifiers and keys of services |
| [The did:ixo DID Method](https://github.com/ixofoundation/ixo-did-method/blob/main/README.md) | IXO's method, registered in the [W3C DID method registry](https://www.w3.org/TR/did-extensions-methods/) | Identifiers and keys of people and entities, resolved through IXO Blocksync |
| [UCAN](https://github.com/ucan-wg/spec) | Token format 0.9.1, through `@ixo/ucan` 2.3.0 (built on [ucanto](https://github.com/storacha/ucanto)); [UCAN revocation](https://github.com/ucan-wg/revocation) | Authentication at the Credentials worker; offer consents and standing consents |
| JOSE: [JWS (RFC 7515)](https://www.rfc-editor.org/rfc/rfc7515), [JWE (RFC 7516)](https://www.rfc-editor.org/rfc/rfc7516), [JWK (RFC 7517)](https://www.rfc-editor.org/rfc/rfc7517), [JWA (RFC 7518)](https://www.rfc-editor.org/rfc/rfc7518), [JWT (RFC 7519)](https://www.rfc-editor.org/rfc/rfc7519), [RFC 7800](https://www.rfc-editor.org/rfc/rfc7800), [RFC 8037](https://www.rfc-editor.org/rfc/rfc8037), [RFC 9864](https://www.rfc-editor.org/rfc/rfc9864) | Proposed Standards | Ed25519 signatures (`EdDSA`, `Ed25519`), `ECDH-ES` on P-256 with `A128GCM` or `A256GCM`, `cnf` |
| OAuth: [RFC 8414](https://www.rfc-editor.org/rfc/rfc8414), [RFC 9101](https://www.rfc-editor.org/rfc/rfc9101), [RFC 9396](https://www.rfc-editor.org/rfc/rfc9396) | Proposed Standards | Authorization server metadata, JWT-secured request objects, `authorization_details` of type `openid_credential` |

Two of the credential standards are still drafts: SD-JWT VC and Token Status List. The field names IXO relies on (`vct`, `cnf`, `status`, `status_list`, `statuslist+jwt`, `ttl`) have not changed across recent drafts. The SD-JWT VC changes from `-24` to `-26` answer IESG review comments (clarifications of issuer key discovery, an update to RFC 7800 for `cnf`, and editorial fixes); the code has not been re-checked against `-26` line by line. A change in a later draft or in the final RFC would be handled as a new profile version.

## How the standards fit together

```mermaid
flowchart LR
  subgraph Issuance["OpenID4VCI 1.0"]
    O["Offer by reference"] --> T["Token (pre-authorized code)"] --> N["Nonce"] --> C["Credential (jwt key proof)"]
  end
  subgraph Credential["SD-JWT VC on RFC 9901"]
    SD["dc+sd-jwt, Ed25519, cnf.jwk, status"]
  end
  subgraph Presentation["OpenID4VP 1.0"]
    R["Signed request object (DCQL)"] --> P["SD-JWT + KB-JWT, direct_post.jwt"]
  end
  C --> SD --> P
  SD -. "status.status_list" .-> TSL["Token Status List"]
  SD -. "iss, kid" .-> DID["did:ixo / did:web"]
  R -. "client_id = decentralized_identifier:DID" .-> DID
```

## SD-JWT (RFC 9901)

**Uses:** the compact serialization; object-property disclosures (§4.2.1) and, when verifying, nested object and array-element disclosures processed recursively (§4.2.4, §4.2.6, §7.1); `_sd_alg: sha-256`; decoy digests (§4.2.5); the Key Binding JWT with `typ: kb+jwt`, `aud`, `nonce`, `iat` and `sd_hash` (§4.3); verification by the holder (§7.2, the kit's `verifyIssuedCredential`) and by the verifier (§7.3, the kit's `verifyPresentation`).

**Does not use:** the JWS JSON serialization (§8). Presentations without key binding are refused. IXO issuers issue flat credentials (every disclosure is a top-level claim), and a verifier can ask only for top-level claims.

## SD-JWT VC

**Uses:** `typ: dc+sd-jwt`; the registered claims `iss`, `sub`, `iat`, `nbf`, `exp`, `cnf`, `vct` and `status`; key binding through `cnf.jwk`; the verification rules.

**Issuer key discovery:** SD-JWT VC defines two mechanisms (an HTTPS `iss` with JWT VC Issuer Metadata, or an `x5c` certificate chain) and lets an ecosystem define others, provided an attacker cannot choose the mechanism. Under the IXO profile `iss` is always a DID (`did:ixo` or `did:web`), and the signing key is the one the JOSE `kid` names under `assertionMethod` on that DID document. That is the only mechanism.

**Does not use:** JWT VC Issuer Metadata, `x5c`, type metadata retrieval by verifiers, `vct#integrity` and `aka_vcts`. Verifiers match `vct` as an exact string and never fetch it.

**Profile rules for any issuer:** the kit's verifier requires `sub` and `exp`, and refuses `iss`, `nbf`, `exp`, `cnf`, `vct`, `vct#integrity`, `aka_vcts` and `status` as disclosures. It still accepts the older `typ: vc+sd-jwt`.

**Consequence:** a verifier outside IXO can check an IXO credential only if it resolves `did:ixo` or `did:web` and follows this key rule.

## OpenID4VCI 1.0

**Uses:**

- the pre-authorized code flow (§3.5) and nothing else;
- credential offers by reference (§4.1.3): the offer inbox holds a `credential_offer_uri`, and the issuer mints a fresh pre-authorized code on every fetch (5 minutes, single use at IXO issuers). Offers by value (§4.1.1) are accepted for other issuers;
- the token endpoint with anonymous pre-authorized access (§6), including `authorization_details` of type `openid_credential`, echoed with `credential_identifiers`;
- OAuth authorization server metadata (RFC 8414) with `pre-authorized_grant_anonymous_access_supported: true` and `token_endpoint_auth_methods_supported: ["none"]`;
- the nonce endpoint (§7) and the `jwt` key proof with `typ: openid4vci-proof+jwt` and a DID URL in `kid` (Appendix F.1);
- the credential endpoint with exactly one proof (§8.2) and the `credentials` / `notification_id` response (§8.3);
- the notification endpoint (§11);
- issuer metadata at `/.well-known/openid-credential-issuer/<path>` (§12.2), listing `EdDSA` and `Ed25519`;
- the SD-JWT VC format profile, `dc+sd-jwt` (Appendix A.3).

**IXO additions, invisible to the protocol:** offers reach the wallet through the offer inbox, addressed to a DID, instead of a QR code (the offer object is standard); and **subject binding**: the issuer refuses a proof whose key is not on the subject's own DID document, which answers the replay risk of pre-authorized codes.

**Does not use:** the authorization code flow (§3.4), transaction codes (`tx_code`), batch issuance (§3.3.2), deferred issuance at IXO issuers (the kit wallet can poll a deferred endpoint; the Auth Hub does not), encrypted credential requests and responses (§10), signed issuer metadata (§12.2.3), key attestations (Appendix D), and `jwk` or `x5c` key proofs.

## OpenID4VP 1.0

**Uses:**

- a signed request object, `typ: oauth-authz-req+jwt` (§5, RFC 9101), passed by reference through `request_uri` with the default GET method;
- the `decentralized_identifier` client identifier prefix (§5.9.3): the request is signed by a key on the verifier's DID document, named by `kid`. IXO requires that key under `authentication` or `assertionMethod`;
- `response_type: vp_token`, `nonce` and `state`;
- the Digital Credentials Query Language (DCQL, §6), restricted to a subset: one-segment claim paths, format `dc+sd-jwt`, value matching on `iss` to name accepted issuers. `credential_sets`, `claim_sets`, `trusted_authorities` and nested paths are refused; unknown members are ignored and `multiple: true` is answered with one presentation;
- the `vp_token` object keyed by credential query id (§8.1);
- `direct_post.jwt` responses (§8.3), encrypted with `ECDH-ES` to a P-256 key in `client_metadata.jwks`, with `A128GCM` (the default) or `A256GCM`. Plain `direct_post` only in local development;
- wallet error responses (§8.5), sent only after the person decided;
- the request as a link, `openid4vp://?client_id=…&request_uri=…`, for wallets other than the Auth Hub;
- replay protection through the KB-JWT's `aud` (the full client identifier) and `nonce`;
- `vp_formats_supported` with `Ed25519` and `EdDSA`.

**IXO addition:** requests reach the Auth Hub through the presentation broker, addressed to a DID. Other wallets can use the standard link.

**Does not use:** `scope`-based requests, `request_uri_method: post`, `transaction_data`, `verifier_info`, verifier attestations, the Digital Credentials API (Appendix A), other credential formats, client identifier prefixes other than `decentralized_identifier`, and the same-device redirect with a response code. IXO flows are cross-device; a verifier binds each answer to the person it asked.

## Token Status List

**Uses:** the status list in JSON with a compressed byte array; the status list token as a JWT, `typ: statuslist+jwt`, with `sub`, `iat`, `exp`, `ttl` and `status_list`; the `status.status_list` claim with `uri` and `idx`; the values `VALID` (0) and `INVALID` (1); retrieval over HTTP as `application/statuslist+jwt` with CORS for everyone; the validation rules, including that the token's `sub` equals the credential's `uri` and that an index outside the list is a refusal.

**IXO choice:** issuers upload their signed tokens to the Credentials worker's registry, and credentials point there. The standard only requires that the `uri` resolves. Clients never follow redirects when fetching a list (the standard says they should); this is a security rule of the kit.

**Does not use:** the CWT format, status list aggregation, historical resolution, and status types other than valid and invalid (any non-zero value is reported as `revoked`).

## DIDs: DID v1.0, did:web and did:ixo

- **DID v1.0** defines the identifiers and documents. IXO reads `verificationMethod`, `authentication` and `assertionMethod` with Ed25519 keys. DID v1.1 is a W3C Candidate Recommendation (March 2026); IXO has not moved to it.
- **did:web** identifies services. `did:web:HOST` resolves to `https://HOST/.well-known/did.json`, `did:web:HOST:A:B` to `https://HOST/A/B/did.json`, a port written `%3A`. Only the canonical spelling is accepted (lower-case host, punycode for international names, no IP address), so one DID has one spelling. Every DID is its own sender, exactly as written; there is no grouping by domain.
- **did:ixo** identifies people (`did:ixo:ixo1…`) and entities (`did:ixo:entity:…`). Documents live on the IXO chain and are read through IXO Blocksync. Other DID methods, `did:key` included, are refused.

## UCAN

Every call to the Credentials worker carries a UCAN invocation: `Authorization: Bearer` with a base64 CAR, addressed to the worker's `did:web`, valid at most 300 seconds, used once, and signed at every link by a `did:ixo` or `did:web`. IXO adds one rule on top of UCAN: the invocation carries the **request-binding fact** `{ "method": "<HTTP method>", "path": "<full path>" }`, so a token works for exactly one request. Delegations can only narrow what they were given, and revoked delegations are refused through the UCAN store. The person's offer consent (`credentials/offer`) and standing consents (`credentials/present`) are UCAN delegations too.

UCAN is IXO's choice for service authentication; it is not part of any credential standard, and a party that ignores the worker never sees it.

## JOSE algorithms in use

| Use | Algorithm |
| --- | --- |
| Credential, KB-JWT, request object, key proof, status list token | JWS with Ed25519. IXO signs with `alg: EdDSA` (RFC 8037) and accepts `EdDSA` and `Ed25519` (RFC 9864, which deprecates `EdDSA` in favour of the fully specified `Ed25519`) |
| Presentation response (`direct_post.jwt`) | JWE `alg: ECDH-ES` on P-256, `enc: A128GCM` (default) or `A256GCM` |
| Holder key binding | `cnf.jwk` (RFC 7800) with an Ed25519 public key (`OKP`) |
| Webhook from the worker to the Hub | Ed25519 signature with the worker's `did:web` key (`x-ixo-signature`) |

ECDSA (`ES256`) and other key types are not supported for signatures.

## Where IXO is stricter than the standards

- Key binding is mandatory on every presentation.
- Status is mandatory, and verifiers fail closed when a list cannot be read.
- Issuers must check that the proof key belongs to the subject.
- There is one way to find an issuer's key.
- Request objects deposited at the worker must carry `exp` and live at most 24 hours.
- Outbound fetches never follow redirects and refuse private addresses.

## Conformance matrix

The standards review checked 52 areas of the five credential standards against the code: **26 implemented**, **11 profile choices** (implemented, narrowed on purpose; a counterpart outside the subset gets a clear error) and **15 not supported**. The not supported areas are listed in the "Does not use" lines above.

Independent implementations agreed with IXO's own output in that review: `jose` 6.2.13 verified the request object, the key proof and the status list token and decrypted the response JWE; `@sd-jwt/sd-jwt-vc` 0.23.0 accepted a Self-minted credential and a kit-built presentation with key binding; the kit decoded both Token Status List test vectors. These probes ran before the fix rounds and have not been re-run since.

## EU Digital Identity Wallet

The European Digital Identity (EUDI) Wallet is the wallet framework of the EU Digital Identity Regulation. Its technical rules are in the **EUDI Wallet Architecture and Reference Framework (ARF)**; the current version is [ARF 3.0.0](https://github.com/eu-digital-identity-wallet/eudi-doc-architecture-and-reference-framework/releases/tag/v3.0.0) (23 July 2026, readable at [eudi.dev](https://eudi.dev)). For remote flows the ARF uses the [OpenID4VC High Assurance Interoperability Profile (HAIP) 1.0](https://openid.net/specs/openid4vc-high-assurance-interoperability-profile-1_0-final.html), Final since 24 December 2025.

**IXO Credentials is built on the same core standards as the EUDI Wallet: SD-JWT VC, OpenID4VCI, OpenID4VP with DCQL, and Token Status List. It is aligned with, not certified against, the ARF.** It is not an EUDI Wallet, it does not claim conformance to the ARF or to HAIP, and an EUDI Wallet or an EUDI relying party cannot be assumed to work with it.

The differences:

| Area | EUDI Wallet (ARF 3.0.0 with HAIP 1.0) | IXO Credentials |
| --- | --- | --- |
| Who issuers and verifiers are | X.509 certificates, chained to trust anchors in Trusted Lists and Lists of Trusted Entities; relying parties are registered | DIDs (`did:ixo`, `did:web`); each verifier chooses the issuers it accepts; the catalog is self-declared and is not a trust list |
| Issuer key discovery | `x5c` certificate chain in the credential | The DID in `iss` and the `kid` under `assertionMethod` |
| Verifier identity in requests | Client identifier prefix `x509_hash` for signed requests | `decentralized_identifier` only |
| What is issued | Person Identification Data (PID) and qualified or other attestations from regulated providers | No PID and no qualified attestations. IXO types such as `IdentityLevel1` (not live yet) use their own claim names, for example `birth_date` where the PID rulebook uses `birthdate` |
| The holder key | Held in a certified Wallet Secure Cryptographic Device (WSCD), proven by key attestations and a wallet attestation | For Auth Hub users the key is held by the Hub (custodial); no WSCD, no key attestation, no wallet attestation. A self-sovereign wallet holds its own key |
| Signature algorithms | ECDSA with P-256 (`ES256`) required | Ed25519 only (`EdDSA` / `Ed25519`) |
| Credential formats | SD-JWT VC and ISO/IEC 18013-5 mdoc | SD-JWT VC only; no mdoc |
| Issuance flow | Authorization code flow with PKCE, PAR, DPoP and wallet attestation | Pre-authorized code flow only, without client authentication; subject binding at the issuer instead |
| Presentation channels | Same-device redirect flow, the Digital Credentials API, and proximity presentation (ISO/IEC 18013-5) | Cross-device remote flow only, through the presentation broker or an `openid4vp://` link |
| DCQL | Full DCQL, including `trusted_authorities` | A subset; `trusted_authorities`, `credential_sets` and `claim_sets` are refused |
| Transaction data | Supported (`transaction_data`) | Refused |
| Unlinkability | Once-only (batch-issued) attestations so relying parties cannot link presentations | One credential per person, with the same `sub` and holder key at every service; presentations are linkable |
| Certification | Wallet Solutions are certified under the EU framework | Not certified |

Because the core formats and protocols are the same, moving towards the ARF is a matter of the items in this table (certificates and trust lists, `ES256`, the authorization code flow, attestations, and the missing presentation channels), not of a new credential format.

## Related pages

- [IXO Credentials overview](/guides/dev/credentials/overview)
- [Request proof](/guides/dev/credentials/request-proof)
- [Issue a credential](/guides/dev/credentials/issue-a-credential)
- [Credentials API reference](/guides/dev/credentials/api-reference)
