Skip to content

Add 1/OPENAC spec (raw)#88

Open
cc03668 wants to merge 1 commit into
privacy-ethereum:mainfrom
cc03668:specs/openac-draft
Open

Add 1/OPENAC spec (raw)#88
cc03668 wants to merge 1 commit into
privacy-ethereum:mainfrom
cc03668:specs/openac-draft

Conversation

@cc03668
Copy link
Copy Markdown
Contributor

@cc03668 cc03668 commented May 14, 2026

Summary

  • Adds specs/1-openac/ — the OpenAC anonymous-credential presentation protocol spec.
  • Status: raw. Imported from zkspecs#23 (previously 7/OPENAC-CORE); supersedes the earlier draft at zkspecs#21.
  • Companion PR: #87 (human verification + age eligibility specs). Order of merge is independent; this PR's contents do not overlap.
  • No implementation changes — documentation only.

What's included

Rename: OPENAC-COREOPENAC

The spec is renamed at the identifier level only:

  • Folder: 1-openac-core/1-openac/
  • Slug: 71; title: 7/OPENAC-CORE1/OPENAC
  • name frontmatter: OpenAC Core ProtocolOpenAC

In-body uses of "OpenAC Core" as a scope qualifier are preserved — the spec uses that phrase to distinguish the core protocol layer from future extensions (revocation, nullifiers, on-chain verifiers, additional credential profiles). Changing it everywhere would obscure that distinction.

Why this is a separate PR from #87

OpenAC is still in editorial flux. Tracking issue #89 (formerly zkspecs#22) collects open verifier-profile boundary questions that need resolution before promotion beyond raw. Keeping this PR separate from #87 lets the other two specs land without being held up by that review.

Cross-references

Follow-ups

Once this lands:

  • Add the 1/OPENAC row to specs/README.md (one-line edit).
  • Address tracked verifier-profile questions in #89 via subsequent PRs against specs/1-openac/.

cc @oskarth @vplasencia

🤖 Generated with Claude Code

Adds the OpenAC anonymous-credential presentation protocol spec at
specs/1-openac/. Previously incubated in privacy-ethereum/zkspecs as
7/OPENAC-CORE (zkspecs#23; an earlier draft existed at zkspecs#21).

Renamed from `OPENAC-CORE` to `OPENAC` at the identifier level
(slug, folder, title, frontmatter name). In-body uses of "OpenAC Core"
as a scope qualifier (distinguishing the core layer from future
extensions like revocation, nullifiers, on-chain verifiers) are
preserved as-is.

Companion PR: privacy-ethereum#87 (the other two specs).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Core text treats those items as future extensions or future profile specs,
not latent requirements of the current protocol.

## 2. Device Public Key Exposure
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The device key isn't just exposed by the SDK, it's a public output of the Show circuit itself.

  • wasm/src/lib.rs:258verify() doesn't take any device key as input. It only takes proof bytes, verifying keys, and instances.
  • verifier.ts:67-70 — the device key comes out as showPublicValues[1] and [2], right after expression_result at [0].

So every Show proof emits (expression_result, deviceKeyX, deviceKeyY) as public values. Same device → same coordinates → verifier can link sessions.

To hide the device key, you need a new Show circuit (key becomes a private witness, PoP is proven against a commitment), a new verifying key, and a new version identifier. i think its more relevant to change profile change not an SDK

Also: the device key is in payload.cnf.jwk in the SD-JWT cleartext, so the issuer always sees the device→credential link. Hiding it from verifiers only helps if they don't talk to the issuer.

Suggested split:

  • Current SD-JWT-P256 profile: accept that deviceKeyX/Y are public outputs. Document it.
  • New profile later for the unlinkable version, with its own version id.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @0xVikasRushi for the clarification. I want to make sure I understand the privacy implication correctly.

If deviceKeyX/Y are public values of the current Show circuit, then this is not just an SDK API artifact. It means the current SD-JWT-P256 profile exposes a stable device public key to verifiers. If the same device key is reused across presentations, colluding verifiers can link sessions by comparing the key coordinates.

That seems to substantially weaken verifier-side unlinkability for the current implementation. My read is that this should be documented as a current-profile privacy caveat, rather than treated as an OpenAC Core property.

A few questions to help us define the spec accurately:

  1. Should the current SD-JWT-P256 profile explicitly say that deviceKeyX/Y are public outputs and therefore verifier-observable linking identifiers?
  2. Should OpenAC Core still state the intended long-term property as “proof of possession of the bound device key,” without requiring stable device key exposure?
  3. Would an unlinkable device-binding version require a new Show circuit, verifying key, profile/version identifier, and a hidden-key or commitment-based PoP design?

I think the spec should distinguish:

  • current implementation behavior,
  • current privacy caveat,
  • intended long-term OpenAC Core property,
  • and future unlinkable device-binding profile work.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @cc03668 for laying out the framing so clearly, it actually helped me look at this more carefully, and i think the fix turns out to be simpler than my earlier comment suggested. Apologies for the earlier framing pointing toward a new profile; the unlinkable device-binding machinery is in fact already implemented, we just aren't taking advantage of it.

A quick walk-through of what's already there:

commitment is hiding, re-randomized per session, and already binds Prepare's extracted device key to Show's signing key so by construction we don't actually need the device binding key in the circuit's public values at all.

Suggested fix: Remove the device-binding-key exposure from the Show circuit's public values. The key still flows from the issuer-signed credential through Prepare into Show's shared witness, and comm_W_shared equality enforces that binding so the verifier already has the cryptographic guarantee they need without seeing the raw coordinates.

On your three questions, with this in mind:

1/ I'd lean toward treating this as a current-profile bug to fix rather than a property to document. The intent of the design is unlinkability; the leak is unintentional, and fixing it doesn't require breaking changes elsewhere.
2/ Yes, PoP of the bound key, no stable identifier exposure, is the right long-term Core property. comm_W_shared is already the PoP mechanism that delivers it.
3/ With the fix above, a new Show circuit / VK / profile id shouldn't be necessary. The construction is in place; it just needs to actually be private.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh that's a great news! Just one more check: does removing deviceKeyX/Y from public values change the public input layout, verifying key, serialized instance format, or test vectors?
If yes, we may still need a version/test-vector update even if we do not need a new profile.


Primary external references:

- [OpenAC whitepaper](https://github.com/privacy-ethereum/zkID/tree/main/paper)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use this link https://eprint.iacr.org/2026/251

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants