In traditional finance, investor verification relies on centralized Know Your Customer (KYC) processes. Users submit sensitive personal documents—passports, utility bills, bank statements—to a central authority. This model creates significant risks: centralized data honeypots are prime targets for hackers, and users lose control over how their personal information is stored, shared, or monetized. For Web3 participants who value sovereignty, this is a fundamental conflict.
Setting Up a Decentralized Identity Solution for Investor Privacy
Introduction: The Need for Private Investor Verification
Traditional KYC processes compromise user privacy and create central points of failure. Decentralized identity offers a solution.
Decentralized Identity (DID) and Verifiable Credentials (VCs) provide a cryptographic alternative. Instead of handing over raw data, a user obtains a verifiable credential from a trusted issuer (like a government or accredited KYC provider). This credential is a cryptographically signed attestation stored in the user's private digital wallet. To prove they are verified, the user presents only a zero-knowledge proof (ZKP) derived from this credential, revealing nothing else. This shifts the paradigm from "verify by exposing" to "verify by proving."
The technical stack for this is built on open standards from the World Wide Web Consortium (W3C), primarily the Decentralized Identifiers (DIDs) v1.0 and Verifiable Credentials Data Model v2.0. A DID is a unique, user-controlled identifier (e.g., did:ethr:0x...) that anchors a public key. Verifiable Credentials are JSON-LD or JWT-formatted documents signed by an issuer's DID, containing claims (e.g., "accreditedInvestor": true) and a proof of signature.
For developers, implementing this involves integrating a wallet SDK (like SpruceID's didkit or Veramo) and a verification smart contract. The flow is: 1) User obtains a VC from an issuer off-chain. 2) The dApp requests a specific proof, like "prove you are over 18 and accredited." 3) The wallet generates a ZKP (e.g., using snarkjs or circuits). 4) The user submits the proof to a verifier contract. The contract checks the cryptographic proof against the issuer's known public key without seeing the underlying data.
This architecture enables compliant participation in regulated DeFi pools, token sales, and DAOs without sacrificing privacy. It reduces liability for dApp developers by outsourcing KYC compliance to specialized issuers and minimizes friction for users through reusable, portable credentials. The result is a system where privacy and compliance are not mutually exclusive, paving the way for broader institutional adoption of decentralized finance.
Prerequisites and System Architecture
A technical overview of the core components and requirements for building a privacy-preserving identity system for investors.
Building a decentralized identity (DID) solution for investor privacy requires a foundational understanding of its core architecture. The system is built on a trust triangle comprising the Holder (the investor), the Issuer (a trusted entity like a KYC provider), and the Verifier (the platform requiring proof). This model, formalized by the W3C Verifiable Credentials (VC) standard, shifts data control to the user. Instead of storing personal data on-chain, the system uses zero-knowledge proofs (ZKPs) and cryptographic signatures to enable selective, privacy-preserving disclosure.
The technical stack is anchored by a DID method, which defines how identifiers are created, resolved, and managed on a specific blockchain. Popular choices include did:ethr for Ethereum-compatible chains and did:key for a lightweight, offline approach. Each investor's DID Document contains public keys and service endpoints, acting as their cryptographic identity root. Credentials are issued as JSON-LD or JWT-formatted Verifiable Credentials, signed by the Issuer's DID. The Holder stores these in a digital wallet—a secure, user-controlled agent—such as SpruceID's Credible or Trinsic's ecosystem.
Privacy is enforced through Selective Disclosure and ZKPs. A verifier may request proof an investor is accredited without revealing their name or income. Using BBS+ signatures or zk-SNARKs circuits, the wallet can generate a proof that a valid, unrevoked credential exists satisfying the predicate, while keeping all other data private. The Verifiable Data Registry, typically a blockchain like Ethereum or Polygon, is used minimally to anchor DIDs and publish revocation registries (e.g., using a smart contract or a Revocation List 2020).
Key prerequisites for development include a Node.js (v18+) environment, familiarity with TypeScript, and a wallet SDK. Essential libraries are the Veramo Framework for agent-based credential management or Sphereon's SSI-SDK. You will need access to a blockchain node (via Infura or Alchemy) for DID operations and a secure storage layer for wallet data (e.g., SQLite or PostgreSQL). For advanced ZKP features, integrating Circom for circuit compilation and snarkjs for proof generation may be necessary.
The architecture's security hinges on proper key management. Decentralized Key Management Systems (DKMS) or hardware security modules (HSMs) are recommended for Issuer keys. Holder wallets should use secure enclaves on mobile devices. A critical design decision is the revocation mechanism; using status list 2021 credentials stored on IPFS with content identifiers (CIDs) anchored on-chain provides a scalable, privacy-preserving alternative to traditional certificate revocation lists.
Finally, interoperability is non-negotiable. Your system must support core W3C standards: Decentralized Identifiers (DID) v1.0, Verifiable Credentials Data Model v2.0, and the DIDComm v2 protocol for secure, encrypted messaging between agents. Testing should involve the OpenID Connect for Verifiable Credentials (OIDC4VC) flow to ensure compatibility with existing identity ecosystems. This architecture provides the robust, portable, and private foundation required for investor onboarding in regulated DeFi and real-world asset platforms.
Step 1: Setting Up the Credential Issuer
This guide walks through the initial setup of a credential issuer using the Verifiable Credentials (VC) data model, a core component for building privacy-preserving identity solutions in Web3.
A credential issuer is a trusted entity that creates and digitally signs Verifiable Credentials. In a decentralized identity (DID) system for investor privacy, this could be a KYC provider, a fund administrator, or a regulatory body. The issuer uses a Decentralized Identifier (DID) and its associated cryptographic keys to sign credentials, creating cryptographically verifiable attestations about an investor (the holder), such as accreditation status or country of residence. This setup moves away from centralized databases to a model where the user controls their data.
To begin, you must choose and configure your issuer DID method. Popular methods for this use case include did:ethr (Ethereum), did:key, or did:web. For an Ethereum-based stack, you can generate an did:ethr identifier using a library like ethr-did-registry. The core task is to create a DID document and manage the associated private key securely, as it will sign all issued credentials. The public key is published to the DID's method-specific registry (like an Ethereum smart contract for did:ethr), allowing anyone to resolve the DID and verify signatures.
Next, define your credential schema. This is a JSON or JSON-LD template that structures the data you will attest to. For investor credentials, schemas might include fields like accreditedInvestor (boolean), jurisdiction (string), or kycLevel (integer). Using a shared schema registry, like those on the Veramo platform or the Indicio network, ensures interoperability. Here is a minimal schema example defining an accreditation credential:
json{ "@context": ["https://www.w3.org/2018/credentials/v1"], "type": ["VerifiableCredential", "AccreditedInvestorCredential"], "issuer": "did:ethr:0x1234...", "credentialSubject": { "id": "did:ethr:0xabcd...", "accreditedStatus": true, "expiryDate": "2025-12-31" } }
With your DID and schema ready, implement the issuance logic using an SDK like Veramo or SpruceID's Credible. These frameworks handle the complex processes of signing, proof generation (e.g., JWT or JSON-LD Proofs), and optional credential status management. A critical consideration is selective disclosure. You should issue credentials that support Zero-Knowledge Proof (ZKP) techniques, allowing the investor to prove a claim (e.g., "I am accredited") without revealing the entire credential or their DID. Libraries like @veramo/credential-w3c provide methods for creating such verifiable presentations.
Finally, establish a secure endpoint for credential issuance. This is typically a backend API that authenticates the investor (the future credential holder), performs any necessary checks (like verifying source documents), and returns the signed Verifiable Credential. The endpoint must protect the issuer's private key, often using Hardware Security Modules (HSMs) or cloud KMS solutions in production. The credential is then delivered to the investor's digital wallet (e.g., a mobile app using Veramo Agent), where it is stored securely in their custody, completing the issuance flow.
Step 2: Investor Wallet Integration and Credential Storage
This guide explains how to integrate a self-custody wallet with a decentralized identity (DID) protocol to manage investor credentials privately and verifiably.
The foundation of investor privacy in Web3 is a decentralized identifier (DID). Unlike traditional usernames or emails tied to a central database, a DID is a cryptographically verifiable identifier anchored on a blockchain, such as Ethereum or Polygon. It is controlled solely by the investor through their private keys. For this setup, you will use the wallet address from Step 1 as the basis for a DID, typically following the did:ethr or did:pkh method. This creates a permanent, self-sovereign identity that the investor uses across applications without relying on a centralized authority.
With a DID established, you can issue and store Verifiable Credentials (VCs). A VC is a tamper-proof digital attestation, like a KYC approval or accredited investor status, issued by a trusted entity (the issuer). The credential is cryptographically signed and linked to the investor's DID. The investor stores these credentials in a digital wallet that supports the W3C Verifiable Credentials data model, such as a wallet with SSI (Self-Sovereign Identity) capabilities. Crucially, the credential data itself is stored off-chain (e.g., on IPFS or the user's device), with only the essential cryptographic proofs referenced on-chain for verification, preserving data minimalism and privacy.
To implement this, developers use libraries like ethr-did-resolver and did-jwt-vc from the Identity Foundation. The process involves: 1) Creating a DID document for the user's Ethereum address, 2) Having an issuer sign a JWT-formatted credential with their private key, and 3) Allowing the user to present this credential. The verification happens by resolving the DID to check the issuer's public key on-chain and validating the JWT signature, all without exposing the underlying personal data. This ensures investor attributes are proven without being permanently leaked on a public ledger.
For secure credential storage, the wallet must manage Decentralized Key Management (DKMs). Solutions like Ceramic Network's Identity or MetaMask Snaps allow wallets to interact with DID protocols and store encrypted credential data in decentralized storage networks. The private keys for signing and decrypting these credentials never leave the user's secure enclave or hardware wallet. This architecture ensures that even the application front-end cannot access raw credential data, putting the investor in full control of when and with whom they share their verified attributes.
The final step is selective disclosure. Using Zero-Knowledge Proofs (ZKPs) via protocols like Sismo or Polygon ID, an investor can prove a credential's validity (e.g., "I am an accredited investor") without revealing the credential's contents or their full DID. The wallet generates a ZK proof from the stored VC and presents only that proof for verification. This maximizes privacy for on-chain transactions or gated community access, as the verifying smart contract only checks the proof's validity on-chain without processing any personal data.
Step 3: Generating Zero-Knowledge Proofs for Selective Disclosure
This step explains how to generate zero-knowledge proofs that allow investors to prove specific claims about their identity or credentials without revealing the underlying data.
A zero-knowledge proof (ZKP) is a cryptographic protocol where one party (the prover) can prove to another (the verifier) that a statement is true, without revealing any information beyond the validity of the statement itself. In a decentralized identity (DID) context, this enables selective disclosure. For example, an investor can prove they are an accredited investor, are over 18, or hold a specific credential from a trusted issuer, without exposing their full name, date of birth, or the credential's detailed contents. This is a fundamental shift from the all-or-nothing data sharing model of traditional systems.
To generate a ZKP, you need a circuit that defines the logical statement to be proven. This circuit is a program, often written in a domain-specific language like Circom or Noir, that encodes the constraints of the claim. For an accreditation proof, the circuit might verify that a signed credential from a known issuer exists in the user's wallet, that it has not been revoked, and that its accredited field is set to true. The user's wallet acts as the prover, running this circuit with their private data to generate a proof.
Here is a simplified conceptual example of a Circom circuit template for proving accreditation:
circomtemplate AccreditedInvestor() { // Private inputs (known only to prover) signal input issuerPublicKey; signal input credentialSignature; signal input isAccredited; signal input nullifier; // For preventing proof replay // Public inputs (known to verifier) signal output verified; // Constraint: Verify the credential's cryptographic signature component sigVerify = VerifyEdDSASignature(); sigVerify.publicKey <== issuerPublicKey; sigVerify.signature <== credentialSignature; // (Message hash logic would be included here) // Constraint: Check the accredited flag is true (1) isAccredited * (1 - isAccredited) === 0; // Ensures binary value isAccredited === 1; // Constraint: Generate a unique nullifier hash to prevent double-spending the proof component nullifierHash = Poseidon(2); nullifierHash.in[0] <== nullifier; nullifierHash.in[1] <== issuerPublicKey; verified <== 1; }
This circuit outputs verified=1 only if all constraints pass. The actual proof is a small, verifiable piece of data generated from running this circuit.
Once the circuit is compiled, the prover uses it with a ZK-SNARK or ZK-STARK proving system. Libraries like snarkjs (for JavaScript) or arkworks (for Rust) are commonly used. The proving process takes the private witness data (the user's secret credentials) and the public parameters to generate a proof. This proof, along with the public outputs (like the nullifier hash), is then sent to the verifier—typically a smart contract on-chain. The verifier contract, which contains the circuit's verification key, can check the proof's validity in constant time, often for less than 200k gas on Ethereum.
The nullifier is a critical component for privacy and security. It is a unique, secret value hashed with the issuer's key to create a public nullifierHash. This hash is published when the proof is verified on-chain, preventing the same proof from being reused (replay attack). However, because the original nullifier is secret, the hash does not reveal which user submitted the proof, preserving anonymity. This pattern is essential for credential systems and anonymous voting within investor DAOs.
In practice, developers integrate ZKP generation into wallet applications or backend services. Frameworks like iden3's circom and zkKit, or platforms like Sismo and Polygon ID, provide SDKs to abstract much of the cryptographic complexity. The final step is having the verifier smart contract—governed by the investment platform's rules—check the proof. A successful verification grants the user access to private deal rooms or permissioned functions, all while keeping their underlying identity data confidential and under their control.
Step 4: Building the On-Chain Verifier Contract
This section details the development of the smart contract that validates investor credentials on-chain without exposing the underlying data.
The core of a privacy-preserving decentralized identity (DID) system is the on-chain verifier contract. This smart contract does not store or see the user's private data. Instead, it contains the logic to verify a Zero-Knowledge Proof (ZKP). When an investor wants to prove they are accredited, their wallet submits a cryptographic proof, generated off-chain, to this contract. The contract's verifyProof function checks the proof against a public verification key stored in the contract. A return value of true confirms the investor's claim is valid, enabling access to a gated investment pool.
Setting up the contract requires a verification key, which is the public counterpart to a proving key used to generate ZKPs. This key is specific to the credential circuit—a program that defines the rules for accreditation (e.g., netWorth > $1M). You generate this key pair using a tool like SnarkJS for Circom or gnark for Go. The verification key is then hardcoded into the contract's constructor or initialized by a deployer. Popular libraries for on-chain verification include the Semaphore verifier contract or circomlib's Verifier.sol template, which handle the complex elliptic curve pairing operations.
Here is a simplified interface for a typical verifier contract:
solidityinterface IZKVerifier { function verifyProof( uint[2] memory a, uint[2][2] memory b, uint[2] memory c, uint[1] memory input ) external view returns (bool); }
The parameters a, b, and c are the ZKP components, and input is the public signal (e.g., a hash of the investor's DID). The contract must be deployed on the same network where the investment dApp operates, such as Ethereum Mainnet, Arbitrum, or Base. Gas optimization is critical, as ZK verification can be computationally expensive.
Integrating this verifier with your application's access control is the final step. Your main investment pool contract will import the verifier and call it within a modifier like onlyVerifiedInvestor. The investor's client-side SDK (e.g., iden3 or Sismo) generates the proof locally and submits the transaction. This pattern ensures selective disclosure—the protocol learns only that the investor is accredited, not their income or address. For production, consider using a verifier registry contract to allow for key updates without redeploying your main application logic.
Comparison of Decentralized Identity Frameworks
Key technical and privacy features of leading DID frameworks for investor onboarding and KYC/AML compliance.
| Feature / Metric | Verifiable Credentials (W3C) | Soulbound Tokens (SBTs) | zkPassport / zkKYC |
|---|---|---|---|
Data Minimization | |||
Selective Disclosure | |||
Revocation Mechanism | Status List / Registry | Non-Transferable | On-Chain Attestation |
Primary Standard | W3C VC-DATA-MODEL 2.0 | ERC-721 / ERC-1155 | Custom ZK Circuits |
Trust Model | Issuer & Verifier | Issuer & Blockchain | Issuer & Zero-Knowledge Proof |
Typical Issuer | Regulated Entity (KYC Provider) | DAO / Protocol | Identity Verifier (e.g., Civic) |
Gas Cost for Verification | Off-Chain (Low) | On-Chain (High) | On-Chain Proof (Medium-High) |
Privacy Leakage Risk | Low (Correlation) | High (Public Ledger) | Very Low (ZK Proofs) |
Interoperability | High (DIDComm, CHAPI) | Medium (EVM Chains) | Low (Protocol-Specific) |
Step 5: Full-Stack Application Integration
Integrate a decentralized identity (DID) solution into a full-stack application to protect investor privacy while enabling compliant on-chain interactions.
A decentralized identity (DID) solution allows investors to prove eligibility—such as accredited investor status or KYC verification—without revealing their underlying personal data on-chain. This is achieved using verifiable credentials (VCs), which are cryptographically signed attestations from trusted issuers (e.g., a compliance provider). The investor holds these credentials in a secure wallet, like a browser extension or mobile app, and can generate zero-knowledge proofs (ZKPs) to satisfy application logic. This architecture shifts the paradigm from data collection to proof verification, minimizing privacy exposure and regulatory risk for the application.
The integration flow involves three core components: the issuer backend, the user wallet, and your application smart contracts. First, set up an issuer service using a framework like SpruceID's Credential Kit or Veramo. This service will issue signed VCs to users after off-chain verification. Your frontend must then connect to a user's wallet that supports VCs, such as SpruceID's Sign-In with Ethereum toolkit or a wallet with W3C VC support. The wallet will request the necessary credential and generate a proof.
On the smart contract side, implement a verifier that can check the proof. For Ethereum, use a ZK-SNARK verifier contract, often generated by tools like Circom and snarkjs. The contract's verification function should accept the proof and public signals as inputs. A common pattern is to gate a function with a modifier that calls this verifier. For example, a function mintPrivateSaleNFT() would require a valid proof of an accredited investor credential. The contract logic only sees the proof's validity, not the investor's income or address.
In your application's frontend (e.g., a Next.js dApp), orchestrate the flow. Use a library like @spruceid/siwe to authenticate the user's Ethereum account. Then, request a specific VC from their wallet and ask the wallet to generate a proof for your contract's verifier. Submit this proof along with the transaction. Handle states for credential_requested, proof_generated, and transaction_pending. Always provide clear user feedback, as the proof generation can be computationally intensive for the user's device.
For testing, use developer tools from your chosen DID stack. SpruceID and Veramo offer local issuers and test wallets. Deploy your verifier contract to a testnet and simulate the entire flow. Key metrics to monitor are gas cost of verification, proof generation time user-side, and credential revocation status. Remember, the issuer must maintain a revocation registry (like a smart contract or indexed database) that your verifier can query or that is referenced in the proof to ensure credentials are still valid.
This integration creates a powerful privacy-preserving funnel. Investors interact with your protocol using a pseudonymous address, yet you can enforce complex, real-world compliance rules. The sensitive data never touches your servers or the public blockchain, significantly reducing liability. The end result is a more secure, compliant, and user-respecting application that aligns with the core tenets of Web3.
Setting Up a Decentralized Identity Solution for Investor Privacy
This guide explains how to implement a decentralized identity (DID) system to protect investor privacy in Web3 applications, using verifiable credentials and selective disclosure.
Decentralized Identity (DID) provides a privacy-preserving alternative to traditional KYC by allowing users to control their own credentials. Instead of storing sensitive investor data on a centralized server, a DID system uses verifiable credentials (VCs) issued by trusted entities. An investor can prove they are accredited or have passed a background check without revealing their full identity or personal details. Core standards for this are defined by the World Wide Web Consortium (W3C) in their DID Core specification. This shifts the paradigm from data collection to cryptographic proof.
The technical foundation relies on DID methods and verifiable data registries. A DID method, like did:ethr or did:key, defines how a DID is created, resolved, and managed on a specific blockchain or network. The DID document, stored on a registry, contains public keys and service endpoints for interaction. For issuing a credential, an issuer (like a KYC provider) signs a VC containing claims (e.g., "accreditedInvestor": true) with their private key. The investor holds this VC in a digital wallet, such as one built with the SpruceID SDK, which manages private keys and presentation of proofs.
Selective disclosure is the key privacy feature. Using zero-knowledge proofs (ZKPs) or BBS+ signatures, an investor can generate a proof that cryptographically verifies a specific claim from a VC without exposing the entire document. For example, a DeFi protocol can request proof that a user is an accredited investor. The user's wallet creates a proof derived from their VC, and the protocol's smart contract verifies the issuer's signature and the proof's validity. This process ensures compliance without exposing the user's name, address, or other irrelevant data. Libraries like @veramo/core facilitate this credential handling.
Implementation involves several steps. First, choose a DID method and registry (e.g., Ethereum for did:ethr, or Ceramic Network for mutable documents). Next, integrate an SDK like Veramo or SpruceID into your application backend to act as an issuer and verifier. The investor-facing dApp must integrate a wallet capable of holding VCs, such as MetaMask with Snap functionality or a dedicated identity wallet. The verification logic, often a set of smart contract functions, must check the proof's validity against the known public key of the trusted issuer. This creates a trust triangle between issuer, holder, and verifier.
Key security considerations include secure key management for the user's wallet, ensuring the revocation status of credentials is checked (e.g., via a revocation registry), and auditing the ZK circuits or cryptographic protocols used for proof generation. Privacy risks arise if the DID itself becomes a correlatable identifier across applications; using pairwise DIDs (unique DIDs for each relationship) mitigates this. For developers, starting with testnets and existing infrastructure reduces risk. The European Union's eIDAS2 regulation and projects like Ontology's DID provide real-world frameworks and examples of these systems in production.
Essential Tools and Documentation
These tools and standards are commonly used to build decentralized identity (DID) systems that protect investor privacy while meeting regulatory and operational requirements. Each resource supports verifiable credentials, selective disclosure, or privacy-preserving compliance workflows.
Frequently Asked Questions
Common technical questions and troubleshooting for implementing decentralized identity (DID) solutions focused on investor privacy, covering standards, verification, and on-chain integration.
A Decentralized Identifier (DID) is a globally unique, persistent identifier that an individual or entity controls, independent of any centralized registry. It is defined by the W3C standard and typically looks like did:example:123456. A blockchain wallet address (e.g., 0x...) is a specific type of identifier for a cryptographic key pair on a particular chain.
Key Differences:
- Control & Portability: A DID is controlled by the holder via private keys and can be resolved to a DID Document containing public keys and service endpoints. A wallet address is tied to a specific blockchain network.
- Function: A DID is a general-purpose identifier for verifiable credentials and interactions. A wallet address is primarily for receiving assets and signing transactions.
- Standardization: DIDs follow the W3C DID Core specification, while wallet addresses are chain-specific. You can embed a wallet address within a DID Document as a verification method.
Conclusion and Next Steps
You have now configured a decentralized identity (DID) system using verifiable credentials to protect investor privacy. This guide covered the core setup, but the journey continues with integration and scaling.
The solution you've built establishes a foundational privacy layer for investor interactions. By using DID methods like did:ethr or did:key and verifiable credentials (VCs) issued via a smart contract, you enable investors to prove claims—such as accredited status or jurisdiction—without revealing their underlying personal data. This shifts the paradigm from data collection to cryptographic proof verification, minimizing custodial risk. Your issuer service acts as a trusted root, while the investor's wallet (the holder) maintains control. The verifier (your platform) only receives the signed, tamper-proof credential.
To move from prototype to production, several critical next steps are required. First, audit your smart contracts thoroughly, especially the credential registry and revocation logic. Services like OpenZeppelin Defender can help manage upgrades and admin functions securely. Second, design a robust key management and recovery flow for users; consider integrating with wallet providers like MetaMask Snaps or dedicated DID wallets such as SpruceID's Sign-In with Ethereum. Third, plan for interoperability by supporting the W3C Verifiable Credentials Data Model standard and exploring cross-chain attestation protocols like EAS (Ethereum Attestation Service).
Finally, consider the broader architecture. For high-throughput applications, you may need to index credential status off-chain using a solution like Ceramic Network or IPFS for scalable storage, referencing the content hash on-chain. Monitor gas optimization for credential issuance and implement selective disclosure techniques, such as zero-knowledge proofs via Circom or zkSNARKs libraries, to allow investors to prove specific credential attributes without exposing the entire document. This enhances privacy further for complex compliance checks.
The landscape of decentralized identity is evolving rapidly. Stay informed by contributing to and following standards bodies like the Decentralized Identity Foundation (DIF) and the W3C Credentials Community Group. Experiment with emerging privacy-preserving verification SDKs from projects like Polygon ID or Sismo. By implementing these next steps, you transition your solution from a functional prototype to a resilient, production-ready system that genuinely empowers investor privacy and trustless verification.