各位观众老爷,大家好!今天咱们来聊聊DIDs、VCs 和 Presentation Exchange 这三个家伙,它们可是构建下一代互联网信任体系的关键角色。这三个玩意儿听起来唬人,其实没那么复杂,咱们用大白话 + 代码的方式,保证你听完能上手。
一、DID:数字身份的身份证
想象一下,在网上冲浪,你得注册各种账号,密码记都记不过来,还得担心被盗号。DID 就是来解决这个问题的,它给你一个去中心化的数字身份,你自己说了算,不用依赖任何中心机构。
-
啥是 DID?
DID (Distributed Identifier) 是一种新型的标识符,它具有以下特点:
- 去中心化 (Decentralized): 不依赖于中心化的身份提供商。
- 可控性 (Controllable): 你自己控制你的 DID。
- 可验证性 (Verifiable): 可以通过密码学方法验证 DID 的所有权。
- 持久性 (Persistent): 即使你离开某个平台,DID 仍然存在。
-
DID 的结构
一个 DID 通常长这样:
did:method:identifier
did
: 固定前缀,表示这是一个 DID。method
: DID 方法,指定了如何创建、解析和更新 DID。常见的 DID 方法有did:key
,did:web
,did:pkh
等。identifier
: 方法特定的标识符,用于唯一标识一个 DID。
-
DID 方法举例
-
did:key
最简单的 DID 方法,直接使用公钥作为标识符。
// 生成一个随机的 Ed25519 密钥对 (需要导入相关库,比如 tweetnacl) const keyPair = nacl.sign.keyPair(); const publicKeyBase58 = bs58.encode(keyPair.publicKey); // 将公钥编码为 Base58 const didKey = `did:key:z${publicKeyBase58}`; // 构建 did:key console.log("did:key:", didKey); // 输出类似: did:key:z6MkpTHR3DQTU99YvNVnbKogJx2uhJvE2DiAcjVzZVMR
这个例子中,我们生成了一个Ed25519密钥对,然后将公钥编码为Base58格式,最后拼接到
did:key:
后面,就得到了一个did:key
类型的 DID。 注意z
前缀是 Multibase 编码的一部分,用于指示编码类型。 -
did:web
使用一个 HTTPS URL 作为标识符,DID 文档托管在这个 URL 上。
did:web:example.com
要解析这个 DID,我们需要去
https://example.com/.well-known/did.json
获取 DID 文档。 -
did:pkh
使用区块链地址作为标识符 (Public Key Hash)。
did:pkh:eip155:1:0x1234567890123456789012345678901234567890
这个例子中,
eip155:1
表示以太坊主网,0x123...
是一个以太坊地址。
-
-
DID 文档
DID 文档是一个 JSON-LD 文档,包含了关于 DID 的元数据,例如:
id
: DID 本身。verificationMethod
: 用于验证 DID 所有者的公钥。authentication
: 用于身份验证的验证方法。assertionMethod
: 用于声明的验证方法。capabilityInvocation
: 用于调用能力的验证方法。capabilityDelegation
: 用于委托能力的验证方法。service
: 用于发现与 DID 相关的服务的端点。
一个简单的 DID 文档示例:
{ "@context": [ "https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1" ], "id": "did:example:123456789abcdefghi", "verificationMethod": [ { "id": "did:example:123456789abcdefghi#key-1", "type": "Ed25519VerificationKey2020", "controller": "did:example:123456789abcdefghi", "publicKeyMultibase": "z6MkpTHR3DQTU99YvNVnbKogJx2uhJvE2DiAcjVzZVMR" } ], "authentication": [ "did:example:123456789abcdefghi#key-1" ], "assertionMethod": [ "did:example:123456789abcdefghi#key-1" ] }
这个文档声明了 DID
did:example:123456789abcdefghi
的所有者有一个 Ed25519 公钥,可以用于身份验证和声明。
二、VC:你的数字证书
有了 DID,我们就能证明“我是我”,但是怎么证明“我是个好人”、“我毕业了”、“我年满 18 岁”呢? 这时候就轮到 Verifiable Credentials (VCs) 出场了。 VC 相当于数字世界的证书,可以证明关于你的各种信息。
-
啥是 VC?
VC 是一种数字化的凭证,由一个 Issuer (颁发者) 颁发给一个 Subject (主体),用于证明关于 Subject 的某些信息。 VC 具有以下特点:
- 可验证性 (Verifiable): 可以通过密码学方法验证 VC 的真实性和完整性。
- 可移植性 (Portable): 可以被 Subject 在不同的场景中使用。
- 可选择性披露 (Selective Disclosure): Subject 可以选择性地披露 VC 中的部分信息。
-
VC 的结构
一个 VC 通常是一个 JSON-LD 文档,包含了以下关键字段:
@context
: JSON-LD 上下文,定义了 VC 中使用的术语。type
: VC 的类型,例如VerifiableCredential
,UniversityDegreeCredential
等。issuer
: 颁发者的 DID 或其他标识符。issuanceDate
: 颁发日期。expirationDate
: 过期日期 (可选)。credentialSubject
: 关于 Subject 的信息。proof
: 用于验证 VC 的密码学证明。
一个简单的 VC 示例:
{ "@context": [ "https://www.w3.org/2018/credentials/v1", "https://example.org/credentials/v1" ], "type": [ "VerifiableCredential", "UniversityDegreeCredential" ], "issuer": "did:example:issuer", "issuanceDate": "2023-10-27T12:00:00Z", "credentialSubject": { "id": "did:example:subject", "name": "Alice Smith", "degree": { "type": "BachelorDegree", "university": "Example University", "major": "Computer Science" } }, "proof": { "type": "Ed25519Signature2020", "created": "2023-10-27T12:00:00Z", "verificationMethod": "did:example:issuer#key-1", "proofPurpose": "assertionMethod", "jws": "..." // JWT 签名 } }
这个 VC 证明了 Alice Smith 在 Example University 获得了计算机科学专业的学士学位。
-
颁发 VC 的流程
- Issuer 创建 VC: Issuer 根据 Subject 的信息创建一个 VC 对象。
- Issuer 签名 VC: Issuer 使用自己的私钥对 VC 进行签名,生成
proof
字段。 - Issuer 将 VC 发给 Subject: Subject 获得 VC。
代码示例(简化版,没有包含完整的密钥管理和错误处理):
// 假设我们已经有了 Issuer 的 DID 和密钥对 const issuerDid = "did:example:issuer"; const issuerPrivateKey = nacl.sign.keyPair().secretKey; // 简化,实际需要安全地存储和访问私钥 async function issueCredential(subjectDid, subjectName, degree) { const credential = { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://example.org/credentials/v1" ], "type": [ "VerifiableCredential", "UniversityDegreeCredential" ], "issuer": issuerDid, "issuanceDate": new Date().toISOString(), "credentialSubject": { "id": subjectDid, "name": subjectName, "degree": degree } }; // 使用 JWT 签名 VC (需要导入 jose 库) const jws = await new jose.SignJWT(credential) .setProtectedHeader({ alg: 'EdDSA', kid: `${issuerDid}#key-1` }) // 假设 DID 文档中定义了 key-1 .setIssuer(issuerDid) .sign(issuerPrivateKey); // 使用私钥签名 credential.proof = { type: "Ed25519Signature2020", created: new Date().toISOString(), verificationMethod: `${issuerDid}#key-1`, proofPurpose: "assertionMethod", jws: jws }; return credential; } // 示例:颁发一个学位证书给 Alice issueCredential("did:example:alice", "Alice Smith", { type: "BachelorDegree", university: "Example University", major: "Computer Science" }).then(vc => { console.log("颁发的 VC:", vc); });
-
验证 VC 的流程
- Verifier 获取 VC: Verifier 从 Subject 那里获取 VC。
- Verifier 获取 Issuer 的 DID 文档: Verifier 通过 Issuer 的 DID 解析出 DID 文档,获取 Issuer 的公钥。
- Verifier 验证 VC 的签名: Verifier 使用 Issuer 的公钥验证 VC 的
proof
字段的签名。 - Verifier 验证 VC 的有效性: Verifier 检查 VC 的
issuanceDate
和expirationDate
是否有效。 - Verifier 验证 VC 的内容: Verifier 根据自己的需求验证 VC 的
credentialSubject
字段的内容。
代码示例(简化版):
async function verifyCredential(credential) { try { // 1. 验证 JWS 签名 (需要 jose 库) const { payload, protectedHeader } = await jose.jwtVerify( credential.proof.jws, async (protectedHeader, credential) => { // 模拟从 DID 文档中获取公钥 (实际需要根据 credential.issuer 从 DID Registry 解析 DID 文档) const issuerDid = credential.issuer; const publicKey = nacl.sign.keyPair().publicKey; // 假设我们能拿到 issuer 的公钥 return publicKey; }, { issuer: credential.issuer, algorithms: ['EdDSA'] // 验证算法 } ); // 2. 验证 VC 的有效性 const issuanceDate = new Date(credential.issuanceDate); const expirationDate = credential.expirationDate ? new Date(credential.expirationDate) : null; const now = new Date(); if (issuanceDate > now) { throw new Error("VC 还未生效"); } if (expirationDate && expirationDate < now) { throw new Error("VC 已过期"); } // 3. 其他自定义验证逻辑... (例如,验证学位是否符合要求) console.log("VC 验证成功!"); return true; } catch (error) { console.error("VC 验证失败:", error); return false; } } // 示例:验证之前颁发的 VC issueCredential("did:example:alice", "Alice Smith", { type: "BachelorDegree", university: "Example University", major: "Computer Science" }).then(vc => { verifyCredential(vc); });
三、Presentation Exchange:选择性地展示你的 VC
有了 VC,Alice 就可以把她的学位证书给任何想看的人。但是,如果 Alice 只是想证明自己毕业于某所大学,而不想透露自己的姓名和专业呢? 这时候 Presentation Exchange (PX) 就派上用场了。 PX 允许 Alice 选择性地披露 VC 中的部分信息。
-
啥是 Presentation Exchange?
Presentation Exchange 是一种标准,用于定义 Verifier 如何向 Holder 请求凭证,以及 Holder 如何创建和提交满足 Verifier 要求的 Presentation。 Presentation Exchange 允许 Verifier 指定它需要的凭证类型、属性和约束,而 Holder 可以选择性地披露满足这些要求的凭证。
-
Presentation Definition
Presentation Definition 是一个 JSON 对象,定义了 Verifier 需要的凭证类型、属性和约束。 它就像一份详细的“需求清单”。
一个简单的 Presentation Definition 示例:
{ "id": "32f54163-716f-42d0-a19b-0466b4d5e59c", "definition": { "input_descriptors": [ { "id": "degree_credential", "name": "University Degree", "purpose": "We need your degree to verify your education level.", "constraints": { "fields": [ { "path": [ "$.type" ], "filter": { "type": "string", "const": "UniversityDegreeCredential" } }, { "path": [ "$.credentialSubject.degree.university" ], "filter": { "type": "string", "const": "Example University" } } ] } } ] } }
这个 Presentation Definition 要求 Holder 提供一个
UniversityDegreeCredential
类型的 VC,并且 VC 中的credentialSubject.degree.university
字段必须是 "Example University"。 -
Presentation
Presentation 是 Holder 根据 Presentation Definition 创建的 JSON 对象,包含了满足 Verifier 要求的 VC。 Presentation 必须包含 Verifier 需要的所有信息,并且不能包含 Verifier 没有要求的信息。
一个简单的 Presentation 示例:
{ "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://example.org/credentials/v1" ], "type": [ "VerifiableCredential", "UniversityDegreeCredential" ], "issuer": "did:example:issuer", "issuanceDate": "2023-10-27T12:00:00Z", "credentialSubject": { "id": "did:example:alice", "name": "Alice Smith", "degree": { "type": "BachelorDegree", "university": "Example University", "major": "Computer Science" } }, "proof": { "type": "Ed25519Signature2020", "created": "2023-10-27T12:00:00Z", "verificationMethod": "did:example:issuer#key-1", "proofPurpose": "assertionMethod", "jws": "..." // JWT 签名 } } ], "presentation_submission": { "id": "a47c8255-6368-4999-8cb8-0a5f2683698a", "definition_id": "32f54163-716f-42d0-a19b-0466b4d5e59c", "descriptor_map": [ { "id": "degree_credential", "format": "vc+jwt", "path": "$.verifiableCredential[0]" } ] } }
这个 Presentation 包含了之前颁发的
UniversityDegreeCredential
,并且通过presentation_submission
字段指定了哪个 VC 满足哪个input_descriptor
的要求。 -
Presentation Exchange 的流程
- Verifier 创建 Presentation Definition: Verifier 根据自己的需求创建一个 Presentation Definition。
- Verifier 将 Presentation Definition 发给 Holder: Verifier 将 Presentation Definition 发给 Holder。
- Holder 根据 Presentation Definition 创建 Presentation: Holder 根据 Presentation Definition 从自己的 VC 中选择满足要求的 VC,并创建一个 Presentation。
- Holder 将 Presentation 发给 Verifier: Holder 将 Presentation 发给 Verifier。
- Verifier 验证 Presentation: Verifier 验证 Presentation 是否满足 Presentation Definition 的要求,以及 VC 的有效性。
代码示例(简化版):
// 1. Verifier 创建 Presentation Definition (同上) const presentationDefinition = { "id": "32f54163-716f-42d0-a19b-0466b4d5e59c", "definition": { "input_descriptors": [ { "id": "degree_credential", "name": "University Degree", "purpose": "We need your degree to verify your education level.", "constraints": { "fields": [ { "path": [ "$.type" ], "filter": { "type": "string", "const": "UniversityDegreeCredential" } }, { "path": [ "$.credentialSubject.degree.university" ], "filter": { "type": "string", "const": "Example University" } } ] } } ] } }; // 2. (模拟) Holder 收到 Presentation Definition, 并创建 Presentation async function createPresentation(credential, presentationDefinition) { const presentation = { verifiableCredential: [credential], presentation_submission: { id: "a47c8255-6368-4999-8cb8-0a5f2683698a", definition_id: presentationDefinition.id, descriptor_map: [ { id: "degree_credential", format: "vc+jwt", path: "$.verifiableCredential[0]" } ] } }; return presentation; } // 3. (模拟) Verifier 验证 Presentation async function verifyPresentation(presentation, presentationDefinition) { // 简化验证逻辑,实际需要根据 presentationDefinition 完整验证 try { if (presentation.presentation_submission.definition_id !== presentationDefinition.id) { throw new Error("Presentation Definition ID 不匹配"); } const credential = presentation.verifiableCredential[0]; if (!credential) { throw new Error("未找到 verifiableCredential"); } // 简单验证 credential 类型 if (!credential.type.includes("UniversityDegreeCredential")) { throw new Error("credential 类型不匹配"); } console.log("Presentation 验证成功!"); return true; } catch (error) { console.error("Presentation 验证失败:", error); return false; } } // 示例:完整的流程 issueCredential("did:example:alice", "Alice Smith", { type: "BachelorDegree", university: "Example University", major: "Computer Science" }).then(vc => { createPresentation(vc, presentationDefinition).then(presentation => { verifyPresentation(presentation, presentationDefinition).then(verified => { console.log("Presentation 验证结果:", verified); }); }); });
四、总结
技术 | 作用 | 优点 | 缺点 |
---|---|---|---|
DID | 提供去中心化的数字身份 | 去中心化,可控性,可验证性,持久性 | 复杂性,需要 DID 方法的支持 |
Verifiable Credentials | 提供数字化的凭证,用于证明关于 Subject 的信息 | 可验证性,可移植性,可选择性披露 | 需要可信的 Issuer,隐私问题,需要标准化 |
Presentation Exchange | 允许 Verifier 向 Holder 请求凭证,并允许 Holder 选择性地披露满足 Verifier 要求的凭证 | 保护隐私,提高效率,支持各种场景 | 需要标准化,复杂性 |
总的来说,DIDs、VCs 和 Presentation Exchange 是一套强大的工具,可以构建一个更加安全、可信和用户友好的互联网。 虽然现在还处于发展初期,但它们代表了未来的方向。 希望今天的讲解能让你对这三个家伙有个初步的了解,也欢迎大家深入研究,一起推动这个领域的发展!
好了,今天的讲座就到这里,散会! 记住,代码要多敲,才能真正掌握这些技术。 咱们下期再见!