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

Setting Up a Decentralized Identity (DID) Integration for KYC

A step-by-step developer tutorial for building a smart contract system that verifies KYC credentials using W3C standards and zero-knowledge proofs.
Chainscore © 2026
introduction
INTRODUCTION

Setting Up a Decentralized Identity (DID) Integration for KYC

This guide explains how to integrate Decentralized Identity (DID) systems to enhance Know Your Customer (KYC) processes, moving from centralized data silos to user-controlled verification.

Decentralized Identity (DID) provides a user-centric model for digital credentials, fundamentally shifting control from centralized institutions to the individual. In the context of KYC, this means verified identity attributes—like proof of age or residency—are issued as verifiable credentials (VCs) stored in a user's digital wallet. A service provider can then request proof of these credentials without ever storing the user's raw personal data. This approach, built on standards from the World Wide Web Consortium (W3C), reduces data breach risks, streamlines compliance, and improves user privacy through selective disclosure.

The core components of a DID-based KYC flow are the issuer, holder, and verifier. A regulated entity, such as a bank or government agency, acts as the issuer, creating and signing verifiable credentials. The end-user is the holder, storing these credentials in a secure wallet like MetaMask with Snap or a specialized SSI wallet. The verifier is the application, such as a DeFi platform or exchange, that requests proof. They interact via a DID method—a specification for creating and managing DIDs on a specific blockchain or system, such as did:ethr for Ethereum or did:key for a more portable approach.

To implement this, developers typically work with SDKs from DID protocol providers. For example, using the Veramo framework, you can create a verifier service that generates a QR code containing a presentation request. The user scans this with their wallet, which locally proves they hold a valid credential from a trusted issuer, and returns a verifiable presentation. Your backend verifies the presentation's cryptographic signature against the issuer's public DID on the blockchain. This entire process can be executed without exposing the user's DID or personal details to your servers, minimizing liability.

Key technical considerations include choosing a DID method suitable for your stack, managing revocation status (often via a smart contract or a revocation registry), and defining a credential schema for the data you need to verify. For instance, a schema for a KYC credential might include fields for fullName, birthDate, and identificationDocumentCountry. It's crucial to integrate with trusted issuers whose DIDs are recognized within your ecosystem. Projects like Ontology's ONT ID, Microsoft's ION on Bitcoin, and the European Blockchain Services Infrastructure (EBSI) are pioneering real-world implementations.

The benefits extend beyond privacy. DID-based KYC enables portable identity, where a user verified by one service can seamlessly access others, reducing friction. It also allows for granular consent; a user can prove they are over 18 without revealing their exact birthdate. For developers, this model can simplify compliance by outsourcing the complex identity verification to specialized issuers, allowing you to focus on core application logic while adhering to regulations like GDPR through data minimization by design.

prerequisites
SETUP

Prerequisites

Before integrating a Decentralized Identity (DID) system for KYC, you need to establish the foundational technical and conceptual environment. This section outlines the essential tools, knowledge, and accounts required.

A Decentralized Identity (DID) is a user-controlled, portable identifier anchored on a blockchain. Unlike traditional KYC where data is stored centrally, DID-based KYC uses verifiable credentials—tamper-proof digital attestations issued by trusted entities. You must understand core standards: the W3C's DID Core specification defines the data model, while Verifiable Credentials Data Model governs the credentials themselves. Familiarity with these concepts is non-negotiable for a proper implementation.

You will need a development environment capable of interacting with blockchain networks. This includes Node.js (v18 or later) and a package manager like npm or yarn. Essential libraries include did-resolver and veramo or daf for higher-level DID operations, or ethr-did-resolver for Ethereum-based identities. For smart contract interaction, a toolkit like Hardhat or Foundry is recommended. Ensure you have a basic understanding of public-key cryptography, as DIDs are fundamentally based on key pairs.

Select a DID method that aligns with your chain and use case. For Ethereum, did:ethr (used by Veramo) and did:pkh (used by Ceramic) are popular. For Polygon, did:polygonid is a dedicated option. You will need access to a blockchain node via a provider like Infura, Alchemy, or a public RPC endpoint for the chosen network. Acquire testnet ETH or MATIC for deploying any necessary registry contracts or paying gas fees during development.

The integration involves three primary roles: the issuer (the KYC provider), the holder (the end-user), and the verifier (your application). You must decide which role your system will fulfill. As a verifier, your focus is on requesting and validating credentials. You'll need to design the presentation request, specifying which credential types (e.g., KYCAMLAttestation) and claims (e.g., birthDate) are required from the user's digital wallet.

Finally, set up a wallet for testing. Users will interact with your system using DID-enabled wallets like MetaMask (with Snap capabilities), Spruce ID's Sign-In with Ethereum, or walletconnect. You should install one of these wallets to test the flow from the holder's perspective. Having a clear test plan for issuing a mock credential and having your application verify it is crucial before moving to production integrations with actual KYC providers like Bloom or Veriff.

architecture-overview
SYSTEM ARCHITECTURE AND FLOW

Setting Up a Decentralized Identity (DID) Integration for KYC

This guide outlines the technical architecture and data flow for integrating a Decentralized Identity (DID) system into a traditional Know Your Customer (KYC) process, enabling user-controlled, verifiable credentials.

A DID-based KYC system shifts the paradigm from centralized data silos to a user-centric model. The core components are: the Issuer (a regulated entity like a bank), the Holder (the end-user), and the Verifier (a service requiring KYC). They interact using Verifiable Credentials (VCs)—tamper-evident, cryptographically signed attestations—and Decentralized Identifiers (DIDs)—unique, self-sovereign identifiers anchored on a blockchain or distributed ledger. This architecture minimizes data exposure and puts the user in control of their credentials.

The technical flow begins with the Holder generating their own DID, typically using a wallet or identity agent. The Issuer, after performing its standard offline KYC checks, creates a Verifiable Credential (e.g., proof of identity, residency) and signs it cryptographically with its own DID. This VC is issued directly to the Holder's wallet, where it is stored locally or in a private cloud vault. The Issuer never stores the VC; they only maintain an audit log of the issuance event, often recorded as an immutable event on a ledger for non-repudiation.

When the Holder wants to access a service from a Verifier, they do not send raw credentials. Instead, they create a Verifiable Presentation (VP). This is a package, signed by the Holder's DID, that contains selective disclosures from one or more VCs. For example, a VP could prove the Holder is over 18 without revealing their birthdate. The presentation is sent to the Verifier via a secure, user-consented channel, such as a QR code scan or a deep link.

The Verifier's backend must perform several checks. First, it resolves the DIDs of both the Holder and the Issuer from their respective DID methods (e.g., did:ethr:, did:web:) to obtain public keys. It then cryptographically verifies the signatures on the VP and the embedded VC. Finally, it checks the credential's status against a revocation registry (like a smart contract or a verifiable data registry) to ensure it hasn't been revoked. Only after these automated checks pass is the KYC considered verified.

Implementing this requires careful choice of standards and tooling. The foundational specifications are the W3C's Verifiable Credentials Data Model and Decentralized Identifiers recommendations. For Ethereum-based systems, tools like Veramo or SpruceID's Kepler and Sign-In with Ethereum (SIWE) provide frameworks for managing DIDs and VCs. A critical design decision is selecting the DID method and revocation mechanism (e.g., smart contract-based registries, accumulators) that balance trust, cost, and performance for your use case.

This architecture offers significant advantages: reduced liability for verifiers who no longer store sensitive PII, improved user experience through portable credentials, and enhanced privacy via zero-knowledge proofs. However, it introduces new complexities like key management for users and the need for legal recognition of digital signatures. Successful integration hinges on aligning this decentralized flow with existing regulatory compliance frameworks like Travel Rule or AML directives, often requiring Issuers to remain the ultimate authority for credential validity.

key-concepts
DECENTRALIZED IDENTITY

Core Concepts and Standards

Essential protocols and frameworks for implementing decentralized identity (DID) and verifiable credentials for compliant KYC processes.

04

The Trust Triangle & Roles

Every DID/VC system involves three core roles:

  • Issuer: The trusted entity (e.g., a KYC provider) that creates and signs Verifiable Credentials.
  • Holder: The user (subject) who receives and stores the credential in their digital wallet.
  • Verifier: The service (e.g., a DeFi protocol) that requests and cryptographically verifies the presented credentials.

This model decouples issuance from verification, removing the need for verifiers to directly query issuers.

05

Zero-Knowledge Proofs for KYC

Zero-Knowledge Proofs (ZKPs), like zk-SNARKs or zk-STARKs, can be applied to Verifiable Credentials to enable privacy-preserving verification. Instead of presenting a raw credential, a user generates a ZK proof that they possess a valid credential meeting specific criteria (e.g., "I am over 18" or "I am accredited") without revealing the underlying data or the issuer's identity. This is a key technology for compliant yet private on-chain KYC.

schema-design
FOUNDATION

Step 1: Designing the Credential Schema

The credential schema defines the structure and data types for the verifiable credentials in your KYC system, ensuring interoperability and trust.

A credential schema is a formal specification that defines the structure, data types, and semantic meaning of the claims within a Verifiable Credential (VC). For KYC, this is the blueprint for what information is attested to, such as fullName, dateOfBirth, nationalIdNumber, and residentialAddress. Using a standardized schema ensures that credentials issued by your system can be understood and reliably processed by any verifier in the decentralized identity ecosystem, preventing data misinterpretation.

Schemas are typically published to a decentralized registry to become immutable, publicly referenceable artifacts. Common locations include the Ethereum blockchain via smart contracts, IPFS (InterPlanetary File System), or a trusted web domain. The schema is referenced in the credential by its unique identifier (e.g., a DID URL or IPFS hash). This allows a verifier to fetch the schema independently to validate the credential's structure, separating the trust in the data's format from the trust in the issuer's signature.

When designing your KYC schema, adhere to established W3C Verifiable Credentials data model conventions and consider reusing or extending existing schemas from communities like the Decentralized Identity Foundation (DIF). For example, you might start with a base Person schema and add KYC-specific fields. Define each property's type (string, number, boolean), format (e.g., date-time for dates), and whether it is mandatory. Avoid storing raw, sensitive PII directly in credential claims; instead, use cryptographic hashes or zero-knowledge proof-friendly encodings where possible.

Here is a simplified example of a JSON-LD schema definition for a basic KYC credential, publishable to IPFS:

json
{
  "@context": ["https://www.w3.org/2018/credentials/v1"],
  "id": "ipfs://QmExampleSchemaHash",
  "type": "JsonSchemaValidator2018",
  "name": "BasicKYC",
  "author": "did:ethr:0x1234...",
  "schema": {
    "$id": "https://yourapp.com/schemas/kyc-v1.json",
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
      "fullName": { "type": "string" },
      "dateOfBirth": { "type": "string", "format": "date" },
      "countryOfResidence": { "type": "string" }
    },
    "required": ["fullName", "dateOfBirth", "countryOfResidence"]
  }
}

The final step in schema design is versioning. Implement a clear versioning strategy (e.g., appending -v1.1 to the schema ID) to manage updates without breaking existing issued credentials. Once published, the schema is immutable. Any change requires deploying a new schema with a new identifier, allowing issuers to migrate to the new version while old credentials remain valid and verifiable against the original schema they reference.

proof-generation
ZK-SNARK IMPLEMENTATION

Step 2: Generating the Zero-Knowledge Proof

This step transforms verified user data into a privacy-preserving cryptographic proof, allowing verification without exposing the underlying information.

With your user's verified credentials stored in a W3C Verifiable Credential format on a decentralized storage layer like IPFS or Ceramic, the next step is to generate a Zero-Knowledge Proof (ZKP). This proof cryptographically attests that the user possesses credentials satisfying your KYC policy—such as being over 18 and a resident of a specific country—without revealing the actual date of birth or passport number. For this, you'll use a ZK-SNARK circuit library like circom or a higher-level framework such as zkSNARKs.js or SnarkJS.

First, you must define the logical circuit that represents your KYC rules. In circom, this is a .circom file. For example, a circuit to prove age >= 18 without revealing the birthdate would take a secret birthdate and a public current date as inputs, compute the age, and output a signal confirming the age is 18 or older. The circuit's constraints ensure the computation is correct. You then compile this circuit to generate proving and verification keys, which are essential for the proof generation and verification phases.

Using the compiled circuit and the proving key, your application's backend or a client-side SDK generates the actual proof. The process involves providing the witness—the private inputs (the actual birthdate) and public inputs (the current date and the required minimum age). A library like snarkjs can handle this: snarkjs groth16 prove circuit_final.zkey witness.wtns proof.json public.json. The output is a small proof.json file and a public.json file containing the public signals. Only the proof and public signals are shared with the verifier; the private witness data remains entirely hidden.

For developers, integrating this into a Node.js backend might involve using the ffjavascript library suite. A common pattern is to have an API endpoint that accepts the hashed identifiers of the user's Verifiable Credentials, retrieves the necessary private data from a secure, user-consented session, runs the witness calculation and proof generation, and returns the proof data. It's critical that the private data never leaves a trusted environment controlled by the user or your secure server during this phase.

The generated ZKP is extremely compact, typically only a few hundred bytes, making it cheap to store on-chain. This proof, along with the public signals, is what you will submit in the next step to the verifier contract on-chain. This approach ensures selective disclosure and data minimization, core principles of privacy-preserving KYC. Popular real-world implementations for identity can be studied in projects like Semaphore for anonymous signaling or zkPass for private data verification.

contract-verification
DID INTEGRATION

Step 3: Writing the On-Chain Verifier Contract

This step focuses on building the smart contract that will verify decentralized identity credentials on-chain, enabling trustless KYC checks for your application.

The on-chain verifier is the core component that validates Verifiable Credentials (VCs) issued by a trusted identity provider. Its primary function is to check the cryptographic proof attached to a credential—typically a JSON Web Token (JWT) or a W3C Verifiable Credential—against a known public key or decentralized identifier (DID) stored on-chain. This contract does not store personal data; it only verifies the signature and checks the credential's status (e.g., not revoked) and claims (e.g., isAbove18: true).

You'll need to choose a verification library compatible with your blockchain. For Ethereum and EVM chains, consider using Veramo's @veramo/cli for off-chain preparation or libraries like ethr-did-resolver and did-jwt-vc for on-chain logic. For non-EVM chains, you may need to implement custom signature verification. The contract will expose a function, such as verifyCredential(bytes memory _vcJwt, address _user), that returns a boolean.

Here is a simplified example of a verifier contract stub using a hypothetical CredentialVerifier library. It assumes the issuer's DID document and public key are already registered on-chain in a trusted registry contract.

solidity
import "./ICredentialVerifier.sol";

contract KYCVerifier {
    ICredentialVerifier public verifier;
    address public trustedRegistry;

    constructor(address _verifier, address _registry) {
        verifier = ICredentialVerifier(_verifier);
        trustedRegistry = _registry;
    }

    function verifyKYC(address user, bytes memory vcJWT) public returns (bool) {
        // 1. Extract the issuer DID from the JWT
        // 2. Resolve the issuer's public key from the trustedRegistry
        // 3. Use the verifier library to validate the JWT signature
        // 4. Parse the VC payload and check for required claims (e.g., KYCValidated)
        // 5. Return true if all checks pass
        bool isValid = verifier.verify(vcJWT, trustedRegistry);
        if (isValid) {
            emit CredentialVerified(user, block.timestamp);
        }
        return isValid;
    }
}

Critical security considerations for your verifier include: - Trust Anchor Management: How are issuer DIDs and public keys registered and updated? Use a governance-controlled or decentralized registry. - Proof Expiry: Credentials should have an expirationDate claim that the contract must check. - Revocation Checks: The contract must query a revocation registry (like a smart contract or a verifiable data registry) to ensure the credential hasn't been revoked. - Gas Optimization: JWT verification can be gas-intensive. Consider using optimized precompiles for elliptic curve operations on supported chains or moving heavy computation off-chain with zk-SNARKs.

After deployment, your dApp's frontend or backend will call this verifier contract when a user attempts a gated action. The user signs a message with their wallet (which controls their DID), and your service submits their VC JWT to the verifyKYC function. A successful verification can mint a non-transferable Soulbound Token (SBT) to the user's address or update an on-chain mapping (e.g., mapping(address => bool) public isKYCD;), granting them access. This pattern creates a reusable, privacy-preserving KYC status that works across multiple dApps without re-submitting documents.

For production, integrate with established DID methods like ethr (Ethereum), polygonid, or cheqd. Test thoroughly with frameworks like Hardhat or Foundry, using real VCs from test identity providers. Refer to the W3C Verifiable Credentials Data Model and the Decentralized Identity Foundation specifications for standards-compliance. The next step involves building the off-chain issuer or integrator that requests and processes credentials before they reach the chain.

DID PROTOCOLS

Implementation Stack Comparison

Comparison of leading decentralized identity protocols for KYC integration based on technical specifications and developer experience.

FeatureSidetree (ION)VeramoSpruceID (DID:key)

Underlying DID Method

did:ion

did:ethr, did:key, did:web

did:key, did:web

Anchor Layer

Bitcoin (Layer 1)

Ethereum, Polygon, Tezos

Any blockchain (agnostic)

Primary SDK Language

TypeScript

TypeScript

TypeScript, Rust

VC (Verifiable Credential) Support

ZK-Proof Integration for KYC

Average Attestation Cost

$2-5 (BTC fees)

$0.10-1.00 (L2 gas)

< $0.01 (signature only)

Resolution Latency

~10 minutes (BTC confirm)

< 15 seconds

< 2 seconds

Required Infrastructure

Bitcoin node, IPFS

EVM RPC, Database

Local key management

DID INTEGRATION

Common Pitfalls and How to Avoid Them

Integrating Decentralized Identity (DID) for KYC involves navigating complex standards, key management, and interoperability. This guide addresses frequent developer challenges and provides solutions.

A 'DID not found' error often stems from resolver misconfiguration or an unsupported DID method. The resolver must be pointed to the correct DID method driver and network.

Common causes and fixes:

  • Incorrect Resolver URL: Ensure your resolver (e.g., did-resolver library) is configured with the correct Universal Resolver endpoint or a specific method's driver.
  • Unsynced Blockchain State: For blockchain-based DIDs (e.g., did:ethr, did:polygonid), the resolver may query a node that hasn't synced the latest block containing the DID document transaction. Use a reliable, synced RPC provider.
  • Method Not Supported: Verify the DID method (the part after did:) is registered and supported by your resolver library. You may need to import and register a specific package like ethr-did-resolver.

Example fix for did:ethr:

javascript
import { Resolver } from 'did-resolver';
import { getResolver } from 'ethr-did-resolver';

// Provide your Ethereum provider configuration
const providerConfig = { networks: [{ name: 'mainnet', rpcUrl: 'https://mainnet.infura.io/v3/YOUR_KEY' }] };
const ethrResolver = getResolver(providerConfig);
const resolver = new Resolver(ethrResolver);

// Now resolve the DID
const didDocument = await resolver.resolve('did:ethr:0xabc...');
DID INTEGRATION

Frequently Asked Questions

Common technical questions and solutions for developers implementing decentralized identity (DID) for KYC and compliance workflows.

A Decentralized Identifier (DID) is a W3C-standardized, self-sovereign identifier (e.g., did:ethr:0xabc123...) that is controlled by a user's private keys. Unlike a standard wallet address (e.g., 0xabc123...), a DID is designed for identity, not just asset transfer. The key differences are:

  • Verifiable Credentials (VCs): DIDs can be linked to VCs—tamper-proof, cryptographically signed attestations (like a KYC proof) issued by a trusted entity.
  • DID Document: Each DID resolves to a public document containing public keys, service endpoints, and verification methods, enabling trust frameworks.
  • Portability: A user's DID and associated VCs can be used across multiple applications without re-verification, whereas a wallet address alone carries no inherent identity data.

In short, a wallet address is for transactions; a DID is a foundation for a reusable, verifiable identity layer.

conclusion-next-steps
IMPLEMENTATION SUMMARY

Conclusion and Next Steps

You have now integrated a decentralized identity (DID) solution for KYC, moving from centralized data silos to user-controlled verification.

This guide walked through the core components of a DID-based KYC flow: issuing a Verifiable Credential (VC) from a trusted entity, storing it in a user's digital wallet, and presenting a Verifiable Presentation (VP) for verification. By using standards like W3C DIDs and VCs, you ensure interoperability across different platforms and wallets. The key architectural shift is placing the user in control of their data, allowing them to selectively disclose information without revealing their entire identity.

For production deployment, several critical next steps are required. First, establish a robust credential revocation strategy, such as implementing a revocation registry or using status list credentials. Second, integrate with trust frameworks like the Trust Over IP (ToIP) stack or the Gaia-X compliance framework to ensure your issuance and verification processes meet regulatory standards. Finally, conduct thorough security audits on your smart contracts and backend systems, focusing on signature validation and replay attack prevention.

To extend your integration, explore advanced patterns. Consider zero-knowledge proofs (ZKPs) for privacy-preserving checks, allowing users to prove they are over 18 or accredited without revealing their birthdate or income. Implement conditional credential presentation using Oracle services to fetch real-time data, such as checking a wallet's transaction history against sanctions lists. Frameworks like Veramo and Serto offer plugins for these advanced features, accelerating development.

The ecosystem of tools and services is rapidly evolving. Stay updated with the Decentralized Identity Foundation (DIF) and W3C Credentials Community Group for new specifications. For blockchain-specific developments, monitor Ethereum's ERC-725/735 for on-chain identity and Polygon ID for scalable zero-knowledge identity solutions. Engaging with these communities will help you adapt to new best practices and regulatory guidance.

Start testing your integration in a controlled environment. Use testnets like Sepolia or Polygon Mumbai and sandbox environments from credential issuers. Gradually onboard users, collecting feedback on the wallet interaction flow. The ultimate goal is a system that enhances user privacy and compliance efficiency, reducing friction and liability for your application while empowering your users with true data sovereignty.

How to Integrate Decentralized Identity (DID) for KYC Smart Contracts | ChainScore Guides