Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

How to Implement Selective Disclosure for Asset Ownership Proofs

A technical guide for developers on building systems that allow proving specific asset attributes cryptographically while keeping other data private, using ZK-SNARKs and verifiable credentials.
Chainscore © 2026
introduction
ZKP GUIDE

Introduction to Selective Disclosure for Asset Ownership Proofs

Selective disclosure allows users to prove specific attributes about their assets without revealing the entire data set. This guide explains the core concepts and implementation patterns for asset ownership proofs using zero-knowledge proofs.

Selective disclosure is a cryptographic technique that enables privacy-preserving verification. In the context of digital assets, it allows a user to prove they own an asset meeting certain criteria—such as a minimum balance, a specific token type, or membership in a group—without revealing the asset's exact identity, its total value, or other sensitive metadata. This is achieved using zero-knowledge proofs (ZKPs), which generate a cryptographic proof that a statement is true without disclosing the underlying data. For example, a user could prove they hold over 1 ETH in a wallet without revealing the wallet's address or total balance.

The technical foundation for these proofs often involves commitment schemes and signature schemes like BBS+ or CL signatures. A user first creates a cryptographic commitment to their asset data, which acts as a blinded fingerprint. They then generate a ZKP that demonstrates knowledge of the data inside the commitment and that it satisfies the required predicate (e.g., balance > 100). Verifiers only receive the proof and the public commitment, not the raw data. Protocols like Semaphore for anonymous signaling or zkSNARKs-based token standards implement these principles to enable private transactions and credential checks on-chain.

Implementing selective disclosure typically follows a workflow: 1) Credential Issuance: An authority (like a protocol or wallet) signs a user's asset attributes, creating a verifiable credential. 2) Proof Generation: The user selects which attributes to disclose and which to keep private, then uses a ZKP library (e.g., snarkjs, circom) to generate a proof. 3) Verification: The verifier checks the proof against the public commitment and the disclosed attributes. On Ethereum, this can be done with a verifier smart contract. A simple check for a minimum balance might use a circuit to prove a committed number is within a range.

Key use cases include private proof-of-funds for DeFi loan collateral, age-restricted asset gating (proving you hold an NFT from a collection older than 30 days without revealing which one), and compliance-friendly privacy where institutions prove regulatory adherence without exposing full transaction graphs. The @semaphore-protocol library and zk-email's work on private credentials are practical starting points for developers. The core challenge is designing efficient ZKP circuits that balance proof generation time, gas costs for verification, and the complexity of the asset predicates being proven.

prerequisites
TUTORIAL

Prerequisites and Setup

This guide walks through implementing selective disclosure for proving asset ownership without revealing sensitive details, using Zero-Knowledge Succinct Non-Interactive Arguments of Knowledge (zk-SNARKs).

Selective disclosure is a cryptographic technique that allows a user to prove a specific claim derived from private data, such as owning an asset worth over a certain threshold, without revealing the underlying data itself—like the exact balance or transaction history. This is crucial for privacy-preserving applications in DeFi, credential verification, and regulatory compliance. The core mechanism relies on zero-knowledge proofs (ZKPs), specifically zk-SNARKs, which enable one party (the prover) to convince another (the verifier) that a statement is true without conveying any information beyond the validity of the statement itself.

To follow this implementation, you will need a foundational understanding of blockchain concepts, smart contracts, and basic cryptography. Essential tools include Node.js (v18 or later) and a package manager like npm or yarn. We will use the Circom domain-specific language for designing arithmetic circuits that define the computational statement to be proven, and the snarkjs library to generate and verify proofs. For testing and deployment, familiarity with a development framework such as Hardhat or Foundry is recommended, along with access to an Ethereum testnet like Sepolia.

The first step is to define the logic of your disclosure. For an asset proof, this involves creating a Circom circuit. A simple circuit might confirm that a private input balance is greater than a public threshold minAmount without revealing balance. The circuit code, compiled with circom, produces two key artifacts: a proving key and a verification key. The proving key is used to generate proofs from private witness data, while the verification key allows anyone to check the proof's validity, often embedded within a verifier smart contract.

Next, you'll integrate this with a client application. Using snarkjs, you generate a proof on the frontend by supplying the private witness (the actual balance) and the public inputs (the threshold). This proof, along with the public inputs, is sent to a verifier contract on-chain. The contract, which contains the embedded verification key, executes the verifyProof function. A return value of true confirms the claim is valid, enabling features like gated access to a service based on wealth proof, all while maintaining user privacy.

For production, consider security and efficiency. Use a trusted setup ceremony to generate your circuit's proving and verification keys, as a compromised setup can break the system's soundness. Optimize your circuit for gas costs, as on-chain verification can be expensive. Libraries like zk-kit or Semaphore offer higher-level abstractions for common identity and proof operations. Always audit your circuits and smart contracts, and test thoroughly with various inputs to ensure the proof system behaves correctly for both valid and invalid claims.

key-concepts-text
CORE CRYPTOGRAPHIC CONCEPTS

How to Implement Selective Disclosure for Asset Ownership Proofs

Selective disclosure allows users to prove ownership of a digital asset without revealing its specific details, a fundamental technique for privacy-preserving applications in Web3.

Selective disclosure is a cryptographic technique that enables a user to prove a specific claim derived from a credential or asset, while keeping the rest of the data private. In the context of asset ownership, this means you can prove you own an asset from a collection—like an NFT—without revealing which exact token ID you hold. This is crucial for privacy in scenarios like proving eligibility for a token-gated community or verifying a minimum balance for a loan application without exposing your full portfolio. The core mechanism relies on zero-knowledge proofs (ZKPs) or commitment schemes to separate the proof of possession from the proof of identity of the asset.

A common implementation uses Merkle proofs combined with digital signatures. First, the issuer (e.g., an NFT contract) creates a Merkle tree where each leaf is a commitment to an owner's address and their token ID. The root of this tree is published on-chain. To generate a proof, the user receives their specific leaf data and the corresponding Merkle path. They can then create a ZKP, such as a zk-SNARK, that demonstrates: 1) they know a secret (a digital signature from their private key), 2) this secret validates a leaf in the committed Merkle tree, and 3) the leaf contains an asset from a desired collection (proven by the leaf's structure). The actual token ID remains hidden within the proof.

For developers, libraries like Circom and snarkjs provide the tooling to construct these circuits. A basic Circom template for this proof might include components to verify an EdDSA signature against the prover's public key and the leaf hash, and to verify the Merkle path against the known public root. The user's client-side wallet would generate the witness and proof. This proof, which is just a few hundred bytes, can be submitted to a verifier contract on-chain. The Semaphore protocol is a practical example of this pattern, allowing anonymous signaling of group membership.

When implementing, key design decisions include choosing the commitment scheme and the type of ZKP. Pedersen commitments are often used for the leaf hashes as they are hiding and binding. For the ZKP system, Groth16 is efficient for on-chain verification but requires a trusted setup, while PLONK offers universal setup. You must also manage the nullifier to prevent proof replay; a unique nullifier derived from the user's identity and the context is published on-chain with the proof. Security audits for the circuit logic are non-negotiable, as bugs can lead to false proofs or privacy leaks.

The primary use cases extend beyond simple ownership. This technology enables anonymous voting (proving you hold a governance token), privacy-preserving credit checks (proving your NFT portfolio value exceeds a threshold), and selective KYC (proving you are from an authorized jurisdiction without showing your passport). As regulatory scrutiny increases, these techniques allow protocols to verify necessary compliance conditions while upholding the core Web3 principle of user sovereignty over personal data. The implementation complexity is a trade-off for the strong privacy guarantees it provides to end-users.

zk-snarks-implementation
ZK-PROOF FUNDAMENTALS

Step 1: Designing and Implementing a ZK-SNARK Circuit

This guide explains how to design a ZK-SNARK circuit to prove asset ownership without revealing the asset's identity, a core technique for selective disclosure.

Selective disclosure with ZK-SNARKs allows a user to prove they own an asset from a private set—like an NFT from a specific collection—without revealing which specific asset they hold. The cryptographic circuit must verify two key facts: that a secret input belongs to a known public set (the collection), and that the prover possesses the corresponding private key. This is typically implemented using a Merkle tree where the public root represents the entire collection and a private leaf represents the user's specific, undisclosed asset.

To build this, you first define the circuit's public and private inputs. The public inputs are the Merkle root of the asset set and the prover's public address. The private inputs are the specific asset identifier (the leaf), its authentication path (the Merkle proof), and the private key that signed a commitment. The circuit logic will: 1) hash the private leaf, 2) verify it reconstructs the public root using the provided Merkle path, and 3) verify a cryptographic signature showing control of the address. Popular frameworks like Circom or Halo2 are used to encode this logic.

Here is a simplified Circom template for the core verification. The circuit ensures the computed Merkle root from the private path matches the public root.

circom
template AssetOwnership(rootHeight) {
    // Public Inputs
    signal input merkleRoot;
    signal input publicKey;
    // Private Inputs
    signal input privateLeaf;
    signal input pathElements[rootHeight];
    signal input pathIndices[rootHeight];
    // Internal: Hash the leaf
    component leafHash = Poseidon(1);
    leafHash.in[0] <== privateLeaf;
    // Internal: Compute Merkle root from path
    component merkleVerifier = MerkleTreeChecker(rootHeight);
    merkleVerifier.leaf <== leafHash.out;
    for (var i = 0; i < rootHeight; i++) {
        merkleVerifier.pathElements[i] <== pathElements[i];
        merkleVerifier.pathIndices[i] <== pathIndices[i];
    }
    // Constraint: Computed root must equal public input root
    merkleVerifier.root === merkleRoot;
    // Additional component to verify signature of (root, publicKey) would be added here
}

After designing the circuit, you must compile it to generate the proving key, verification key, and Solidity verifier contract. Using the snarkjs library, you compile the Circom code (circom circuit.circom --r1cs --wasm), perform a trusted setup ceremony to generate the keys, and then export the verifier. The final step is integrating the proof generation into your application, where a user's client-side code uses the private witness to generate a proof, which is then sent to and validated by the on-chain verifier contract, completing the trustless disclosure.

bbs-signatures-implementation
IMPLEMENTATION

Step 2: Using BBS+ Signatures for Multi-Attribute Credentials

This guide explains how to implement selective disclosure for asset ownership proofs using BBS+ signatures, allowing a user to prove specific attributes from a credential without revealing the entire document.

BBS+ (Boneh-Boyen-Shacham with a pairing-friendly curve) is a cryptographic signature scheme that enables selective disclosure. Unlike standard signatures that verify an entire signed message, a BBS+ signature is generated over a set of individual message attributes. This allows a prover (e.g., a wallet holder) to create a zero-knowledge proof that they possess a valid signature from an issuer (e.g., a protocol or registry) for a subset of those attributes, without revealing the signature or the undisclosed attributes themselves. For asset ownership, this means proving you own a specific NFT or token meeting certain criteria without exposing your entire wallet balance or transaction history.

A credential for asset ownership would contain multiple attributes signed by the issuer. For example, a credential asserting ownership of a High-Value NFT might include: asset_type: ERC-721, contract_address: 0x..., token_id: 1234, owner_did: did:ethr:..., and timestamp. The BBS+ signature is computed over the cryptographic commitments of each of these individual attributes. The user then stores the complete signed credential locally. When needing to prove ownership to a verifier (e.g., a gated community or loan protocol), they can generate a proof for only the necessary attributes, such as asset_type and contract_address, while keeping token_id and owner_did hidden.

Implementing this requires a BBS+ library. Using the @mattrglobal/bbs-signatures JavaScript library, the flow involves three steps. First, the issuer creates the signature. They must hash each attribute to a scalar value in the signature's field. The core signing call is: bbs.sign({ messages: hashedMessages, secretKey: issuerSecKey, publicKey: issuerPubKey }). This produces a detached signature that is sent to the user alongside the plaintext attribute values.

Second, the user generates a proof for selective disclosure. They specify the indices of the attributes they wish to reveal (e.g., [0, 1] for the first two attributes) and keep the others hidden. The proof generation function is: bbs.createProof({ signature, publicKey: issuerPubKey, messages: hashedMessages, revealed: revealedIndices }). This creates a compact proof that cryptographically binds the revealed messages to the original issuer's public key, without leaking the signature or hidden messages. The proof and revealed attributes are sent to the verifier.

Finally, the verifier validates the proof. Using only the issuer's public key, the revealed attributes, and the proof, they call: bbs.verifyProof({ proof, publicKey: issuerPubKey, messages: revealedMessages }). A return value of true cryptographically guarantees that the revealed attributes were part of a set originally signed by the legitimate issuer. This enables trustless verification. This pattern is foundational for privacy-preserving DeFi, DAO governance, and credential-based access control, moving beyond all-or-nothing signature schemes.

disclosure-policy-design
IMPLEMENTATION GUIDE

Step 3: Designing and Enforcing Disclosure Policies

This guide explains how to implement selective disclosure mechanisms for proving asset ownership without revealing the full portfolio, using zero-knowledge proofs and policy contracts.

Selective disclosure allows a user to prove a specific claim about their assets—like owning at least 1 ETH—without exposing their total balance or other holdings. This is achieved using zero-knowledge proofs (ZKPs), which generate cryptographic proof that a private statement is true. For on-chain assets, this typically involves creating a Merkle proof that a specific asset is included in a committed Merkle root of the user's portfolio, without revealing the other leaves in the tree. The core cryptographic primitive enabling this is a zk-SNARK or zk-STARK, which allows the prover to convince a verifier of the statement's validity with minimal data transfer.

The implementation involves two main components: a policy contract and a proof generation client. First, define the disclosure logic in a smart contract. For example, a contract could verify a ZKP that proves: 1) The user controls a private key for an address, 2) That address holds an asset in a verified token contract, and 3) The asset's value meets a minimum threshold. The contract's verifyProof function would accept the proof and public inputs (like the token address and minimum value), then use a verification key to check the proof's validity against the agreed-upon circuit.

To generate the proof, a client-side application uses a ZK circuit library like Circom or Halo2. The circuit is programmed with the constraints for the disclosure policy. For an ERC-20 balance proof, the private inputs are the user's private key and full balance sheet, while the public output is a boolean attesting balance >= X. The user runs their data through the circuit to generate a proof, which is then submitted to the policy contract. Only the proof and the public output are revealed; the private keys and exact balances remain hidden.

Enforcement is handled on-chain by the policy contract. After verification, the contract can mint a verifiable credential or a soulbound token (SBT) to the user's address, serving as a temporary attestation of the proven claim. Other protocols can then trust this attestation by checking the SBT or by calling a view function on the policy contract. This creates a reusable, privacy-preserving proof system. Key considerations include circuit auditability, gas costs for verification (which can be high for complex proofs), and trusted setup requirements for some ZK systems like Groth16.

For practical development, start with a framework like Semaphore for identity proofs or zkKit for token-related circuits. A basic flow is: 1) Use circom to write a circuit proving a Merkle tree inclusion of a balance. 2) Perform a trusted setup to generate proving/verification keys. 3) Compile the circuit and generate proofs in a frontend using snarkjs. 4) Deploy a Solidity verifier contract with the generated verification key. 5) Build a policy contract that calls this verifier and issues an attestation upon success. Always use established libraries and consider using proof aggregation or recursive proofs to reduce on-chain verification costs for production systems.

CRYPTOGRAPHIC PRIMITIVES

ZK-SNARKs vs. BBS+ Signatures: A Comparison

Key technical differences between two leading cryptographic schemes for implementing selective disclosure in asset ownership proofs.

FeatureZK-SNARKs (e.g., Groth16)BBS+ Signatures (W3C Standard)Recommended Use Case

Cryptographic Assumption

Knowledge of Exponent, Pairing

q-Strong Diffie-Hellman

Security foundation

Proof Size

~200-300 bytes

~150-250 bytes

On-chain verification cost

Prover Complexity

High (trusted setup, circuit compilation)

Low (simple arithmetic operations)

Developer experience

Verifier Complexity

Low (constant-time pairing check)

Low (constant-time pairing check)

Smart contract gas cost

Selective Disclosure

Via circuit design (prove subset of inputs)

Native (derive proofs for any subset of messages)

Core functionality for ownership proofs

Trusted Setup Required

Operational security risk

Post-Quantum Security

Future-proofing consideration

Standardization Status

Protocol-specific (e.g., ZCash)

W3C Verifiable Credentials Data Model

Interoperability

SELECTIVE DISCLOSURE

Frequently Asked Questions

Common developer questions and solutions for implementing selective disclosure of asset ownership using zero-knowledge proofs.

Selective disclosure is a cryptographic technique that allows a user to prove a specific statement about their data without revealing the underlying data itself. For asset ownership, this means proving you own an asset meeting certain criteria (e.g., a balance > 1000 USDC, an NFT from a specific collection) without revealing your wallet address, the exact balance, or the specific token ID.

This is crucial for privacy-preserving applications like:

  • Private credentialing: Proving eligibility for a token-gated event or loan without doxxing your portfolio.
  • Compliance: Demonstrating you are not from a sanctioned jurisdiction by proving asset ownership in an allowed region, without revealing your citizenship.
  • Reputation systems: Building trust by proving historical on-chain activity without exposing all transaction details.

Traditional Merkle proofs reveal the specific leaf (your data), while ZK proofs like those from Circom or Halo2 allow you to prove membership in a set and predicate compliance simultaneously.

conclusion
IMPLEMENTATION GUIDE

Conclusion and Next Steps

This guide has covered the core principles and technical steps for implementing selective disclosure in asset ownership proofs. The following summary and next steps will help you solidify your understanding and apply these concepts.

Selective disclosure is a critical privacy-enhancing technique for Web3. It allows a user to prove they own a specific asset or meet certain criteria without revealing their entire wallet history or identity. The core mechanism relies on zero-knowledge proofs (ZKPs) or verifiable credentials to generate cryptographic attestations. For example, you can prove you hold an NFT from a specific collection or that your wallet balance exceeds a threshold, all while keeping the exact token ID or amount private. This moves beyond the all-or-nothing transparency of traditional blockchain queries.

To implement this, you typically follow a workflow: first, generate a cryptographic commitment to the private data (like an asset list). Next, create a proof that this committed data satisfies the public statement (e.g., "contains an asset from Collection X"). Finally, the verifier checks the proof against the commitment and the public statement. Libraries like Circuits for ZK-SNARKs or JSON Web Tokens (JWTs) with selective disclosure claims can be used. Always ensure your implementation uses audited, standard cryptographic primitives to avoid security pitfalls.

Your next steps should involve hands-on experimentation. Start by exploring frameworks such as zk-SNARKs via circom or zk-STARKs with cairo. For a credential-based approach, study the W3C Verifiable Credentials data model. Practical projects include building a proof-of-membership gate for a DAO or a private attestation for a credit score based on DeFi history. Remember to thoroughly test your circuits or credential schemas with invalid inputs to ensure robust verification logic.

Further research should focus on scalability and user experience. Proof aggregation (batching multiple proofs into one) and recursive proofs can reduce on-chain verification costs. Investigate identity protocols like Polygon ID or zkPass that abstract much of this complexity. The field is rapidly evolving, so follow developments in EIP-712 (structured data signing) and EIP-4337 (account abstraction) for native integration patterns. The ultimate goal is to make privacy-preserving proofs as seamless as a conventional wallet signature.

How to Implement Selective Disclosure for Asset Ownership Proofs | ChainScore Guides