零知识身份验证:KYC的隐私保护替代方案
2020年,一部名为《Coded Bias》的纪录片在Netflix上引起了广泛关注。这部电影揭示了AI算法中的"编码偏见"——面部识别系统对有色人种和女性的识别准确率显著低于白人男性。但这部电影还揭示了另一个更深层的问题:在数字时代,我们的身份数据正在被"编码"进各种系统中,而我们对此几乎毫无控制权。2026年,零知识证明(Zero-Knowledge Proof,ZKP)技术正在为身份验证提供一个革命性的替代方案:你可以在不透露任何个人信息的情况下,向验证者证明你"有资格"访问某个资源。这就是零知识身份验证——KYC(Know Your Customer)的隐私保护替代方案。
第一幕:KYC的"全景监狱"困境
第一场:传统KYC的隐私泄露
传统的KYC流程要求用户提交大量的个人信息:身份证照片、居住地址证明、银行流水、人脸识别视频、护照扫描件等。这些信息被存储在中心化的服务器上,成为黑客攻击的"高价值目标"。
2024年,全球最大的KYC数据泄露事件暴露了超过3000万用户的身份信息,包括身份证号、护照照片和家庭住址。这些数据被用于身份盗窃、金融欺诈和社交工程攻击。
第二场:KYC的"数据冗余"问题
在传统KYC流程中,用户需要在每个平台都重复提交相同的身份信息。如果你在10个不同的DeFi协议上进行交易,你就需要向10个不同的平台提交10次KYC信息。这意味着你的身份信息被复制了10次,存储在了10个不同的服务器上——每次复制都增加了数据泄露的风险。
第三场:监管合规与隐私保护的矛盾
监管机构要求平台进行KYC验证,以防止洗钱、恐怖融资和金融犯罪。但用户要求保护自己的隐私,不希望自己的个人信息被广泛分享。这个矛盾在2026年变得更加尖锐——随着AI技术的发展,身份信息可以被用于训练AI模型、构建用户画像、进行精准营销,甚至被用于"数字身份盗窃"。
第二幕:零知识证明的"隐形身份"技术
第一场:零知识证明的基本原理
零知识证明(Zero-Knowledge Proof)是一种密码学技术,允许一方(证明者)向另一方(验证者)证明某个陈述是真实的,而不透露任何超出该陈述真实性的信息。
一个经典的例子是"阿里巴巴的山洞":证明者需要向验证者证明自己知道山洞的秘密通道,但不需要展示秘密通道在哪里。证明者可以通过进入山洞、从另一边出来的方式,向验证者证明自己知道秘密——但验证者仍然不知道秘密通道的具体位置。
第二场:zkKYC——零知识身份验证
zkKYC(Zero-Knowledge KYC)是零知识证明在身份验证领域的应用。其核心思想是:
- 身份发行:用户向一个可信的身份发行机构(如政府、银行)提交身份信息,获得一个"数字身份凭证"。
- 零知识证明:用户使用零知识证明技术,向验证者证明自己"满足某些条件"(如年龄>18岁、居住在某国、信用评分>700),而不透露具体的身份信息。
- 链上验证:验证者可以在链上验证零知识证明的有效性,而不需要查看用户的原始身份信息。
第三场:zkKYC的优势
与传统KYC相比,zkKYC具有以下优势:
- 隐私保护:用户不需要向验证者透露任何个人信息。
- 数据最小化:验证者只获得"条件满足"的证明,不获得任何额外的数据。
- 跨平台复用:用户可以在多个平台使用同一个"数字身份凭证",而不需要重复提交KYC。
- 防篡改:零知识证明基于密码学,无法被伪造或篡改。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
contract zkKYCVerifier is AccessControl, ReentrancyGuard {
bytes32 public constant ISSUER_ROLE = keccak256("ISSUER_ROLE");
bytes32 public constant VERIFIER_ROLE = keccak256("VERIFIER_ROLE");
enum VerificationType {
AGE_OVER_18,
AGE_OVER_21,
RESIDENT_COUNTRY,
CREDIT_SCORE_OVER,
AML_CHECK,
PEP_CHECK,
SANCTION_CHECK,
CUSTOM
}
enum VerificationStatus {
PENDING,
VERIFIED,
REJECTED,
EXPIRED,
REVOKED
}
struct IdentityCommitment {
bytes32 commitmentHash;
address user;
address issuer;
uint256 issuedAt;
uint256 expiresAt;
bool isRevoked;
}
struct VerificationRequest {
bytes32 requestId;
address user;
address verifier;
VerificationType vType;
bytes32 proofHash;
bytes32 publicInputsHash;
VerificationStatus status;
uint256 requestedAt;
uint256 verifiedAt;
}
struct Issuer {
address issuerAddress;
string name;
uint256 totalIssued;
uint256 totalRevoked;
uint256 reputation;
bool isActive;
}
uint256 private _commitmentCounter;
uint256 private _requestCounter;
mapping(bytes32 => IdentityCommitment) public commitments;
mapping(bytes32 => VerificationRequest) public verificationRequests;
mapping(address => Issuer) public issuers;
mapping(address => bytes32[]) public userCommitments;
mapping(address => mapping(address => bool)) public userConsent;
uint256 public constant COMMITMENT_EXPIRY = 365 days;
uint256 public constant VERIFICATION_EXPIRY = 30 days;
event IdentityIssued(bytes32 indexed commitmentHash, address indexed user, address indexed issuer);
event VerificationRequested(bytes32 indexed requestId, address indexed user, address indexed verifier);
event VerificationApproved(bytes32 indexed requestId, bytes32 proofHash);
event VerificationRejected(bytes32 indexed requestId, string reason);
event IdentityRevoked(bytes32 indexed commitmentHash, address indexed issuer);
event ConsentGranted(address indexed user, address indexed verifier);
event ConsentRevoked(address indexed user, address indexed verifier);
constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
function registerIssuer(string memory _name) external {
require(issuers[msg.sender].issuerAddress == address(0), "Already registered");
issuers[msg.sender] = Issuer({
issuerAddress: msg.sender,
name: _name,
totalIssued: 0,
totalRevoked: 0,
reputation: 1000,
isActive: true
});
_grantRole(ISSUER_ROLE, msg.sender);
}
function issueIdentity(bytes32 _commitmentHash, address _user, uint256 _durationDays) external onlyRole(ISSUER_ROLE) {
require(commitments[_commitmentHash].issuer == address(0), "Commitment already exists");
commitments[_commitmentHash] = IdentityCommitment({
commitmentHash: _commitmentHash,
user: _user,
issuer: msg.sender,
issuedAt: block.timestamp,
expiresAt: block.timestamp + (_durationDays * 1 days),
isRevoked: false
});
userCommitments[_user].push(_commitmentHash);
issuers[msg.sender].totalIssued++;
emit IdentityIssued(_commitmentHash, _user, msg.sender);
}
function grantConsent(address _verifier) external {
userConsent[msg.sender][_verifier] = true;
emit ConsentGranted(msg.sender, _verifier);
}
function revokeConsent(address _verifier) external {
userConsent[msg.sender][_verifier] = false;
emit ConsentRevoked(msg.sender, _verifier);
}
function requestVerification(
bytes32 _commitmentHash,
VerificationType _vType,
bytes32 _proofHash,
bytes32 _publicInputsHash
) external nonReentrant returns (bytes32) {
IdentityCommitment storage commitment = commitments[_commitmentHash];
require(commitment.user == msg.sender, "Not the identity owner");
require(!commitment.isRevoked, "Identity revoked");
require(block.timestamp < commitment.expiresAt, "Identity expired");
require(userConsent[msg.sender][_commitmentHash] == true, "Consent not granted");
bytes32 requestId = keccak256(abi.encodePacked(_commitmentHash, msg.sender, block.timestamp, _requestCounter));
verificationRequests[requestId] = VerificationRequest({
requestId: requestId,
user: msg.sender,
verifier: _commitmentHash,
vType: _vType,
proofHash: _proofHash,
publicInputsHash: _publicInputsHash,
status: VerificationStatus.PENDING,
requestedAt: block.timestamp,
verifiedAt: 0
});
_requestCounter++;
emit VerificationRequested(requestId, msg.sender, _commitmentHash);
return requestId;
}
function verifyProof(
bytes32 _requestId,
bool _isValid
) external onlyRole(VERIFIER_ROLE) nonReentrant {
VerificationRequest storage request = verificationRequests[_requestId];
require(request.status == VerificationStatus.PENDING, "Already processed");
if (_isValid) {
request.status = VerificationStatus.VERIFIED;
request.verifiedAt = block.timestamp;
emit VerificationApproved(_requestId, request.proofHash);
} else {
request.status = VerificationStatus.REJECTED;
emit VerificationRejected(_requestId, "Proof invalid");
}
}
function revokeIdentity(bytes32 _commitmentHash) external onlyRole(ISSUER_ROLE) {
IdentityCommitment storage commitment = commitments[_commitmentHash];
require(commitment.issuer == msg.sender, "Not the issuer");
commitment.isRevoked = true;
issuers[msg.sender].totalRevoked++;
emit IdentityRevoked(_commitmentHash, msg.sender);
}
function getVerificationStatus(bytes32 _requestId) external view returns (VerificationStatus) {
return verificationRequests[_requestId].status;
}
function getUserCommitments(address _user) external view returns (bytes32[] memory) {
return userCommitments[_user];
}
}
第三幕:zkKYC的技术实现
第一场:零知识证明的密码学基础
零知识证明的实现依赖于复杂的密码学原语:
- zk-SNARKs(Zero-Knowledge Succinct Non-Interactive Argument of Knowledge):生成紧凑的证明,验证速度快,但需要可信设置。
- zk-STARKs(Zero-Knowledge Scalable Transparent Argument of Knowledge):不需要可信设置,可扩展性强,但证明体积较大。
- Bulletproofs:不需要可信设置,证明体积小,但验证时间较长。
- PLONK:通用可信设置,支持多种电路。
第二场:身份凭证的链上管理
在zkKYC系统中,身份凭证的管理是一个关键环节:
- 身份发行:用户向可信发行机构(如政府、银行、认证机构)提交身份信息,发行机构验证信息后,生成一个"数字身份凭证"。
- 凭证存储:用户将"数字身份凭证"存储在自己的设备上(如手机、硬件钱包),而不是存储在中心化服务器上。
- 凭证使用:用户需要向某个平台证明自己的身份时,使用零知识证明技术生成一个"证明",证明自己"满足某些条件"。
第三场:隐私保护与监管合规的平衡
zkKYC不是要完全消除KYC,而是要在隐私保护和监管合规之间找到平衡:
- 选择性披露:用户可以选择只披露"必要"的信息,而不是全部信息。
- 可审计性:监管机构可以通过"审计密钥"查看用户的身份信息,但需要用户的同意。
- 可撤销性:如果用户被发现有违法行为,发行机构可以"撤销"用户的身份凭证。
# Zero-Knowledge Identity Verification System
# zkKYC implementation for privacy-preserving identity verification
import hashlib
import json
import time
import random
from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass
from enum import Enum
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec, rsa, padding
from cryptography.hazmat.primitives import serialization
class VerificationType(Enum):
AGE_OVER_18 = "age_over_18"
AGE_OVER_21 = "age_over_21"
RESIDENT_COUNTRY = "resident_country"
CREDIT_SCORE_OVER = "credit_score_over"
AML_PASSED = "aml_passed"
NOT_SANCTIONED = "not_sanctioned"
CUSTOM = "custom"
class IdentityStatus(Enum):
ISSUED = "issued"
ACTIVE = "active"
REVOKED = "revoked"
EXPIRED = "expired"
@dataclass
class IdentityCommitment:
commitment_hash: str
user_address: str
issuer_address: str
issued_at: float
expires_at: float
status: IdentityStatus
attributes: Dict # Encrypted attributes
@dataclass
class VerificationProof:
proof_id: str
commitment_hash: str
verifier: str
verification_type: VerificationType
proof_data: Dict
public_inputs: Dict
timestamp: float
is_valid: bool
@dataclass
class Issuer:
address: str
name: str
public_key: str
total_issued: int
total_revoked: int
is_active: bool
class zkKYCSystem:
def __init__(self):
self.issuers: Dict[str, Issuer] = {}
self.commitments: Dict[str, IdentityCommitment] = {}
self.proofs: Dict[str, VerificationProof] = {}
self.user_commitments: Dict[str, List[str]] = {}
self.user_consent: Dict[str, Dict[str, bool]] = {}
self.audit_log: List[Dict] = []
def register_issuer(self, address: str, name: str, public_key: str) -> Issuer:
if address in self.issuers:
raise ValueError(f"Issuer {address} already registered")
issuer = Issuer(address=address, name=name, public_key=public_key,
total_issued=0, total_revoked=0, is_active=True)
self.issuers[address] = issuer
print(f"[ISSUER] Registered: {name} ({address})")
return issuer
def issue_identity(self, user_address: str, issuer_address: str,
attributes: Dict, duration_days: int = 365) -> IdentityCommitment:
if issuer_address not in self.issuers:
raise ValueError(f"Issuer {issuer_address} not registered")
issuer = self.issuers[issuer_address]
if not issuer.is_active:
raise ValueError(f"Issuer {issuer_address} is not active")
# Create commitment hash
commitment_data = json.dumps({
"user": user_address, "issuer": issuer_address,
"attributes": attributes, "timestamp": time.time(),
"nonce": random.randint(0, 2**64)
}, sort_keys=True)
commitment_hash = hashlib.sha256(commitment_data.encode()).hexdigest()
commitment = IdentityCommitment(
commitment_hash=commitment_hash,
user_address=user_address,
issuer_address=issuer_address,
issued_at=time.time(),
expires_at=time.time() + (duration_days * 86400),
status=IdentityStatus.ISSUED,
attributes=attributes
)
self.commitments[commitment_hash] = commitment
if user_address not in self.user_commitments:
self.user_commitments[user_address] = []
self.user_commitments[user_address].append(commitment_hash)
issuer.total_issued += 1
print(f"[ISSUE] Identity issued to {user_address} by {issuer.name}")
return commitment
def generate_proof(self, commitment_hash: str, user_address: str,
verifier: str, vtype: VerificationType,
condition: Dict) -> VerificationProof:
if commitment_hash not in self.commitments:
raise ValueError(f"Commitment {commitment_hash} not found")
commitment = self.commitments[commitment_hash]
if commitment.user_address != user_address:
raise ValueError("User does not own this commitment")
if commitment.status != IdentityStatus.ISSUED:
raise ValueError(f"Commitment status is {commitment.status}")
if time.time() > commitment.expires_at:
raise ValueError("Commitment has expired")
# Simulate zero-knowledge proof generation
# In reality, this would use zk-SNARKs/STARKs
proof_data = self._generate_zk_proof(commitment, vtype, condition)
proof_id = hashlib.sha256(f"{commitment_hash}{verifier}{time.time()}".encode()).hexdigest()[:16]
proof = VerificationProof(
proof_id=proof_id,
commitment_hash=commitment_hash,
verifier=verifier,
verification_type=vtype,
proof_data=proof_data,
public_inputs={"verification_type": vtype.value, "condition": condition},
timestamp=time.time(),
is_valid=True
)
self.proofs[proof_id] = proof
print(f"[PROOF] Generated proof {proof_id} for {vtype.value}")
return proof
def _generate_zk_proof(self, commitment: IdentityCommitment,
vtype: VerificationType, condition: Dict) -> Dict:
# Simulated ZK proof generation
attributes = commitment.attributes
proof = {"commitment_hash": commitment.commitment_hash, "verified_claims": []}
if vtype == VerificationType.AGE_OVER_18:
birth_date = attributes.get("birth_date", "2000-01-01")
birth_year = int(birth_date.split("-")[0])
age = 2026 - birth_year
required_age = condition.get("min_age", 18)
proof["verified_claims"].append({
"claim": f"age_over_{required_age}",
"result": age >= required_age,
"revealed_info": "none"
})
elif vtype == VerificationType.RESIDENT_COUNTRY:
country = attributes.get("country", "")
allowed_countries = condition.get("countries", [])
proof["verified_claims"].append({
"claim": "resident_country",
"result": country in allowed_countries,
"revealed_info": "none"
})
elif vtype == VerificationType.AML_PASSED:
aml_status = attributes.get("aml_status", "pending")
proof["verified_claims"].append({
"claim": "aml_passed",
"result": aml_status == "passed",
"revealed_info": "none"
})
proof["proof_hash"] = hashlib.sha256(json.dumps(proof, sort_keys=True).encode()).hexdigest()
return proof
def verify_proof(self, proof_id: str, verifier: str) -> bool:
if proof_id not in self.proofs:
raise ValueError(f"Proof {proof_id} not found")
proof = self.proofs[proof_id]
if proof.verifier != verifier:
raise ValueError("Verifier mismatch")
if not proof.is_valid:
return False
# Verify the proof
# In reality, this would verify the zk-SNARK/STARK
commitment = self.commitments.get(proof.commitment_hash)
if not commitment or commitment.status != IdentityStatus.ISSUED:
return False
if time.time() > commitment.expires_at:
return False
return True
def revoke_identity(self, commitment_hash: str, issuer_address: str):
if commitment_hash not in self.commitments:
raise ValueError(f"Commitment {commitment_hash} not found")
commitment = self.commitments[commitment_hash]
if commitment.issuer_address != issuer_address:
raise ValueError("Only the issuer can revoke")
commitment.status = IdentityStatus.REVOKED
self.issuers[issuer_address].total_revoked += 1
print(f"[REVOKE] Identity {commitment_hash[:16]}... revoked")
def grant_consent(self, user_address: str, verifier: str):
if user_address not in self.user_consent:
self.user_consent[user_address] = {}
self.user_consent[user_address][verifier] = True
print(f"[CONSENT] {user_address} granted consent to {verifier}")
def revoke_consent(self, user_address: str, verifier: str):
if user_address in self.user_consent:
self.user_consent[user_address][verifier] = False
print(f"[CONSENT] {user_address} revoked consent from {verifier}")
def get_user_identity_summary(self, user_address: str) -> List[Dict]:
summaries = []
if user_address in self.user_commitments:
for ch in self.user_commitments[user_address]:
c = self.commitments[ch]
summaries.append({
"commitment_hash": ch[:16] + "...",
"issuer": self.issuers[c.issuer_address].name if c.issuer_address in self.issuers else "Unknown",
"issued_at": c.issued_at,
"expires_at": c.expires_at,
"status": c.status.value
})
return summaries
# Example
zk = zkKYCSystem()
zk.register_issuer("0xGOV", "Government ID Authority", "pub_key_123")
zk.register_issuer("0xBank", "Bank KYC Provider", "pub_key_456")
# Issue identity
commitment = zk.issue_identity("0xUSER", "0xGOV", {
"full_name": "ENC:John Doe",
"birth_date": "1990-01-15",
"country": "US",
"aml_status": "passed",
"credit_score": 750
})
# User grants consent
zk.grant_consent("0xUSER", "0xDeFiProtocol")
# Generate age verification proof
proof = zk.generate_proof(commitment.commitment_hash, "0xUSER",
"0xDeFiProtocol", VerificationType.AGE_OVER_18,
{"min_age": 18})
# Verify proof
is_valid = zk.verify_proof(proof.proof_id, "0xDeFiProtocol")
print(f"Proof valid: {is_valid}")
# Check user identity summary
summary = zk.get_user_identity_summary("0xUSER")
print(f"User identities: {json.dumps(summary, indent=2)}")
第四幕:zkKYC的未来
第一场:从金融到内容——zkKYC的应用扩展
2026年,zkKYC的应用正在从金融领域扩展到内容领域:
- 年龄验证:内容平台可以使用zkKYC验证用户的年龄,而不需要收集用户的出生日期。
- 地域限制:流媒体平台可以使用zkKYC验证用户的地理位置,而不需要收集用户的IP地址或居住地址。
- 身份验证:社交媒体平台可以使用zkKYC验证用户是否是真人,而不需要收集用户的身份证信息。
第二场:从"需要知道"到"需要证明"
zkKYC的核心理念是"最小化信息披露"——平台"需要知道"的不是用户的身份信息,而是用户"满足某些条件"的"证明"。这个理念可以应用于更广泛的场景:
- 信用验证:证明自己的信用评分超过某个阈值,而不透露具体的评分。
- 收入验证:证明自己的年收入超过某个阈值,而不透露具体的收入金额。
- 资格验证:证明自己拥有某个资格(如学位、执照),而不透露具体的证书号。
第三场:从中心化到去中心化——身份主权
zkKYC的最终目标是实现"身份主权"——用户完全控制自己的身份数据,而不是将身份数据交给中心化平台。2026年,DID(去中心化身份)和VC(可验证凭证)标准正在推动这一愿景的实现。
// zkKYC Identity Verification API
// Privacy-preserving identity verification using zero-knowledge proofs
class zkKYCManager {
constructor() {
this.issuers = new Map();
this.identities = new Map();
this.proofs = new Map();
this.userIdentities = new Map();
this.consentRegistry = new Map();
this.auditLog = [];
}
registerIssuer(address, name, publicKey) {
if (this.issuers.has(address)) throw new Error(`Issuer ${address} exists`);
const issuer = { address, name, publicKey, totalIssued: 0, totalRevoked: 0, isActive: true };
this.issuers.set(address, issuer);
console.log(`[ISSUER] Registered: ${name}`);
return issuer;
}
issueIdentity(userAddress, issuerAddress, attributes, durationDays = 365) {
const issuer = this.issuers.get(issuerAddress);
if (!issuer) throw new Error(`Issuer ${issuerAddress} not found`);
if (!issuer.isActive) throw new Error('Issuer is inactive');
const commitmentHash = require('crypto')
.createHash('sha256')
.update(JSON.stringify({userAddress, issuerAddress, attributes, timestamp: Date.now(), nonce: Math.random()}))
.digest('hex');
const identity = {
commitmentHash, userAddress, issuerAddress, attributes,
issuedAt: Date.now(), expiresAt: Date.now() + durationDays * 86400000,
status: 'issued'
};
this.identities.set(commitmentHash, identity);
if (!this.userIdentities.has(userAddress)) this.userIdentities.set(userAddress, []);
this.userIdentities.get(userAddress).push(commitmentHash);
issuer.totalIssued++;
console.log(`[ISSUE] Identity issued to ${userAddress} by ${issuer.name}`);
return identity;
}
generateProof(commitmentHash, userAddress, verifier, vtype, condition) {
const identity = this.identities.get(commitmentHash);
if (!identity) throw new Error(`Commitment ${commitmentHash} not found`);
if (identity.userAddress !== userAddress) throw new Error('Not the owner');
if (identity.status !== 'issued') throw new Error(`Status: ${identity.status}`);
if (Date.now() > identity.expiresAt) throw new Error('Identity expired');
// Generate zero-knowledge proof
const proofData = this._generateZKProof(identity, vtype, condition);
const proofId = require('crypto')
.createHash('sha256')
.update(`${commitmentHash}${verifier}${Date.now()}`)
.digest('hex')
.substring(0, 16);
const proof = {
proofId, commitmentHash, verifier, verificationType: vtype,
proofData, publicInputs: {verificationType: vtype, condition},
timestamp: Date.now(), isValid: true
};
this.proofs.set(proofId, proof);
console.log(`[PROOF] Generated ${proofId} for ${vtype}`);
return proof;
}
_generateZKProof(identity, vtype, condition) {
const attrs = identity.attributes;
const claims = [];
if (vtype === 'age_over_18') {
const birthYear = parseInt((attrs.birthDate || '2000-01-01').split('-')[0]);
const age = 2026 - birthYear;
const minAge = condition.minAge || 18;
claims.push({claim: `age_over_${minAge}`, result: age >= minAge, revealed: 'none'});
} else if (vtype === 'resident_country') {
const country = attrs.country || '';
const allowed = condition.countries || [];
claims.push({claim: 'resident_country', result: allowed.includes(country), revealed: 'none'});
} else if (vtype === 'aml_passed') {
claims.push({claim: 'aml_passed', result: attrs.amlStatus === 'passed', revealed: 'none'});
}
return {commitmentHash: identity.commitmentHash, claims,
proofHash: require('crypto').createHash('sha256').update(JSON.stringify(claims)).digest('hex')};
}
verifyProof(proofId, verifier) {
const proof = this.proofs.get(proofId);
if (!proof) throw new Error(`Proof ${proofId} not found`);
if (proof.verifier !== verifier) throw new Error('Verifier mismatch');
if (!proof.isValid) return false;
const identity = this.identities.get(proof.commitmentHash);
if (!identity || identity.status !== 'issued') return false;
if (Date.now() > identity.expiresAt) return false;
return true;
}
revokeIdentity(commitmentHash, issuerAddress) {
const identity = this.identities.get(commitmentHash);
if (!identity) throw new Error('Not found');
if (identity.issuerAddress !== issuerAddress) throw new Error('Not the issuer');
identity.status = 'revoked';
this.issuers.get(issuerAddress).totalRevoked++;
console.log(`[REVOKE] Identity ${commitmentHash.substring(0, 16)}... revoked`);
}
grantConsent(user, verifier) {
if (!this.consentRegistry.has(user)) this.consentRegistry.set(user, new Map());
this.consentRegistry.get(user).set(verifier, true);
}
getUserIdentities(userAddress) {
const hashes = this.userIdentities.get(userAddress) || [];
return hashes.map(h => {
const id = this.identities.get(h);
const issuer = this.issuers.get(id.issuerAddress);
return {commitmentHash: h.substring(0, 16) + '...', issuer: issuer ? issuer.name : 'Unknown',
issuedAt: id.issuedAt, expiresAt: id.expiresAt, status: id.status};
});
}
}
// Example
const zk = new zkKYCManager();
zk.registerIssuer('0xGOV', 'Government ID Authority', 'pub_key_123');
zk.registerIssuer('0xBank', 'Bank KYC Provider', 'pub_key_456');
const identity = zk.issueIdentity('0xUSER', '0xGOV', {
fullName: 'ENC:John Doe', birthDate: '1990-01-15', country: 'US',
amlStatus: 'passed', creditScore: 750
});
zk.grantConsent('0xUSER', '0xDeFi');
const proof = zk.generateProof(identity.commitmentHash, '0xUSER', '0xDeFi', 'age_over_18', {minAge: 18});
const valid = zk.verifyProof(proof.proofId, '0xDeFi');
console.log('Proof valid:', valid);
console.log('User identities:', zk.getUserIdentities('0xUSER'));
第四场:结语——从"你是谁"到"你能证明什么"
零知识身份验证正在重新定义"身份"的本质。在传统KYC中,身份是关于"你是谁"——你的名字、你的地址、你的身份证号。在zkKYC中,身份是关于"你能证明什么"——你能否证明自己年满18岁、你能否证明自己居住在某国、你能否证明自己通过了AML检查。这种转变不仅是技术上的,更是哲学上的:它把"身份"的控制权从中心化机构还给了个人。
在这个万物皆可Token化的时代,技术的迭代往往比镜头切换更快。作为北京城市学院2021级广播电视编导的毕业生,我始终在影像与区块链的交汇处寻找共鸣。感谢阅读,我是王森涛,让我们在视听与去中心化的世界里,继续探索。