Securityintermediatearticle35 min read

DID and ZK for VNeID decentralized identity in Vietnam

Vietcardano teamTeam

Đội ngũ biên tập VietCardanoCommunity — các chuyên gia blockchain và Cardano, cung cấp nội dung giáo dục và nghiên cứu chuyên sâu cho cộng đồng.

Published August 31, 2026Updated August 30, 2026
# DID and ZK for VNeID: Decentralized Identity for Vietnam's Digital Future ** ![did-vneid-architecture](https://szphnqitmccoycreinfc.supabase.co/storage/v1/object/public/articles/did-zk-vneid/did-vneid-architecture.png) ** Vietnam's digital transformation is entering a critical phase. The **VNeID** platform — the Ministry of Public Security's national digital identity system — has issued digital identities to tens of millions of Vietnamese citizens. It authenticates users for government services, increasingly required for banking, e-commerce, and even informal verification. But VNeID has a fundamental architectural limitation: **it is still a centralized identity silo**. Every time you prove "I am over 18" through VNeID, you reveal your full VNeID profile. The service learns your name, your CCCD number, your address, your photo — even though it only needed to know one boolean: `age >= 18`. Enter **Decentralized Identifiers (DID)** and **Zero-Knowledge Proofs (ZK)**. A DID is an identifier you create and control — no government department, no corporation, no platform owns it. Combined with **Verifiable Credentials (VCs)** cryptographically issued by trusted authorities (like VNeID), and **ZK selective disclosure** that proves predicates without revealing the underlying data, you get something powerful: a self-owned, portable digital identity that satisfies legal requirements while preserving privacy. This article shows exactly how DID + ZK integrates with VNeID, why it's compliant with Vietnam's ND 13/2023 data protection law, and how Vietnamese developers can build it today. --- ## What Is a Decentralized Identifier (DID)? ** ![did-document-structure](https://szphnqitmccoycreinfc.supabase.co/storage/v1/object/public/articles/did-zk-vneid/did-document-structure.png) ** A **Decentralized Identifier (DID)** is a globally unique identifier that the user — not any central authority — creates and controls. The W3C DID specification (first published 2021, now a Recommendation) defines the standard format: ``` did:method:namespace:unique-id ``` For Vietnam's national identity integration, a citizen's DID might look like: ``` did:vn:gov:vneid:12345 did:key:z6MkhaXgBZDvotDkL5257efizniTRfgbWngL4tjBz2rokp8q ``` ### DID vs Traditional Identifiers | Property | URL | UUID | DID | |---------|-----|------|-----| | Issued by | Domain owner | Central authority | Self (or delegated) | | Resolvable | Via DNS | Via database | Via DID resolver (blockchain/ distributed ledger) | | Lifetime | Tied to domain | Tied to authority | User-controlled | | Example | https://service.example | 550e8400-e29b-41d4 | did:eth:0xabc123... | ### The DID Document Every DID resolves to a **DID Document** — a JSON-LD structure containing: ```json { "@context": ["https://www.w3.org/ns/did/v1"], "id": "did:vn:gov:vneid:12345", "controller": "did:vn:gov:vneid:12345", "verificationMethod": [{ "id": "did:vn:gov:vneid:12345#zk-verification-1", "type": "ZKProofVerification2024", "controller": "did:vn:gov:vneid:12345", "zkPublicParameters": "0xabc123...", "zkVerificationKey": "0xdef456..." }], "authentication": ["did:vn:gov:vneid:12345#zk-verification-1"], "assertionMethod": ["did:vn:gov:vneid:12345#zk-verification-1"], "service": [{ "id": "did:vn:gov:vneid:12345#resolver", "type": "DIDResolution", "serviceEndpoint": "https://resolver.vn/did/12345" }] } ``` The critical addition here is the `verificationMethod` entry of type `ZKProofVerification2024`. This tells verifiers: "To verify claims from this DID, check the ZK proof against this verification key." No blockchain transaction, no central registry lookup — just public-key cryptography. --- ## VNeID Today: What Vietnam's National Digital Identity Provides ** ![vneid-login-comparison](https://szphnqitmccoycreinfc.supabase.co/storage/v1/object/public/articles/did-zk-vneid/vneid-login-comparison.png) ** **VNeID** (Vietnam National Electronic Identification) is Vietnam's official digital identity platform operated by the Ministry of Public Security. Launched under Decree 13/2023, it provides: - **Authentication:** OAuth 2.0 / OIDC login to government and approved services - **Profile data:** Name, CCCD number, date of birth, address, photo, biometric hash - **Digital signature:** Sign documents using your VNeID private key (stored on government server) - **Single sign-on:** One VNeID account accesses multiple government services ### What VNeID Does Well 1. **High trust:** Government-issued, universally accepted 2. **Biometric enrollment:** Fingerprint + facial recognition at registration 3. **Legal standing:** Explicitly recognized in ND 13/2023 for electronic transactions 4. **Coverage:** 100M+ Vietnamese citizens targeted by 2025 ### What VNeID Cannot Do | Need | VNeID Capability | Problem | |------|------------------|---------| | Prove age >= 18 | ❌ Yes, but reveals full name + CCCD | Over-collection violates ND 13/2023 Article 8 | | Share VC with private service | ❌ Requires service to integrate VNeID API | Each integration is government-negotiated | | User controls data sharing | ❌ Government decides what services get | No granular permission | | Cross-border identity (SG, MY, TH) | ❌ Country-specific | ASEAN has no mutual recognition agreement | | Offline proof | ❌ Requires VNeID server connectivity | Poor reliability in rural areas | | Revoke third-party access | ❌ All-or-nothing | Cannot revoke one service without revoking all | **The fundamental gap:** VNeID is a *centralized authentication silo*. Every authentication event reveals the user's full VNeID identity to the service. This is the OAuth problem at national scale. --- ## Zero-Knowledge Proofs: Privacy Without Leaking Data ** ![zk-selective-disclosure](https://szphnqitmccoycreinfc.supabase.co/storage/v1/object/public/articles/did-zk-vneid/zk-selective-disclosure.png) ** A **Zero-Knowledge Proof** lets a prover convince a verifier that a statement is true **without revealing the underlying data**. In the context of VNeID + DID, the magic is in **predicates**: ``` Predicate: "The holder of this VC is at least 18 years old" Raw data: date_of_birth = "1995-03-15" ZK proof proves: birthdate + age_calculation circuit → output: "age >= 18 == true" Verifier learns: boolean (true/false) Verifier does NOT learn: birthdate, name, CCCD, address ``` ### How ZK Selective Disclosure Works 1. **VC issuance:** VNeID issues a VC containing `date_of_birth: 1995-03-15` 2. **User gets ZK circuit:** A pre-built circuit that knows how to compute `age >= 18` from `date_of_birth` 3. **Proof generation:** User runs the circuit locally on their phone with `date_of_birth` as private input. Circuit outputs `age >= 18 = true` 4. **Selective disclosure:** User sends ONLY the proof + `did:vn:gov:vneid:12345` to the verifier 5. **Verification:** Verifier checks proof against the DID document's `verificationMethod[#zk-verification-1]` public key 6. **Access granted:** Verifier now knows "someone with valid VNeID VC who is >= 18" — without knowing *who* --- ## DID + ZK + VNeID: The Three-Layer Architecture **[VISUAL: Diagram - Three-layer DID+ZK+VNeID architecture]** The integration follows a **three-layer model**. Each layer has a clear responsibility: ### Layer 1: VNeID — The Trusted Credential Issuer VNeID remains the source of truth for Vietnamese identity. It issues VCs cryptographically signed with VNeID's private key. ``` Layer 1: VNeID Government Service ├── OAuth 2.0 / OIDC authentication ├── VC issuance (signed by VNeID root key) ├── Contains: name, DOB, CCCD, address, biometric hash, citizen status ├── User stores VC in their DID wallet (encrypted, client-side) └── Government CANNOT see how/when user presents VC to third parties ``` The key innovation: **VNeID's role shrinks to "issuer only"**. It no longer needs to be the authentication oracle for every third-party service. Services verify VCs instead of calling VNeID APIs. ### Layer 2: User's DID — Portable, Self-Owned Identity Container The user controls a DID document that references VCs issued by VNeID. ``` Layer 2: User's DID Document (stored on distributed ledger) ├── DID: did:key:z6Mk... (user-generated) ├── controller: user (self) ├── verificationMethod: │ ├── ZK verification key (proves predicates from VCs) │ ├── Recovery public key (social recovery) │ └── Encryption public key (DIDComm) ├── VCs referenced: │ ├── vc:vn:vneid:age (via hash, not full VC) │ ├── vc:vn:vneid:citizen │ └── vc:vn:vneid:address (optional) └── service endpoints (DID resolution URL) ``` The critical design choice: **the DID document stores only the VC hashes, not the full VC contents**. Full VCs live in the user's encrypted wallet. The proof verifier needs only the ZK public parameters (from the VC issuer's on-chain registration) and the VC hash (to compute the Merkle root the proof commits to). ### Layer 3: Verifier — Trusts the Math, Not the Middleman Relying parties (banks, e-commerce sites, government services) verify ZK proofs. ``` Layer 3: Verifier (relying party) ├── Receives: did + ZK proof + nullifier ├── Resolves DID document via resolver (blockchain or DHT) ├── Gets ZK verification method from DID document ├── Runs: verify(proof, verificationKey, publicInputs) │ → returns: VALID or INVALID ├── Learns: boolean predicate result only └── Does NOT learn: user identity, VNeID data, wallet address ``` ### Data Flow (End-to-End) ``` 1. User authenticates with VNeID → receives signed VC 2. VC stored encrypted in user's DID wallet (on mobile) 3. User needs to prove "age >= 18" to a service 4. ZK circuit runs on user's phone: proves predicate from VC 5. User generates: ZK proof + nullifier + did:key 6. Service receives: {did, proof, nullifier} 7. Service resolves DID → gets ZK verification method 8. Service runs verify(proof, vk) → TRUE 9. Service: "This person is >= 18. I don't know who. Access granted." ``` --- ## Selective Disclosure in Practice ** ![zk-selective-disclosure](https://szphnqitmccoycreinfc.supabase.co/storage/v1/object/public/articles/did-zk-vneid/zk-selective-disclosure.png) ** The VNeID-VC-ZK stack supports rich predicate proofs beyond just age. For Vietnam's regulatory environment, these are the highest-value predicates: | Predicate | VC Source Field | Circuit Logic | Use Case | |-----------|-----------------|---------------|----------| | `age >= 18` | date_of_birth | `current_year - birth_year >= 18` | Social media, airdrops, e-commerce | | `vn_citizen == true` | nationality | `nationality == "VN"` | Government services | | `hanoi_resident == true` | address | `address.startsWith("Hanoi")` | Municipal services | | `income_bracket >= X` | income | `income >= threshold` | Loan eligibility | | `fully_vaccinated == true` | vaccination_status | binary check | Health pass, travel | | `not_on_blacklist == true` | compliance_status | Merkle proof of non-membership | Exchange KYC | **Circuit composition:** A single VC can support multiple predicate proofs simultaneously. For example, one VC issued by VNeID can prove *both* `age >= 18` *and* `vn_citizen == true` in one ZK proof — without revealing name, CCCD, or address. --- ## DID Resolution: The Chicken-and-Egg Problem ** ![did-resolution](https://szphnqitmccoycreinfc.supabase.co/storage/v1/object/public/articles/did-zk-vneid/did-resolution.png) ** A DID is only useful if verifiers can resolve it — find the current DID document. This requires a **DID resolver** infrastructure. ### Resolution Options | Method | Blockchain/Storage | Pros | Cons | VN Suitability | |--------|-------------------|------|------|---------------| | did:eth | Ethereum L1/L2 | Most mature DIDs | High gas | ❌ Too expensive for mass use | | did:polygon | Polygon PoS | Low gas, EVM-compatible | Requires MATIC | ✅ Good for public rollout | | did:cardano | Cardano | Formal methods, W3C native | Smaller ecosystem | ✅ VN has Cardano talent | | did:key | No blockchain (key-only) | Simplest, free | No update mechanism | ⚠️ Good for temporary DIDs | | Permissioned consortium | Government-operated | Fast, controllable | Centralization risk | ✅ Best for Phase 1 pilot | **Recommendation for Vietnam:** - **Phase 1 (pilot):** Permissioned consortium DID network operated by Ministry of Public Science & Technology. Fast, controlled, familiar governance model. - **Phase 2 (public):** Bridge to Polygon PoS for ASEAN interoperability. DID documents anchored on Polygon; Vietnamese government retains issuer role for VCs. --- ## Integration Roadmap for Vietnamese Developers ** ![integration-steps](https://szphnqitmccoycreinfc.supabase.co/storage/v1/object/public/articles/did-zk-vneid/integration-steps.png) ** ### Step 1: Access VNeID APIs (Week 1-2) VNeID provides OAuth 2.0/OIDC integration for approved services. Register your application with the Ministry of Public Security's integration portal. ``` GET https://api.vneid.gov.vn/oauth/authorize → User authenticates with VNeID (OTP + biometric on their phone) → Returns: access_token (long-lived for government services) ``` ### Step 2: Build DID Issuer Service (Week 2-4) Create a web service that: 1. Receives VNeID `access_token` 2. Fetches VC data from VNeID API 3. Creates W3C Verifiable Credential JSON-LD 4. Signs VC with issuer's private key 5. Returns VC to user's mobile wallet ```javascript const vc = { "@context": ["https://www.w3.org/2018/credentials/v1"], "id": "urn:vc:vn:vneid:12345", "type": ["VerifiableCredential", "VNeIDAgeCredential"], "issuer": "did:vn:gov:vneid", "issuanceDate": "2024-03-15", "credentialSubject": { "id": "did:key:z6Mk...", "date_of_birth": "1995-03-15", "vn_citizen": true }, "proof": { "type": "JwtSignature2024", "jws": vneid_signed_jws } }; ``` ### Step 3: Issue VCs to User's DID Wallet (Week 4-5) Mobile wallet flow: 1. User opens DID wallet app (Android-first) 2. Taps "Connect VNeID" 3. OAuth redirect to VNeID app 4. User approves VC issuance 5. VC encrypted and stored in wallet ### Step 4: Build ZK Circuit for Predicates (Week 5-7) Use Circom or Noir to build predicates: - `age_gte`: computes `year - birth_year >= threshold` - `vn_citizen`: equality check - `hanoi_resident`: string prefix check Pre-built predicate libraries: Circomlib has `hash`, `merkle`, `comparison` circuits. Build on top. ### Step 5: Deploy Verifier (Week 7-8) ```javascript async function verifyPredicateProof(did, proof, predicate) { // 1. Resolve DID document const doc = await resolver.resolve(did); // 2. Get ZK verification method const zkMethod = doc.verificationMethod.find( m => m.type === 'ZKProofVerification2024' ); // 3. Verify proof const result = await snarkjs.groth16.verify( zkMethod.zkVerificationKey, proof.publicSignals, proof.proof ); return result; // boolean } ``` ### Step 6: Mobile Wallet Integration (Week 8-10) - Android-first (Kotlin/Java) - Client-side ZK proving (Circom compiled to WASM or native ARM) - Biometric unlock for key derivation (Android Keystore) - Offline VC storage (SQLCipher) - Online proof generation (Prover on device, Verifier remote) --- ## Security and Privacy Analysis ** ![security-comparison](https://szphnqitmccoycreinfc.supabase.co/storage/v1/object/public/articles/did-zk-vneid/security-comparison.png) ** ### Threat Model Comparison: VNeID vs DID vs DID+ZK | Threat | VNeID Only | DID Only | DID+ZK+VNeID | |--------|-----------|----------|--------------| | MITM network attack | ⚠️ OAuth redirect vulnerable | ✅ DID = self-asserted | ✅ DID + ZK proof only | | Service learns full identity | ❌ Always | ⚠️ Depends on VC disclosure | ✅ Only predicate result | | VCCD data breach impact | ⚠️ Full lateral movement | ✅ VC is hash only | ✅ VC stored encrypted in wallet | | Key compromise | Government key (rare) | User key (PMF) | User key (PMF) + recovery | | Revocation | VNeID can revoke | DID controller can revoke | VC issuer can revoke; ZK proof includes epoch | | Replay attacks | ⚠️ Timestamp tokens needed | ⚠️ Nonce needed | ✅ Nullifier prevents double use | --- ## FAQ **Q: Does DID replace VNeID?** A: No. DID complements VNeID. VNeID remains the credential issuer. DID makes VNeID-issued credentials portable and privacy-preserving for third-party use. **Q: What blockchain should Vietnam use for DID infrastructure?** A: Phase 1 (pilot): Permissioned consortium for familiarity and control. Phase 2: Polygon PoS for ASEAN interoperability and lower barrier to international verifiers. **Q: Is this compliant with ND 13/2023?** A: Yes, comprehensively. Article 8 (minimum necessary): ZK predicates satisfy. Article 12 (consent): User controls VC sharing. Article 24 (deletion): VC revocation. Article 28 (cross-border): Permissioned chain keeps data in Vietnam. **Q: What if VNeID is down or the user is offline?** A: VCs are cached locally (encrypted). ZK proofs can be generated offline. DID document resolution — the only online step — can use cached resolver results for up to 24 hours. **Q: Can this work for cross-border ASEAN identity?** A: Yes, that's the long-term goal. W3C DID is an international standard. Once Vietnam anchors DIDs on an interoperable chain (Polygon), Indonesia, Singapore, and Malaysia can verify Vietnamese DIDs using the same W3C resolution flow. --- *Next article in this series: **Soulbound Tokens + ZKP for Sybil Resistance** — How non-transferable ZK-verified identity credentials stop Sybil attacks in airdrops and governance systems.*

Tags:

did zkvneid blockchaindanh tính số phi tập trung