Skip to content

feat(proof): add private claims co-proof POC - #959

Draft
Dzejkop wants to merge 2 commits into
mainfrom
codex/claims-proof-poc
Draft

feat(proof): add private claims co-proof POC#959
Dzejkop wants to merge 2 commits into
mainfrom
codex/claims-proof-poc

Conversation

@Dzejkop

@Dzejkop Dzejkop commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add a Noir companion circuit for proving sparse strict-range predicates over private credential claims
  • recalculate the private claims_hash and verify that it is covered by the issuer credential signature
  • bind the issuer-attested credential to the companion Circom proof through the shared nullifier, issuer, RP/action, and credential time policy
  • add optional claims-proof request/response primitives, native Authenticator generation, and an RP-facing verification helper
  • add embedded, filesystem, cached, and custom artifact-source plumbing for the claims prover and verifier

Privacy model

The raw 15 claim slots and the recalculated claims_hash are private circuit inputs. There is no public claims hash, salt, or claims commitment. Only the RP-requested predicates and the public context needed to pair and verify the two proofs are exposed.

The RP must independently verify both the Circom nullifier proof and the Noir claims proof using matching public context. The claims verifier also requires the issuer public key resolved for the requested issuer/schema.

Claims-proof public inputs

The Noir ABI contains 68 public field elements grouped into three structs:

  1. claims — 60 fields: 15 fixed claim slots, each containing check_min, check_max, range_check_min, and range_check_max. The sparse indexed Rust statements are expanded into these slots internally. The two check flags are constrained to boolean values.
  2. credential — 5 fields: issuer_schema_id, issuer public key coordinates cred_pk[2], current_timestamp, and cred_genesis_issued_at_min.
  3. nullifier — 3 fields: the shared nullifier value, rp_id, and action.

The credential and nullifier fields must match the public context used to verify the companion Circom proof. In the Authenticator integration, current_timestamp is the request item's effective expires_at_min policy value.

POC limitations

  • claims proving and verification are native-only; claims requests return an explicit unsupported error on wasm32
  • this is a draft protocol/API shape and has not received a security audit
  • the fixed 15-slot Noir predicate representation is intentionally hidden behind sparse indexed Rust request types

Validation

  • nix develop --command sh -c 'cd crates/proof/noir/claims-proof && nargo fmt --check && nargo test && nargo compile' — 6 tests passed
  • cargo test -p world-id-primitives — 167 unit tests, regression tests, and doctests passed
  • cargo test -p world-id-proof --lib — 28 tests passed
  • cargo test -p world-id-authenticator --lib — 19 tests passed
  • cargo clippy -p world-id-primitives -p world-id-proof -p world-id-authenticator -p world-id-core --all-targets -- -D warnings
  • real embedded ProveKit generation/verification passed, including rejection when the paired nullifier is changed

@Dzejkop
Dzejkop force-pushed the codex/claims-proof-poc branch from 64efc01 to 4d20c66 Compare August 28, 2026 10:54
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.

1 participant