Skip to main content

OpenAC Implementation Profile

Draft

This page reflects the working draft of the OpenAC Profile (May 2026). Sections 6–9 are outlined with content targets; normative byte-level detail will be added as the profile is finalized. The profile is being developed as a contribution to ETSI TS 119 476-2.

1. Introduction and profile scope

1.1 Subject of this profile

This document specifies the OpenAC Profile — an implementation-oriented profile for proof-based presentations over existing issuer-signed credentials.

OpenAC is designed for digital identity systems where credentials are already issued and signed by existing issuers, stored by a holder wallet, and later used to produce disclosures or derived proofs for a verifier. The OpenAC paper describes this as a design for anonymous credentials from existing digital identity systems, without requiring changes to the current issuance flow.

This profile defines the OpenAC layer needed for interoperable wallet and verifier implementations. It specifies:

  • how a wallet prepares credential-derived state;
  • how it produces an OpenAC response;
  • how a verifier checks the OpenAC proof carried in that response;
  • what the verifier may conclude after accepting an OpenAC response.

This profile does not define a new credential format, a new issuance flow, or a general-purpose presentation protocol.

1.2 Target environment

The primary target environment is the EUDI Wallet ecosystem. The EUDI ARF describes the Wallet ecosystem as a secure, User-controlled environment in which Users manage and present PID and attestations to Relying Parties (ARF 2.4.0).

OpenAC is not a replacement for the EUDI Wallet transaction. The Wallet Unit, Relying Party Instance, credential issuance, trust lists, status checks, and user-approval flow remain supplied by the EUDI environment. OpenAC adds a proof layer over existing issuer-signed credentials.

1.3 Profile boundary and acceptance

OpenAC acceptance is the verifier's proof-layer result. It means that the OpenAC response satisfies this profile: the proof verifies, the response is bound to the request, freshness checks pass, and the proven statement has the meaning assigned by the applicable statement definition.

Final relying-party acceptance is the deployment decision. It also depends on checks outside OpenAC: issuer trust, status or revocation, relying-party authentication, user approval, and service policy.

A valid OpenAC proof is therefore necessary for OpenAC acceptance, but not by itself a final relying-party acceptance decision.

1.4 Out of scope

This profile does not define: issuer-side issuance; credential-format syntax; general wallet UI behavior; relying party registration or authentication infrastructure; trusted-list governance; revocation or status infrastructure (unless explicitly included in an OpenAC statement type); transport and network-layer protections; service-side authorization policy; generic ZKP proof-system design beyond the OpenAC mechanisms selected by this profile; or capabilities not declared by this profile.


2. Conventions, terminology, and references

2.1 Conventions

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, NOT RECOMMENDED, MAY, and OPTIONAL are to be interpreted as described in BCP 14 / RFC 2119 and RFC 8174 when they appear in all capitals.

Sections marked as examples, notes, or implementation guidance are informative unless stated otherwise.

2.2 Terminology

TermDefinition
UserPerson controlling the Wallet Unit and approving presentation. (ARF §3.2)
Wallet UnitThe EUDI deployment role for OpenAC proof generation. (ARF §4.3.2)
Relying PartyEntity requesting attributes from a Wallet Unit. (ARF §3.11.1)
Relying Party InstanceTechnical system used by a Relying Party to interact with Wallet Units. (ARF §3.11.2)
PIDPerson Identification Data. External credential input category; OpenAC does not redefine its format. (ARF §5.2.2)
attestationExternally issued credential material that may enter OpenAC through a credential binding. (ARF §5.2)
EAA / QEAA / PuB-EAAAttestation categories defined in ARF §5.2.3–5.2.5. Treated as external attestation categories by this profile.
presentation requestDeployment-level request sent by a Relying Party Instance to a Wallet Unit. (ARF §6.6.3.2)
presentation responseDeployment-level response returned by a Wallet Unit after approval. (ARF §6.6.3.5.8)
device bindingBinding to a device-held key. (ARF §6.6.3.8) Distinct from User binding in this profile.
User bindingBinding to a specific User. (ARF §6.6.3.9) Not inferred from device binding unless deployment rules support it.
selective disclosurePresenting a subset of attributes or derived information from one or more attestations.
predicate proofA verifiable computation over credential data where only the result is shared, not the underlying inputs.
PrepareThe credential-specific OpenAC phase: parses the credential, checks issuer signature, commits to messages. Independent of the claims proved during presentation; can be precomputed.
ShowThe request-specific OpenAC phase: binds to verifier nonce, evaluates predicates, links to the Prepare commitment. Online latency is dominated by Show.
Reblind / refreshRe-randomization step applied before Show. Breaks cross-session linkability by refreshing the hidden representation.
prepared stateWallet-local state produced by Prepare. Not sent to the verifier as a standalone artifact.
prepared-state poolThe stored collection of prepared states produced by offline Prepare and re-randomization.
prepare relationThe credential-specific relation: checks issuer-signature validity, parses the credential, verifies message hashes.
show relationThe request-specific relation proved during Show; linked to the prepare relation via Hyrax commitments.
witnessPrivate prover data used together with public input to prove that a relation is satisfied.
public inputData checked by the verifier when verifying the proof.
proving key / verifying keyProof-system keys used by the prover and verifier respectively.

2.3 Relationship to external specifications

SpecificationRole
OpenAC paperTechnical basis for this profile; not normative text.
ETSI TS 119 476-2Requirement reference; this profile is a contribution to that work programme.
EUDI ARF (incl. Annex 2)Requirement reference; defines the primary deployment context.
SD-JWT VC (draft-ietf-oauth-sd-jwt-vc)Binding reference for the SD-JWT VC credential family.
ISO/IEC 18013-5:2021Binding reference for the mdoc credential family.

3. Roles, system context, and trust boundary

3.1 Deployment roles

For this profile, only three role relationships matter at the OpenAC layer:

  • The wallet prepares credential-derived state and produces the OpenAC response. In EUDI, this is the Wallet Unit.
  • The relying-party side verifies the OpenAC response and combines the result with external checks. The Relying Party Instance is the technical endpoint; the Relying Party makes the final service decision.
  • The issuer or attestation provider does not participate in presentation-time OpenAC processing. It issues the credential whose data OpenAC later proves statements over.

3.2 System context

OpenAC begins after issuance. The credential has already been issued and stored by the wallet. OpenAC state is prepared from that credential, and later used to produce a response. This matches the OpenAC paper §1 design goal: use existing issuer-signed credentials without changing issuer workflows.

In a EUDI Wallet deployment, the surrounding presentation transaction remains the EUDI transaction. See ARF §4.3.3 (Wallet Unit interfaces) and ARF §4.4 (data presentation flows).

3.3 Trust boundary

OpenAC acceptance means: the proof verifies, the request binding holds, freshness passes, and the statement has the meaning defined by Section 8.

It does not establish that the issuer is trusted, that the relying party was authorized to request attributes, that the user approved the release, that the credential is still valid, or that service access must be granted. Those decisions belong to the surrounding deployment. See ARF §6.6.3.2, §6.6.3.5, §6.6.3.7, §6.6.3.8, §6.6.3.9.

3.4 Boundary rules

OpenAC does not replace the wallet, the Relying Party Instance, the issuer, the presentation protocol, or the trust infrastructure. Checks outside the OpenAC proof relation are not optional merely because they are external to OpenAC.


4. Architecture overview

4.1 EUDI Wallet presentation context

The following diagram shows the EUDI Wallet presentation context without the OpenAC proof layer, as a baseline:

Figure 1. Simplified EUDI Wallet presentation context (based on ARF; not a reproduction of an ARF figure).

4.2 OpenAC proof layer in the presentation flow

OpenAC changes the proof material generated by the wallet and checked by the relying-party side. It does not change issuance, relying-party authentication, user approval, transport, trust-list processing, or service policy.

Figure 2. OpenAC proof layer in the EUDI Wallet presentation context.

4.3 Prepare, Reblind, and Show

OpenAC separates credential-dependent proof work (Prepare) from request-dependent proof work (Show). The paper §3 describes this as a split between a prepare relation and a show relation.

Prepare starts after credential binding. For the SD-JWT path:

  1. Parse the SD-JWT into messages, salts, hashes, and issuer signature.
  2. Check that each hash corresponds to the related message and salt.
  3. Check that the issuer signature verifies under the issuer public key.
  4. Produce a Hyrax commitment to the message vector for later use by Show.

Prepare produces state for the wallet, not a response for the verifier.

Reblind is applied before Show. The wallet refreshes the prepared material. The paper describes storing a pool of re-randomized prepared states and re-randomizing the selected state again before running Show, so the hidden representation used in one presentation is not reused as a stable handle in another.

Show is bound to one request: it uses refreshed prepared state, the requested statement, freshness, and statement-specific binding inputs. Prepare handles credential validity; Show handles the verifier's current statement.

The verifier checks four architectural dependencies:

DependencyVerifier question
Credential bindingIs the proved material derived from a supported issuer-authenticated credential input?
Prepare–Show linkingDoes Show use the same credential-derived messages accepted by Prepare?
Request and freshness bindingIs the proof bound to this request and not reusable as a response to another request?
Statement semanticsDoes the proof establish the statement type requested under Section 8?

4.4 Architecture requirements

Conforming implementations MUST satisfy:

  1. An implementation MUST NOT require issuer-side issuance changes as a condition for OpenAC processing.
  2. A credential MUST enter OpenAC through a credential binding that identifies issuer-authenticated input.
  3. Prepare MUST operate on credential-bound input. It MUST NOT depend on a concrete presentation request, verifier nonce, or requested statement.
  4. Prepared state MUST remain wallet-local. It MUST NOT be sent to the verifier as a standalone presentation artifact.
  5. Before using prepared state for Show, the wallet MUST determine that the state is admissible for the requested statement type, credential binding, freshness requirements, and refresh requirements.
  6. The wallet MUST refresh prepared state before using it in a presentation. Reuse without required refresh is not conformant.
  7. Show MUST operate on refreshed prepared state and request-specific inputs.
  8. The verifier MUST NOT accept an OpenAC response unless the Show proof is linked to the corresponding Prepare output.
  9. The proof backend MUST NOT define statement meaning. Statement meaning is defined by Section 8.
  10. OpenAC acceptance MUST be treated as a proof-layer result. It MUST NOT be treated as final relying-party acceptance unless the required external checks have also passed.

5. Credential-family bindings

5.1 Supported source formats

This profile targets two source formats:

  1. SD-JWT VCdraft-ietf-oauth-sd-jwt-vc
  2. ISO/IEC 18013-5 (mdoc) — mobile credential format specified by ISO/IEC 18013-5:2021

A format is supported only when this profile defines how issuer-authenticated values are selected, addressed, and used by OpenAC. Being parseable by a wallet is not enough.

5.2 Credential binding model

A credential binding connects source-format data to OpenAC input.

The binding MUST identify which values are covered by issuer authentication. Only those values may become OpenAC statement input. Values needed for trust, status, validity, freshness, or device binding remain separate unless a supported statement type explicitly uses them.

5.3 Source-format rules

SD-JWT VC. The binding MUST identify:

  • the issuer-signed JWT payload;
  • the disclosures used as OpenAC input;
  • the salts and digests needed to check disclosure consistency;
  • the issuer signature and issuer verification material;
  • any key-binding or device-binding material used by the selected statement type.

The OpenAC paper §3 gives the SD-JWT prepare relation directly. A claim value may become OpenAC statement input only if it passes this issuer-authentication path. See also credential.ts for the SDK implementation.

ISO/IEC 18013-5 (mdoc). The binding MUST identify:

  • issuer-signed data elements that may become OpenAC statement input, with their namespace and element identifier;
  • issuer-authentication material covering those elements;
  • any device-signed or session-specific material used by the selected statement type;
  • validity, status, or trust material needed by verifier-side checks.

The binding MUST keep issuer-signed data separate from device-signed or session-specific material. After binding, each retained value MUST have a stable identifier.

Both formats. Source-format labels (claim, attribute, metadata, validity field) do not decide OpenAC semantics. A field becomes statement input only if the binding assigns it that role.

5.4 Binding requirements

A conforming credential binding MUST:

  1. Identify the source format and supported version.
  2. Identify which values are covered by issuer authentication.
  3. Define which issuer-authenticated values may become OpenAC statement input.
  4. Define how retained values are addressed after binding.
  5. Separate statement input from values used only for trust validation, status validation, validity validation, freshness, device binding, User binding, or other verifier-side checks.
  6. Define any normalization rule used before Show.
  7. Reject a value whose issuer-authenticated status is ambiguous.
  8. Reject a retained value that cannot be addressed unambiguously.
  9. NOT allow wrapper metadata, display metadata, transport metadata, wallet-local metadata, verifier-supplied text, or unauthenticated source-format fields to become statement input.

A verifier MUST reject an OpenAC response if the claimed credential binding is unsupported.


6. OpenAC request, response, and state model

Outline — to be specified

This section will fix the OpenAC transcript boundary: which values determine the statement being proven, which values stay local to the wallet, and which values the verifier needs before it can accept the response.

6.1 OpenAC request

Fields that determine verifier intent: statement type, credential binding, selected attribute handles or relation inputs, predicate parameters, freshness, verifier context, and alternative-selection rules. Any field that changes the verifier's conclusion is acceptance-critical and must be protected against substitution or downgrade.

6.2 Prepared state

Wallet-local output of Prepare, derived from credential-bound authenticated input. Records: binding identifier, prepared attributes or commitments, supported statement classes, proof parameters, refresh status, expiry, and reuse constraints.

Prepared state is not a presentation artifact.

6.3 OpenAC response and transcript binding

Verifier-visible output of Show: proof object, selected statement, credential binding identifier, transcript binding, freshness binding, disclosed or derived outputs, and validation references required by the credential binding. The response must make it possible to reject replay, substitution, and downgrade without relying on out-of-band interpretation.


7. Wallet procedures

The wallet-side OpenAC path is:

credential binding → Prepare → prepared state → admissibility check → refresh/reblind → Show → response

7.1 Preparation

Prepare starts after the credential binding has fixed the issuer-authenticated input. The wallet prepares over bound and normalized credential material mapped into witness inputs, not over raw credential syntax.

7.2 Prepared-state admissibility and refresh

Before Show, the wallet checks whether the selected prepared state is admissible: binding match, statement support, attribute availability, proof-parameter compatibility, expiry or invalidation, refresh availability, and reuse discipline.

Unsafe reuse (using the same prepared state in two presentations without refresh) is not conformant to this profile.

7.3 Request processing and release gates

The wallet resolves the request into proof material: requested statement, required attributes or relations, credential binding, candidate credential, and admissible prepared state. Unsupported statements, unsupported predicates, ambiguous handles, missing authenticated input, and unsupported relations are rejected here.

User approval and local policy are checked before response release. They gate release of the response; they are not OpenAC-proven facts unless the statement semantics explicitly include them.

7.4 Response generation and wallet failure classes

After admissibility passes, the wallet refreshes or reblinds the selected state, runs Show over the accepted transcript, and attaches required outputs and references. Failure classes: request error, binding error, state error, refresh error, approval/policy gate, proof-generation failure.


8. Statement semantics

8.1 Statement model

Each statement type specifies: credential binding dependency, public inputs, hidden witness values, statement parameters, normalization source, public outputs, verifier conclusion, rejection rule, and composition rule.

Semantics must not be inferred from the circuit shape, proof backend, or credential format alone.

8.2 Disclosure and predicate statements

  • Disclosure: the verifier receives a selected normalized value bound to issuer-authenticated input.
  • Predicate success: only that a hidden authenticated value satisfies the declared rule under the declared type, encoding, and comparison semantics.

Predicate success is not disclosure.

8.3 Binding and relation statements

Binding statements cover: credential-input binding, attribute-to-witness binding, request binding, freshness binding, device binding, and User binding. Device binding and User binding are kept separate.

Relation statements (same-subject, cross-credential) define hidden inputs, public outputs, relation scope, verifier conclusion, and rejection rules.

8.4 Pseudonym, issuer-hiding, status, and composition limits

Pseudonym, issuer-hiding, and status statements are profile-defined statement types. Multi-statement success gives only the combined conclusion defined by the profile. It does not imply issuer trust, non-revocation, user approval, relying-party authorization, or undeclared cross-statement meaning.


9. Verifier processing and OpenAC acceptance

9.1 Verification pipeline

The verifier MUST apply checks in the following order:

parse response
→ check profile version and parameters
→ recover request transcript
→ check credential binding
→ check freshness
→ check Prepare/Show linkage
→ verify proof
→ evaluate statement semantics
→ check outputs
→ accept / reject

The order matters: statement evaluation is meaningful only after transcript, binding, freshness, and linkage have passed.

9.2 Required checks and rejection conditions

Check categoryReject condition
Syntax and versionUnsupported profile version or parameters
Credential bindingUnsupported binding; credential family mismatch
Transcript bindingMissing or failed request or audience binding
FreshnessStale nonce; missing freshness material; expired request
Prepare/Show linkageShow proof does not link to the correct Prepare output
Proof validityProof verification fails
Statement semanticsUndeclared statement type; wrong predicate encoding
Output consistencyInconsistent disclosed values
Extension safetyUndeclared extensions; downgrade detected

9.3 OpenAC acceptance result

The result identifies: accepted statement, binding, outputs, freshness result, parameter set, statement limits, and external checks still required. It remains separate from final relying-party acceptance.


10. External checks and deployment dependencies

OpenAC proves statements over issuer-authenticated credential data. This section prevents confusing the proof-layer result with deployment acceptance.

10.1 External validation material

Credential binding or response construction may retain: issuer identifiers, public-key or certificate references, trust-list references, credential type, status-list references, revocation identifiers, and verifier context. These are references that enable external validation — not validation results.

10.2 Trust, status, revocation, and deployment gates

  • A valid OpenAC proof does not by itself imply a trusted issuer or a non-revoked credential.
  • Relying-party authentication, user approval, wallet policy, service authorization, and final relying-party acceptance remain deployment decisions unless the statement semantics explicitly represent one of them.
  • See Revocation overview for the current status of in-proof revocation.

10.3 External linkability risks

Proof-layer privacy does not remove: network or session metadata, repeated request shapes, rare disclosed values, status-check correlation, trust-list lookup leakage, verifier collusion, mediation logs, or policy fingerprints.


11. Declared support and profile claims

11.1 Declared support surface

An implementation declares: profile version, supported credential bindings, statement types, predicate classes, attribute types, proof backend, setup assumption, hash and commitment choices, freshness mode, device/User binding mode, status handling mode, protocol binding, and external validation dependencies.

Requests that rely on undeclared bindings, statements, predicates, or parameter ranges MUST be rejected.

11.2 Parameters and admissibility limits

Limits that affect whether a request can be processed: security level, proof parameters, maximum attributes, maximum statements, maximum credentials, predicate complexity, prepared-state pool constraints, proof size, and key size. These are not merely performance notes — they decide whether a wallet can generate a response and whether a verifier can evaluate it.

11.3 Wallet and verifier profile claims

Wallet claims cover: credential binding, witness construction, Prepare, prepared-state admissibility, refresh/reblind, Show, transcript binding, and rejection of unsupported requests.

Verifier claims cover: request construction, transcript preservation, freshness, Prepare/Show linkage, proof verification, statement evaluation, output checking, and rejection of unsupported responses.

11.4 Non-conformance anchors

Profile-breaking cases: wrong attribute-to-witness binding; stale challenge accepted; unsafe prepared-state reuse; undeclared statement accepted; ambiguous credential field selected; or OpenAC acceptance treated as final relying-party acceptance.


12. Security and privacy considerations

12.1 Proof-layer assumptions

Correctness, soundness, and zero-knowledge hold under the proof-system assumptions in Security — assumptions. Privacy claims are conditional: they depend on fresh randomness, correct Reblind discipline, and no external leakage of stable identifiers.

12.2 Binding, witness, and prepared-state risks

A proof can verify while proving the wrong value. Main causes:

  • unauthenticated fields entering the witness;
  • wrong field selection or ambiguous claim paths;
  • inconsistent normalization between wallet and verifier;
  • swapped witness indexes;
  • metadata treated as statement material.

Offline preparation can become a linkability or correctness bug through:

  • missing refresh (stable commitment reuse);
  • unsafe pool fallback;
  • state-selection correlation;
  • expired state use;
  • Show not linked to the intended Prepare.

12.3 Transcript, downgrade, and statement-interpretation risks

A valid proof can be attached to the wrong transcript through: request or response substitution, changed predicate parameters, changed attribute handles, missing verifier context, replayed freshness, weaker-statement acceptance, or mismatch between the approved request and the proven statement.

Verifier overclaim is a distinct semantic failure mode:

OverclaimCorrect interpretation
Predicate treated as disclosurePredicate success reveals only the evaluation result, not the underlying value
Device binding treated as User bindingA bound device key does not imply user authentication
Issuer signature treated as issuer trustThe issuer signing a credential does not mean the issuer is trusted by the verifier's policy
Proof validity treated as non-revocationA valid proof does not check the credential's revocation status unless a revocation statement is included
OpenAC acceptance treated as service authorizationProof acceptance is a necessary but not sufficient condition for access

12.4 External privacy and implementation risks

External risks: network metadata, verifier collusion, repeated request shapes, rare disclosed values, status lookup leakage, trust-list lookup leakage, mediation logs, policy fingerprints.

Implementation risks: randomness or side-channel failures, serialization and canonical-encoding mismatches, parameter mismatch, unsafe extension parsing, weak storage, dependency bugs, and mobile fallback behavior.


Annex A — Mapping to ETSI and ARF requirement families

Requirement familyCoverageSectionsDependency or condition
Unlinkability and presentation privacyHandled by OpenAC proof layer, prepared-state refresh, request-specific Show, statement semantics, and verifier checks.3, 4, 6, 7, 8, 9, 12Transport metadata, verifier logging, status-checking patterns, and service-side correlation remain outside the proof layer.
Selective disclosureHandled for issuer-authenticated values that enter OpenAC through a supported credential binding.5, 6, 7, 8, 9Requires SD-JWT VC or ISO/IEC 18013-5 binding detail (Annexes B/C).
Predicate proofsHandled for predicate classes declared by the profile.8, 9, 11Depends on credential-family normalization and declared predicate bounds.
Supported credential familiesHandled through credential bindings, not through generic parsing.5, Annex B, Annex CBaseline: SD-JWT VC and ISO/IEC 18013-5/mdoc.
Authenticated credential inputOnly issuer-authenticated values identified by the binding may become OpenAC statement input.3, 5, 7, 8, 9Issuer trust validation remains external.
Freshness and request bindingOpenAC response bound to request elements required for acceptance, including freshness.6, 7, 8, 9, 11Concrete challenge/nonce carriage depends on protocol binding (Annex D).
Device binding and User bindingHandled only when included by the selected credential binding or statement type.5, 8, 9, 10, 11, 12ARF checks remain outside OpenAC unless included in an OpenAC statement.
Relying-party authenticationExternal. OpenAC may bind to request context, but does not define RP authentication infrastructure.3, 7, 10, 12Supplied by the EUDI Wallet environment or protocol binding.
User approvalExternal precondition. Gates release of the response; not an OpenAC-proven fact.3, 7, 10, 12Supplied by the surrounding wallet environment.
Issuer trust validationExternal by default. Whether the issuer is trusted for a credential type is decided outside the proof.3, 5, 9, 10, 12Trust anchors, trusted lists, LoTEs, issuer authorization, certificates, rulebooks.
Validity-time checkingExternal unless included in a declared statement type.8, 9, 10, 11, 12Depends on credential validity fields and verifier policy.
Revocation and status checksExternal in the baseline profile. A declared status statement must define what is proved and how.5, 8, 9, 10, 11, 12Status lists, revocation lists, accumulators, or declared status mechanism.
In-proof status representationA declared status statement carries status into the OpenAC proof layer.8, 9, 10, 11, 12Requires defined status source, proof relation, verifier semantics, and privacy analysis.
Issuer hidingA declared issuer-hiding statement must define what issuer information remains visible.8, 9, 11, 12Trust validation may require issuer-set or trust-anchor information.
Pseudonym semanticsA declared pseudonym statement must define scope, inputs, verifier context, and linkability limits.8, 9, 11, 12Depends on verifier context, domain separation, and declared pseudonym scope.
Intra-credential relationsHandled for relation types declared in Section 8.5, 8, 9, 11Depends on stable addressing and normalization from the credential binding.
Cross-credential relationsA declared cross-credential statement must define witness linking and composition rules.6, 8, 9, 11, 12Requires credential-family alignment and cross-credential trust assumptions.
Wallet proceduresPreparation, admissibility, refresh, Show, response generation, and failure handling.4, 6, 7, 12Wallet storage protection and local device security remain implementation assumptions.
Verifier processingProof validity, request binding, freshness, statement semantics, declared support, and external checks.9, 10, 11External trust or status failures affect final relying-party acceptance.
Declared support and conformanceImplementations declare supported bindings, statement types, predicates, bounds, backend, and dependencies.11Unsupported statement types must be rejected.
Migration, backup, and recoveryOut of scope for this presentation profile.1Belongs to wallet-function specifications.
Proof-system substitution and post-quantum evolutionTreated as declared support or security consideration.4, 8, 11, 12Requires backend-specific security analysis and parameter declarations.

Annex B — SD-JWT VC binding

To be specified

Contents: authenticated input boundary; claim path syntax; disclosure handling; normalization; attribute-to-witness binding; key binding; status/trust references; unsupported structures; examples.


Annex C — mdoc binding

To be specified

Contents: MSO boundary; namespace and element addressing; issuer-signed item mapping; device signature / mdoc authentication; normalization; attribute-to-witness binding; status/trust references; unsupported structures; examples.


Annex D — Protocol binding

To be specified

Contents: request carriage; response carriage; challenge/freshness mapping; response encoding; verifier metadata; wallet capability discovery; error handling; protocol-level replay interaction.


Annex E — Examples

E.1 Age eligibility

This flow shows an age-gating deployment where the relying party needs an eligibility result without receiving the user's date of birth.

E.1.1 Deployment choices

ItemExample value
Statementage_eligibility
Threshold18
Accepted credential profilejurisdiction-bound driver-license profile
Freshnessverifier nonce
Audiencerelying-party identifier
Result formatpass or fail

The accepted credential profile must be precise enough for the wallet to match a credential and for the verifier to check the statement.

E.1.2 Request

{
"audience": "merchant.example",
"nonce": "verifier-freshness-value",
"expires_at": "2026-05-09T10:15:00Z",
"statement": "age_eligibility",
"threshold": 18,
"accepted_credential_profiles": [
"example.driver_license.profile"
]
}

The request binds together the verifier, freshness, statement, threshold, and accepted credential profile set.

E.1.3 Wallet flow

1. Receive request.
2. Check request context: audience, nonce presence, expiry, statement support.
3. Match credential against accepted_credential_profiles. Reject if ambiguous.
4. Obtain User approval.
5. Select admissible prepared state (matching binding, statement type, expiry).
6. Refresh prepared state (Reblind).
7. Run Show: statement=age_eligibility, threshold=18, nonce, audience.
8. Return OpenAC response.

The response proves the requested age statement. It does not disclose the birth date.

In the current SDK, the age predicate maps to PredicateOp.GE over the normalized birthday claim value. See Generalized predicates and Show phase.

E.1.4 Verifier flow

1. Receive OpenAC response.
2. Check request binding: nonce, audience, threshold, statement from the request.
3. Check credential-profile binding.
4. Verify OpenAC proof.
5. Apply required external checks: issuer trust, status/revocation, service policy.
6. Return bounded application result.

Example result:

{
"result": "pass",
"statement": "age_eligibility",
"threshold": 18
}

The result does not include raw credential fields or undisclosed attributes. Based on the age-eligibility draft.


E.2 Human verification with duplicate prevention

This flow proves two things together:

  1. The user holds a valid accepted credential.
  2. The same credential has not already been accepted for the same application scope.

It adds two deployment-specific objects:

ObjectPurpose
Revocation witnessProves the credential is not revoked under an accepted status root
NullifierPrevents duplicate acceptance within a declared scope

These are not baseline OpenAC requirements — they are declared statement extensions.

E.2.1 Deployment choices

ItemExample value
Statementhuman_verification
Application scopeapp_id
Freshnessverifier challenge
Revocation sourceaccepted status root or snapshot
Duplicate-prevention ruleone accepted nullifier per app_id
Nullifier storagedurable verifier-side store

E.2.2 Request

{
"audience": "verifier.example",
"app_id": "example-app",
"challenge": "session-freshness-value",
"expires_at": "2026-05-09T10:15:00Z",
"statement": "human_verification",
"revocation_root": "accepted-root-identifier"
}

E.2.3 Wallet flow (privacy-preferred)

1. Receive request and check context.
2. Select accepted credential.
3. Obtain revocation witness:
- Download the status data structure locally.
- Compute the witness on device.
- Do NOT send the credential-specific revocation identifier to a witness server.
4. Check that the local witness matches the verifier's revocation_root. Reject if not.
5. Obtain User approval if required.
6. Select and refresh prepared state.
7. Run Show: human_verification, challenge, app_id, revocation_root, nullifier input.
8. Return OpenAC response.

E.2.4 Verifier flow

The verifier MUST apply checks in this order:

1. Verify OpenAC proof.
2. Check challenge and expiry.
3. Check revocation root binding.
4. Check nullifier absence (reject if already accepted for this app_id).
5. Record nullifier durably.
6. Return bounded result.
Nullifier recording order

The verifier MUST record the nullifier only after proof verification succeeds. Recording before verification lets invalid submissions block later valid ones.

Durable storage

If nullifiers are stored only in memory, the duplicate-prevention claim weakens to "not previously accepted since the last verifier restart." To claim duplicate prevention across restarts, the verifier MUST store accepted nullifiers durably.

Based on the human-verification draft.


Progress and roadmap

Track the profile's development on the zkID 2026 roadmap.

The profile is being developed as a contribution to ETSI TS 119 476-2. For the current ETSI context, see ETSI TS 119 476-2 context.