ZK ON ZCASH · ZK SIGN

Back to ecosystem

Private signature · Halo2 · Orchard

Research preview · Circuit in development

Sign on behalf of the group, without revealing who signed.

ZK Sign proves you belong to an authorized set (Merkle root published by the issuer) and that your signature is unique for that document. Your key stays with you, your identity stays private, the nullifier blocks double-signing.

RFC published 2026-04-21. MVP ships SignCircuit with Merkle depth 16 (65k members). Revoke, threshold, and ring mode land in phases S.7+.

Capabilities

Four guarantees in one signature

A single proof covers membership, anti-replay, document binding, and composition with timestamp. Revoke and threshold ship in phase 2.

  • Private membership

    MVP

    Proves you are one of the authorized members (published Merkle root) without revealing which leaf is yours. Rotation becomes a new root.

    Private: sk_sign, merkle_path, merkle_indices. Public: merkle_root.

  • Anti-replay via nullifier

    MVP

    nullifier = Poseidon(sk_sign, doc_hash) binds signer to document. Two signatures on the same doc produce the same nullifier and get rejected.

    Private: sk_sign, doc_hash. Public: nullifier.

  • Traceable revocation

    Phase 2

    Issuer publishes a new Merkle root excluding compromised keys. Old signatures stay valid; new ones from the banned key fail.

    Private: old_pk, old_path. Public: old_root, new_root, revocation_nullifier.

  • Threshold t-of-n

    Phase 2

    Aggregates N signers of the same Merkle into one proof. Shows that at least t distinct keys endorsed without revealing identities.

    Private: sk_sign[t], merkle_path[t]. Public: merkle_root, threshold t, nullifier[t].

How it works

From document upload to the Orchard memo

Seven steps across issuer, signer, and verifier. Everything runs client-side; the server only relays the Zcash transaction.

  1. Issuer

    Builds and publishes Merkle root

    Collects members' public keys, computes a Poseidon Merkle tree of depth 16, and publishes the root (on-chain or via issuer-state.json).

  2. Signer

    Local hash of the document

    SHA-256 runs in the browser via crypto.subtle. The document never leaves the device; the prover only sees doc_hash.

  3. Prover

    Derives pk_sign and nullifier

    pk_sign = Poseidon(sk_sign) and nullifier = Poseidon(sk_sign, doc_hash_lo, doc_hash_hi). All in WASM, zero key exposure.

  4. Prover

    Halo2 proof with Merkle verify

    SignCircuit checks the merkle_path up to the public root and binds the nullifier to doc_hash. Output is the compact proof.

  5. Zcash

    Anchors via Orchard memo

    512B memo with ZKSG magic + merkle_root_hint + 32B nullifier + optional doc_commit. Regular shielded transaction.

  6. Signer

    Delivers receipt

    receipt.json carries proof + nullifier + tx_hash + block height. Verifier receives it offline, no need to reopen the document.

  7. Verifier

    Checks proof + fresh nullifier

    Validates the Halo2 proof, confirms the known Merkle root, and looks up the nullifier in earlier blocks. Double-use triggers reject.

Stack

Same base as the other ZK on Zcash products

Full reuse with ZK Credit, ZK ID, and ZK Timestamp: same zkcgz binary, same pasta_curves primitives, same Orchard anchor. No trusted setup.

  • Proving systemHalo2 + IPA

    pasta_curves, trustless. SignCircuit reuses the Poseidon chip (width=3, rate=2) already used by CredentialCircuit.

  • Member structurePoseidon Merkle (depth 16)

    Each node is Poseidon(left, right). Depth 16 covers 65,536 signers. Rotation publishes a new root.

  • On-chain anchorOrchard memo (512B)

    ZKSG magic + version + merkle_root_hint + nullifier + optional doc_commit. Coexists with ZKT0 and ZKID.

  • Where it runs100% client (WASM)

    sk_sign never leaves the device. Server only relays the Zcash tx. Hosted mode with HSM ships in phase S.6+.

Roadmap

From RFC to E2E demo

Seven MVP phases + S.7 for revocation. Each phase ships something runnable; threshold and ring mode are post-MVP.

  1. S.1

    RFC approved + /sign route

    1 weekIn progress
  2. S.2

    SignCircuit in Rust (halo2_proofs + Merkle Poseidon)

    2 to 3 weeksPlanned
  3. S.3

    CLI zkcgz sign issue/sign/verify

    1 weekPlanned
  4. S.4

    Orchard memo encoder/decoder with ZKSG magic

    1 weekPlanned
  5. S.5

    Surfaces /sign/issue, /sign/sign, /sign/verify

    2 weeksPlanned
  6. S.6

    Testnet E2E: issue, sign, anchor, verify

    1 weekPlanned
  7. S.7

    SignRevokeCircuit + /sign/revoke surface

    2 to 3 weeksPlanned

Out of scope

What ZK Sign is not

Explicit decisions to keep the MVP viable and the pitch crisp.

  • Legal non-repudiation: this is technical evidence, not a substitute for a notary or lawyer.
  • Threshold t-of-n in the MVP: single-signer first, threshold in phase 2.
  • Replacement for ECDSA/Ed25519 where law demands identity: still out of scope.
  • Issuing X.509 certificates from the nullifier: optional future bridge.