好嘞,各位听众,今天咱来聊聊Web3里身份验证的那些事儿,主角是JS的Decentralized Identifiers
(DIDs) 和 Verifiable Credentials
(VCs)。这俩家伙就像是数字世界的身份证和学历证明,不过它们比传统的身份证和学历证明更酷,因为它们是去中心化的,更安全,更可控。
讲座大纲:
- DIDs:Web3的门牌号
- 什么是DIDs?
- DIDs的结构和解析
- DIDs的创建和管理(JS代码示例)
- VCs:你的数字履历
- 什么是VCs?
- VCs的结构和关键字段
- VCs的签发和验证(JS代码示例)
- DIDs和VCs的验证流程:如何证明“你是你”?
- 验证流程概述
- JS代码实现:从VCs中提取DID,验证签名
- 可信数据源:DID Document的作用
- 实战案例:打造一个简单的Web3身份验证系统
- 需求分析
- 架构设计
- 核心代码实现(JS):
- 用户注册(DID创建)
- VCs签发
- VCs验证
- 安全考量和最佳实践
- 防止重放攻击
- 密钥管理
- 隐私保护
- 总结与展望
1. DIDs:Web3的门牌号
想象一下,在Web3的世界里,每个人都需要一个独特的、自己控制的身份。这就是DIDs的作用。
-
什么是DIDs?
DIDs (Decentralized Identifiers) 是一种新型的标识符,它不依赖于中心化的注册机构。你可以把它看作是你在Web3世界的“门牌号”,别人可以通过这个“门牌号”找到你的公开信息,验证你的身份。
-
DIDs的结构和解析
一个典型的DID长这样:
did:example:123456789abcdefghi
它由几个部分组成:
did:
:固定前缀,表示这是一个DID。example:
:DID方法 (DID Method),指定了该DID使用的规范和如何解析。不同的区块链、不同的协议可以使用不同的DID方法。123456789abcdefghi
:DID方法特定的标识符,每个DID方法都有自己的标识符规则。
解析DID的意思就是根据DID方法,找到与这个DID关联的DID Document。DID Document里包含了该DID的公钥、服务端点等信息,是验证身份的关键。
-
DIDs的创建和管理(JS代码示例)
不同的DID方法有不同的创建方式。这里我们用一个简单的例子,假设我们自己定义了一个DID方法叫
mychain
,它的标识符就是用户公钥的哈希。// 引入必要的库 (这里只是示例,实际可能需要更复杂的库) const crypto = require('crypto'); // 生成公私钥对 function generateKeyPair() { const keyPair = crypto.generateKeyPairSync('ed25519'); return { publicKey: keyPair.publicKey.export({ type: 'spki', format: 'jwk' }), privateKey: keyPair.privateKey.export({ type: 'pkcs8', format: 'pem' }) }; } // 计算公钥哈希 function hashPublicKey(publicKey) { const publicKeyString = JSON.stringify(publicKey); const hash = crypto.createHash('sha256').update(publicKeyString).digest('hex'); return hash; } // 创建DID function createDID() { const keyPair = generateKeyPair(); const publicKeyHash = hashPublicKey(keyPair.publicKey); const did = `did:mychain:${publicKeyHash}`; // 模拟将DID和公钥存储到某个地方 (例如数据库) // 在实际应用中,你需要将DID Document发布到可信的存储介质上,例如区块链 storeDIDDocument(did, keyPair.publicKey); return { did, publicKey: keyPair.publicKey, privateKey: keyPair.privateKey }; } // 模拟存储DID Document function storeDIDDocument(did, publicKey) { // 在实际应用中,你需要将DID Document发布到可信的存储介质上 console.log(`存储 DID Document for ${did} with public key:`, publicKey); // 这里只是一个简单的console.log,实际需要更复杂的存储逻辑 } // 示例用法 const { did, publicKey, privateKey } = createDID(); console.log("Generated DID:", did); console.log("Public Key:", publicKey); //console.log("Private Key:", privateKey); // 注意:不要在生产环境中打印私钥!
这段代码演示了如何生成公私钥对,计算公钥的哈希值,然后用哈希值作为DID的标识符。
storeDIDDocument
函数模拟了将DID Document存储到某个地方的过程。在实际应用中,你需要选择一种合适的存储方式,例如区块链、IPFS等。
2. VCs:你的数字履历
有了DIDs,你就有了Web3的“门牌号”,但光有“门牌号”还不够,你还需要一些“履历证明”来证明你是谁,你有什么资格。这就是VCs的作用。
-
什么是VCs?
VCs (Verifiable Credentials) 是一种数字化的证明文件,它可以用来证明你的身份、学历、工作经历等。VCs由一个可信的“签发者”签发,并且可以被“验证者”验证,确保VCs的真实性和完整性。
-
VCs的结构和关键字段
一个典型的VCs长这样(JSON格式):
{ "@context": [ "https://www.w3.org/2018/credentials/v1", "https://example.org/schemas/v1" ], "type": [ "VerifiableCredential", "UniversityDegreeCredential" ], "issuer": "did:example:issuer", "issuanceDate": "2023-10-27T12:00:00Z", "credentialSubject": { "id": "did:example:subject", "name": "Alice", "degree": { "type": "BachelorDegree", "name": "Computer Science" } }, "proof": { "type": "Ed25519Signature2018", "created": "2023-10-27T12:00:00Z", "proofPurpose": "assertionMethod", "verificationMethod": "did:example:issuer#key-1", "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..signature" } }
关键字段说明:
@context
:定义了VCs使用的词汇表和规范。type
:定义了VCs的类型,例如VerifiableCredential
和UniversityDegreeCredential
。issuer
:签发者的DID。issuanceDate
:签发日期。credentialSubject
:证明对象的信息,例如姓名、学历等。proof
:签名信息,用于验证VCs的真实性。
-
VCs的签发和验证(JS代码示例)
// 引入必要的库 const jsonld = require('jsonld'); const jsigs = require('jsonld-signatures'); const { Ed25519KeyPair } = require('crypto-ld'); // 签发VCs async function issueVC(credential, issuerPrivateKey) { const keyPair = new Ed25519KeyPair({ id: "did:example:issuer#key-1", // 签发者密钥的ID privateKeyPem: issuerPrivateKey, // 签发者私钥 publicKey: { '@context': 'https://w3id.org/security/suites/ed25519-2018/v1', type: 'Ed25519VerificationKey2018', id: "did:example:issuer#key-1", controller: 'did:example:issuer', publicKeyJwk: { kty: 'OKP', crv: 'Ed25519', x: Buffer.from(publicKeyJwk.x, 'base64').toString('hex') // 假设publicKeyJwk是签发者的公钥 (JWK格式) } }, controller: 'did:example:issuer' }); const signedCredential = await jsigs.sign(credential, { suite: new jsigs.suites.Ed25519Signature2018({ key: keyPair }), purpose: 'assertionMethod', documentLoader: async (url) => { // 这里需要根据URL返回相应的文档,例如DID Document if (url === "did:example:issuer") { return { document: { "@context": "https://w3id.org/did/v1", "id": "did:example:issuer", "verificationMethod": [{ "id": "did:example:issuer#key-1", "type": "Ed25519VerificationKey2018", "controller": "did:example:issuer", "publicKeyJwk": publicKeyJwk // 签发者的公钥 (JWK格式) }] } }; } throw new Error(`Unknown URL: ${url}`); } }); return signedCredential; } // 验证VCs async function verifyVC(signedCredential) { try { const result = await jsigs.verify(signedCredential, { suite: new jsigs.suites.Ed25519Signature2018(), purpose: 'assertionMethod', documentLoader: async (url) => { // 这里需要根据URL返回相应的文档,例如DID Document if (url === "did:example:issuer") { return { document: { "@context": "https://w3id.org/did/v1", "id": "did:example:issuer", "verificationMethod": [{ "id": "did:example:issuer#key-1", "type": "Ed25519VerificationKey2018", "controller": "did:example:issuer", "publicKeyJwk": publicKeyJwk // 签发者的公钥 (JWK格式) }] } }; } throw new Error(`Unknown URL: ${url}`); } }); return result.verified; } catch (error) { console.error("Verification error:", error); return false; } } // 示例数据 const credential = { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://example.org/schemas/v1" ], "type": [ "VerifiableCredential", "UniversityDegreeCredential" ], "issuer": "did:example:issuer", "issuanceDate": "2023-10-27T12:00:00Z", "credentialSubject": { "id": "did:example:subject", "name": "Alice", "degree": { "type": "BachelorDegree", "name": "Computer Science" } } }; // 假设我们有签发者的私钥 const issuerPrivateKey = "-----BEGIN PRIVATE KEY-----n... (你的私钥) ...n-----END PRIVATE KEY-----"; const publicKeyJwk = { kty: 'OKP', crv: 'Ed25519', x: '...' // 签发者的公钥 (base64) }; // 示例用法 async function runExample() { const signedCredential = await issueVC(credential, issuerPrivateKey); console.log("Signed Credential:", JSON.stringify(signedCredential, null, 2)); const isVerified = await verifyVC(signedCredential); console.log("Credential Verified:", isVerified); } runExample();
这段代码演示了如何使用
jsonld-signatures
库来签发和验证VCs。issueVC
函数使用签发者的私钥对VCs进行签名,verifyVC
函数使用签发者的公钥验证VCs的签名。注意,在实际应用中,你需要安全地管理私钥,并且从可信的数据源获取公钥。
3. DIDs和VCs的验证流程:如何证明“你是你”?
现在我们有了DIDs和VCs,接下来看看如何用它们来证明“你是你”。
-
验证流程概述
- 用户提供VCs: 用户向验证者提供VCs。
- 提取Issuer的DID: 验证者从VCs中提取签发者的DID。
- 解析DID: 验证者根据DID方法,解析DID,获取DID Document。
- 获取公钥: 验证者从DID Document中获取签发者的公钥。
- 验证签名: 验证者使用签发者的公钥验证VCs的签名。
- 验证VCs的内容: 验证者验证VCs的内容是否符合要求,例如是否过期,是否被吊销等。
-
JS代码实现:从VCs中提取DID,验证签名
// (沿用之前的代码) // 验证VCs的函数 (简化版) async function verifyVC(signedCredential) { try { // 1. 提取Issuer的DID const issuerDid = signedCredential.issuer; console.log("Issuer DID:", issuerDid); // 2. 解析DID (这里简化为直接返回公钥) const publicKey = await resolveDID(issuerDid); console.log("Issuer Public Key:", publicKey); // 3. 验证签名 (使用之前的验证函数) const result = await jsigs.verify(signedCredential, { suite: new jsigs.suites.Ed25519Signature2018(), purpose: 'assertionMethod', documentLoader: async (url) => { // 这里需要根据URL返回相应的文档,例如DID Document if (url === "did:example:issuer") { return { document: { "@context": "https://w3id.org/did/v1", "id": "did:example:issuer", "verificationMethod": [{ "id": "did:example:issuer#key-1", "type": "Ed25519VerificationKey2018", "controller": "did:example:issuer", "publicKeyJwk": publicKeyJwk // 签发者的公钥 (JWK格式) }] } }; } throw new Error(`Unknown URL: ${url}`); } }); return result.verified; } catch (error) { console.error("Verification error:", error); return false; } } // 模拟解析DID,返回公钥 async function resolveDID(did) { // 在实际应用中,你需要根据DID方法,从区块链或其他存储介质上获取DID Document // 这里我们简单地返回之前定义的publicKeyJwk return publicKeyJwk; } // 示例用法 (沿用之前的代码) async function runExample() { const signedCredential = await issueVC(credential, issuerPrivateKey); console.log("Signed Credential:", JSON.stringify(signedCredential, null, 2)); const isVerified = await verifyVC(signedCredential); console.log("Credential Verified:", isVerified); } runExample();
这段代码演示了如何从VCs中提取签发者的DID,然后解析DID,获取公钥,最后使用公钥验证VCs的签名。
resolveDID
函数模拟了DID解析的过程,在实际应用中,你需要根据DID方法,从区块链或其他存储介质上获取DID Document。 -
可信数据源:DID Document的作用
DID Document是验证身份的关键。它包含了与DID关联的公钥、服务端点等信息。DID Document必须存储在可信的数据源上,例如区块链、IPFS等,以确保其真实性和完整性。
4. 实战案例:打造一个简单的Web3身份验证系统
接下来,我们来打造一个简单的Web3身份验证系统,看看DIDs和VCs如何在实际应用中使用。
-
需求分析
- 用户可以注册并创建一个DID。
- 注册机构可以签发VCs给用户,证明用户的某些属性,例如年龄、学历等。
- 验证者可以验证用户提供的VCs,确认用户的身份和属性。
-
架构设计
这个系统包含三个角色:
- 用户: 拥有自己的DID和VCs。
- 注册机构: 负责签发VCs。
- 验证者: 负责验证VCs。
系统架构图:
+----------+ +----------------+ +----------+ | 用户 | ----> | 注册机构 | ----> | 验证者 | +----------+ +----------------+ +----------+ (DID, VCs) (签发VCs) (验证VCs)
-
核心代码实现(JS):
-
用户注册(DID创建)
// (沿用之前的DID创建代码) function registerUser() { const { did, publicKey, privateKey } = createDID(); // 将DID、公钥、私钥存储到用户的本地存储或数据库中 // ... return { did, publicKey }; }
-
VCs签发
// (沿用之前的VCs签发代码) async function issueAgeCredential(userDid, age, issuerPrivateKey) { const credential = { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://example.org/schemas/v1" ], "type": [ "VerifiableCredential", "AgeCredential" ], "issuer": "did:example:issuer", "issuanceDate": new Date().toISOString(), "credentialSubject": { "id": userDid, "age": age } }; const signedCredential = await issueVC(credential, issuerPrivateKey); return signedCredential; }
-
VCs验证
// (沿用之前的VCs验证代码) async function verifyAgeCredential(signedCredential) { const isVerified = await verifyVC(signedCredential); if (isVerified) { // 验证VCs的内容 const credentialSubject = signedCredential.credentialSubject; const age = credentialSubject.age; // 验证年龄是否符合要求 if (age >= 18) { return true; } else { console.log("Age is not sufficient."); return false; } } else { console.log("Credential is not verified."); return false; } }
-
5. 安全考量和最佳实践
-
防止重放攻击
重放攻击是指攻击者截获用户发送的VCs,然后重复发送,冒充用户。为了防止重放攻击,可以在VCs中添加一个
nonce
字段,每次发送VCs时都生成一个不同的nonce
值。验证者需要验证nonce
值是否已经使用过。 -
密钥管理
私钥是身份验证的关键,必须安全地管理。可以使用硬件钱包、密钥管理系统等方式来保护私钥。
-
隐私保护
VCs包含了用户的个人信息,需要注意保护用户的隐私。可以使用零知识证明等技术来在不泄露用户具体信息的情况下验证用户的属性。
6. 总结与展望
今天我们学习了DIDs和VCs的基本概念、结构和验证流程,并通过一个实战案例了解了如何在实际应用中使用它们。DIDs和VCs是Web3身份验证的重要组成部分,它们可以帮助我们构建一个更安全、更可控、更注重隐私的数字世界。
未来,DIDs和VCs将在更多的领域得到应用,例如:
- 数字身份: 用于证明用户的身份,例如登录网站、参加会议等。
- 数字凭证: 用于证明用户的学历、工作经历等。
- 供应链管理: 用于追溯商品的来源和流向。
- 医疗保健: 用于安全地共享医疗数据。
希望今天的讲座对大家有所帮助! 感谢各位的聆听,下课!