Skip to main content

Concepts

Anonymous credentials in OpenAC

OpenAC is a proof layer over existing issuer-signed credentials. The credential (today: SD-JWT VC in the PoC) is issued and signed by an existing issuer — OpenAC does not change that. What OpenAC adds is zero-knowledge so verifiers learn only policy outputs and agreed public data, not raw attributes.

The three-phase pipeline: Prepare → Reblind → Show

OpenAC splits credential-dependent proof work from request-dependent proof work:

PhaseWhat happensWhenIn SDK (openac-sdk 0.1.0)In Rust CLI
PrepareParse credential, verify issuer signature, commit to message vector. Independent of any specific request or verifier.Once per credential (offline, cacheable).precompute(...)prepare …
ReblindRe-randomize the prepared state. Refreshes the hidden representation before presentation to break cross-session linkability.Before each Show.Inside present(...)prepare reblind / show reblind
ShowBind to verifier nonce, prove device key ownership, evaluate predicates, link to Prepare commitment.Per presentation (online).present(...)show …

The Prepare–Reblind–Show pipeline is described in Paper §3 and specified in Implementation profile §4.3.

Prepared state stays local

Prepare output is wallet-local state. It is never sent to the verifier as a standalone artifact. Only the Show output (the OpenAC response) reaches the verifier.

OpenAC acceptance vs final relying-party acceptance

This distinction matters for verifier integration:

ResultMeaning
OpenAC acceptanceThe proof verifies, the response is bound to the request, freshness checks pass, and the proven statement has the defined meaning. This is the proof-layer result.
Final relying-party acceptanceAlso requires: issuer trust validation, credential status/revocation check, relying-party authentication, user approval, and service policy. OpenAC acceptance is necessary but not sufficient.

For the full boundary definition see Implementation profile §1.3 and §10.

Commitments and Prepare–Show linking

The paper's preliminaries / commitments section describes Hyrax-style Pedersen vector commitments that link Prepare and Show. Prepare commits to the message vector; Show proves predicates over that same vector without re-revealing it. The verifier checks that the Show proof uses the same credential-derived messages accepted by Prepare by comparing these commitments.

See Prepare phase for the commitment notation.

Credential bindings

Before OpenAC can process a credential, the wallet must bind it: identify which values are covered by issuer authentication. Only those values can become OpenAC statement input. Values used for trust validation, status checks, validity, or device binding remain separate.

Supported credential families:

  • SD-JWT VC — the PoC's primary path; Prepare parses the SD-JWT into messages, salts, hashes, and issuer signature.
  • ISO/IEC 18013-5 (mdoc) — experimental; wallet-unit-poc/circom includes an mdoc compile target.

See Credential formats and Implementation profile §5.

Predicates

Claims are mapped to field elements for the Show circuit. Predicate operations match the Circom circuit (LE, GE, EQ) via numeric codes in PredicateOp. Boolean structure uses postfix tokens (LogicToken).

Predicate success is not disclosure — the verifier learns only the evaluation result, not the underlying claim value. See Generalized predicates.

Revocation (status)

In-wallet scenario tooling distinguishes no revocation, out-of-band, and in-proof (future) — see openac-studio rules. There is no integrated cryptographic revocation tree in this repository yet; see Revocation overview.

A valid OpenAC proof does not by itself imply a non-revoked credential unless a revocation statement type is explicitly declared and included.

EUDI mapping

OpenAC is positioned for EUDI ARF compatibility. OpenAC does not replace any part of the EUDI Wallet transaction; it adds a proof layer inside it. A reading guide and requirement-family table live at EUDI mapping.


Glossary

TermMeaning
SD-JWT / SD-JWT VCSelective-disclosure JWT; disclosures are separate base64url blobs ([salt, name, value] triples). Defined by draft-ietf-oauth-sd-jwt-vc.
cnf.jwkHolder device binding public key inside the JWT payload. Required for precompute in the SDK.
VcSizeJWT circuit payload bucket: '1k', '2k', '4k', '8k' for key loading. Choose based on worst-case JWT length.
Spartan2Transparent zkSNARK used by ecdsa-spartan2 (Setty, CRYPTO 2020).
prepared stateWallet-local output of Prepare. Not sent to verifiers. Must be refreshed before each Show.
prepared-state poolStored collection of prepared states produced by offline Prepare and re-randomization.
ReblindRe-randomization of prepared state before Show. Breaks cross-session linkability.
OpenAC acceptanceProof-layer result: the proof verifies, request binding holds, freshness passes, statement meaning is defined. Not equal to final relying-party acceptance.
predicate proofA verifiable computation where only the result (pass/fail) is shared, not the underlying claim value.
witnessPrivate prover data used to prove a relation is satisfied. Never sent to the verifier.
PIDPerson Identification Data (ARF §5.2.2). External credential input; OpenAC does not redefine it.
Wallet UnitEUDI deployment role for OpenAC proof generation (ARF §4.3.2).
Relying Party InstanceTechnical endpoint that interacts with the Wallet Unit (ARF §3.11.2).
nullifierA value derived from a credential and application scope used to prevent duplicate acceptance. Not part of baseline OpenAC — a declared extension.

Commitment notation

The exact Pedersen vector commitment used by Prepare/Show is defined on the Prepare phase page, matching Paper §Preliminaries.