我对 W3C DID 1.0 标准的理解
先放官方链接
我对这个东西的理解比较肤浅,仅供参考。
DID 的全称
DID 的全称为 Decentralized Identifiers (去中心化身份)
现有的中心化的应用场景
我喜欢用如下生活体验的场景来解释 DID 的作用:
-
证明的签署和发放
(证明的)
发行方签署证明后,为(证明的)持有人发放证明政府给公民发放身份证银行给用户发放资产证明大学给学生发放毕业证书公司给员工提供在职证明
-
证明的使用(提交)
持有人将自己获得的证明提交给验证方以证明某些信息公民将身份证提交给验证方以证明自己的公民身份 (例如去高铁站用身份证买票乘车)用户将资产证明提交给验证方以证明自己的资产 (例如去领事馆办理旅游签证)学生将毕业证书提交给验证方以证明自己的学历 (例如去用人单位面试)员工将在职证明提交给验证方以证明自己的在职状态 (例如去银行办理贷款)
-
证明的真实性验证
验证方对证明的真实性进行验证高铁站需要验证身份证的真实性,以及是否属于持有人领事馆需要验证资产证明的真实性,以及是否属于持有人用人单位需要验证毕业证书的真实性,以及是否属于持有人银行需要验证在职证明的真实性,以及是否属于持有人
这些证明都是由某个发行方签发的,而且都是中心化的。
这里的中心化的意思是,如果验证方需要验证这些证明的有效性,需要联系发行方。
对于身份证,验证方需要使用设备读取身份证上的信息,然后通过网络连接政府提供的服务器来验证身份证的有效性。
对于资产证明,验证方如果只是通过查看公章,那么伪造一枚公章可能就可以欺骗验证方。为了更准确的验证,验证方需要联系银行,通过银行的来验证资产证明的有效性。
其他的证明也是类似的。
中心化的解决方案存在的问题显而易见:
发行方的提供的验证服务可能被假冒发行方的提供的验证服务可能因为异常而中断- 一些小的
发行方, 可能根本就没有能力提供验证服务 - 对于一些防伪程度不高的证明,
发行方本身可能也无法确认是否由自己发放 - 其他未详细列出的问题
(一个特殊的例子是, 毕业证书可以去教育部网站查询,虽然不直接由发行方(大学)提供验证,但是这种验证方式也是中心化的)
用流程图描述上面的过程如下:

去中心化的解决方案
因为本文的主题是 DID (Decentralized Identifiers), 我们就来看看 DID 是如何解决上面的问题的。
DID 为我们提供的解决方案如下:
参与 DID 流程的三方分别叫做 Issuer, Holder, Verifier
-
Issuer 为 Holder 颁发 VC (Verifiable Credential)
-
Holder 拿到 VC 后, 可以按需将 VC 提供给 Verifier 进行验证。
-
Verifier 收到 Holder 发来的 VC 之后, 可以在不需要 Issuer 配合,甚至不需要知会 Issuer 的情况下,验证 VC 的有效性。
即如下内容
-
这份 VC 是否由对应的 Issuer 签发
-
VC 是签发给当前提交 VC 的 Holder,而不是其他 Holder
-
VC 里的内容是否被篡改过
-
-
Verifier 验证了 VC 的有效性后,可以根据 VC 里的内容,决定是否给 Holder 提供服务
VC 里的内容在 DID 中称作
claim`例如身份证对应的 VC 里包含了以下
claim`- 身份证号
- 姓名
- 性别
- 出生日期
- 发证机构
- 证件有效期

从步骤中可以看出,第 1、2、4 步都是和传统的流程一样的,只有第 3 步不一样,他是怎么做到的呢?
DID 的实现基础
公私钥对
公私钥对是非对称加密的基础,这里不再赘述。 相关文档网络上很多,例如这篇文章
主要场景有两种, 一种是加密解密, 一种是签名验证
-
加密解密过程 对于数据 data
-
用公钥对数据 data 进行加密后的结果为 encrypted_data = encrypt(data, public_key)
-
私钥对加密后的数据进行解密后的结果为 decrypted_data = decrypt(encrypted_data, private_key)
-
如果加密的公钥和解密的私钥不对应,那么解密会失败
-
一旦解密成功,那么 decrypted_data 就和 data 的内容一致
-
-
签名验证 对于数据 data
-
用私钥对数据签名后的结果对 singature = sign(data, private_key)
-
用公钥+data+签名 singature, 可以验证这个签名结果 verify(data, signature, public_key)
-
如果签名的私钥和公钥不对应,或者数据被篡改了,那么验签结果会失败。
-
所以当乙需要验证甲的身份时,可以通过如下方式解决
-
甲生成公私钥对
-
甲自己持有私钥,然后将公钥提供给乙。
-
通过加密方式验证身份
-
乙随机产生一份 data, 用公钥加密
-
乙将加密后的数据发送给甲
-
甲用私钥解密,如果解密成功,则身份验证通过
-
(解密后的数据可能是用于某个系统的登录 token, 这样乙就完成了对”甲是否真的解密成功”的验证)
-
-
通过签名方式验证身份
-
乙随机生成一个 data
-
乙将 data 的明文发送给甲
-
甲用私钥对 data 进行签名,然后将签名后的结果发送给乙
-
乙用公钥+data+签名结果,验证签名的有效性,如果验证成功,则身份验证通过
-
公私钥对验证身份的这两种方式,侧重点不同
-
加密解密侧重于信息的保密性信息传输过程中数据是加密的, 所以即使被截获, 也无法知道数据的内容
-
签名验证侧重于信息的来源和完整性数据原文是明文传输的, 接收方无需解密,但可以通过签名验证数据的来源和完整性
在 DID 中需要用到的特性为:
持有公钥的一方,可以验证对方是否持有对应的私钥
区块链
区块链+智能合约有如下特性
-
对信息的存储和获取
任何人都可以将信息存储到区块链的去中心化存储体系上,任何人都可以从区块链上获取信息
-
不可篡改
在区块生成后,即使是上传方也无法恶意修改自己提交过的信息。
-
透明性
任何人都可以根据智能合约的代码,验证智能合约的行为是否符合预期
-
身份验证
上传信息到区块链时,可以通过智能合约的代码,验证上传者的身份,避免信息被伪造
在 DID 中需要用到的特性为:
对于某个固定的 key, 可以往区块链上存储指定的信息,任何人也可以通过这个 key 查询回该信息,
DID 的实现原理
-
Issuer 和 Holder 如下一次性准备工作:
在参与到 DID 流程之前需要进行的准备工作, 且只需要操作一次即可
-
生成公私钥对
-
生成 DID
格式如 did:example:123456789abcdefghi
DID Method 记录了如何通过 DID Method-Specific Identifier 来访问到 DID Document 的方法
-
生成 DID Document
例子如下,里面包含了自己的公钥和 DID 信息
{ "@context": [ "https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1" ] "id": "did:example:123456789abcdefghi", "authentication": [{ // used to authenticate as did:...fghi "id": "did:example:123456789abcdefghi#keys-1", "type": "Ed25519VerificationKey2020", "controller": "did:example:123456789abcdefghi", "publicKeyMultibase": "zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" }] } -
DID Document 上传到区块链(或者其他的去中心化存储体系)上
确保任意参与方都可以通过 DID 访问到 DID Document
-
-
Issuer 为 Holder 签署 VC (Verifiable Credential)
-
Issuer 如何验证 Holder 的身份
-
Issuer 通过 Holder 提供的 DID, 可以从区块链上获取到 Holder 的 DID Document
-
从 DID Document 中获取到 Holder 的公钥
-
Issuer 通过 Holder 的公钥,验证 Holder 是否持有对应的私钥
-
-
签署 VC (Issue a Verifiable Crendential)
- 类似 DID Document, VC 也是一个 JSON 对象
-
VC 包含了如下内容
-
issuer DID
VC 的签发方的 DID
-
issuanceDate
VC 的签发时间
-
expirationDate
VC 的过期时间
-
credentialSubject (Holder DID)
Holder 的 DID 等信息
-
claim
VC 的内容,即 VC 的持有人的相关信息,如年龄,证件号码等
-
proof:
issuer 用自己的私钥,结合 上述 VC 的内容,生成的签名
-
-
VC 的例子
{ // external (all terms in this example) "@context": [ "https://www.w3.org/2018/credentials/v1", "https://w3id.org/citizenship/v1" ], "type": ["VerifiableCredential", "PermanentResidentCard"], "credentialSubject": { "id": "did:example:123", "type": ["PermanentResident", "Person"], "givenName": "JOHN", "familyName": "SMITH", "gender": "Male", "image": "data:image/png;base64,iVBORw0KGgo...kJggg==", "residentSince": "2015-01-01", "lprCategory": "C09", "lprNumber": "000-000-204", "commuterClassification": "C1", "birthCountry": "Bahamas", "birthDate": "1958-08-17" }, "issuer": "did:example:456", "issuanceDate": "2020-04-22T10:37:22Z", "identifier": "83627465", "name": "Permanent Resident Card", "description": "Government of Example Permanent Resident Card.", "proof": { "type": "Ed25519Signature2018", "created": "2020-04-22T10:37:22Z", "proofPurpose": "assertionMethod", "verificationMethod": "did:example:456#key-1", "jws": "eyJjcml0IjpbImI2NCJdLCJiNjQiOmZhbHNlLCJhbGciOiJFZERTQSJ9..BhWew0x-txcroGjgdtK-yBCqoetg9DD9SgV4245TmXJi-PmqFzux6Cwaph0r-mbqzlE17yLebjfqbRT275U1AA" } }
-
-
Holder 提交 VC 给 Verifier
DID 协议 1.0 中并未规定 Holder 如何提交 VC 给 Verifier,只是提到以双方认可的安全的方式提交。
-
Verifier 对 VC 进行验证
这也是与传统流程最大的不同点。
借助前面提到的区块链和公私钥对的特点,Verifier 可以在不需要 Issuer 的配合下,验证 VC 的有效性。
-
Verifier 通过 VC 中的 issuer/Holdler DID, 可以从区块链上获取到 issuer/Holdler 的 DID Document
同时验证 issuer 的 DID 是否与已知的 DID 符合,例如某个大学或者政府机构对外公开的 DID
-
从 DID Document 中获取到 issuer 的公钥
-
通过 issuer 的公钥,验证 VC 中 proof 字段中的 issuer 的签名是否有效,以及 VC 是否被篡改
-
Verifier 通过 VC 中的 credentialSubject, 验证 VC 的持有人是否是当前提交 VC 的 Holder
如果 credentialSubject 字段被修改,那么前面的签名验证会失败
-
Verifier 通过 VC 中的 expirationDate, 验证 VC 是否过期或者注销(见本文后面的章节)
-
Verifier 可以拿着 Holder 的公钥对提供 VP 的 Holder 进行公私钥校验, 确认 Holder 确实持有和公钥匹配的私钥。
-
VP 概念的引入
在实际应用中,我们可能会将多个 VC 组合起来使用。
例如我们要去用人单位面试, 我们可能需要把身份证明、学历证明、工作经历(之前所在单位的在职证明)等多个证明组合提交给用人单位。
按照上一节的知识,我们知道用人单位作为 Verifier,很容易验证这些证明的有效性。
但是让用人单位去所有 VC 里一条一条的查询他们感兴趣的详细条目(claim)并不实际。
在现实中,我们一般是整合成一份简历,同时提供可以证明这些简历内容的对应资料。
在 DID 中也有类似的概念,叫做 VP (Verifiable Presentation).
VP 的例子
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"type": "VerifiablePresentation",
"verifiableCredential": [
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"credentialSchema": {
"id": "did:example:cdf:35LB7w9ueWbagPL94T9bMLtyXDj9pX5o",
"type": "did:example:schema:22KpkXgecryx9k7N6XN1QoN3gXwBkSU8SfyyYQG"
},
"issuer": "did:example:Wz4eUg7SetGfaUVCn8U9d62oDYrUJLuUtcy619",
"credentialSubject": {
"degreeType": "BachelorDegree",
"degreeSchool": "College of Engineering"
},
"proof": {
"type": "AnonCredDerivedCredentialv1",
"primaryProof": "cg7wLNSi48K5qNyAVMwdYqVHSMv1Ur8i...Fg2ZvWF6zGvcSAsym2sgSk737",
"nonRevocationProof": "mu6fg24MfJPU1HvSXsf3ybzKARib4WxG...RSce53M6UwQCxYshCuS3d2h"
}
}],
"proof": {
"type": "AnonCredPresentationProofv1",
"proofValue": "DgYdYMUYHURJLD7xdnWRinqWCEY5u5fK...j915Lt3hMzLHoPiPQ9sSVfRrs1D"
}
}
VP 中包含的内容
VP 中的内容有:
-
Holder 从各个 VC 中整理出来需要 Verfier 关注的 Claim 内容
-
这些 Claims 所引用到的 VC 的原文内容(VC 的数组)
-
Holder 使用私钥对这些内容进行的签名
Verifier 对 VP 的验证
在收到 VP 之后,Verifier 可以进行如下内容验证
-
根据 VP/VC 中的 Issuer 和 Holder 的 DID,获取他们的 DID document,进而获取到他们的公钥
-
对 VC(VP 中的 VC) 里用 issuer 私钥签名的 proof,用 Issuer 的公钥进行签名验证。
-
对 VP 里用 holder 私钥签名的 proof,用 Holder 的公钥进行签名验证。
-
验证 VP 里的内容都是来自于 VC 的, Holder 没有篡改。
-
和 VC 的验证过程类似,Verifier 可以拿着 Holder 的公钥对提供 VP 的 Holder 进行公私钥校验, 确认 Holder 确实持有和公钥匹配的私钥。
-
验证是否有 VC 过期或者注销(见本文后面的章节)
ZKProof
VP 允许在不披露 claims 的详情的前提下,让 Verifier 能证明某个事实存在。
例如不披露年龄,但是可以证明 Holder 的年龄大于 18 岁。
此节细节待后续填坑。
VC 的作废
-
VC 里可以设置过期时间
-
如果 issuer 需要提前作废某个 VC, 可以进行如下操作
(例如学生意外退学后,学籍需要注销)
在 issuer 的 DID Document 中,增加一个 Revocation List (吊销列表), 例如一个智能钱包地址。
issuer 可以按需往这个钱包里通过交易更新吊销后的 VC 的 ID。
Verifier 可以通过 issuer 的 DID Document 来查询指定的 VC 是否出现在这个吊销列表中。
DID 没有完全解决的问题
我认为 DID 没有完全解决电子身份和现实中的身份的对应关系。
例如域名和实体的对应关系。
因为 issuer 基本不会去配合提供私钥来验证自己的身份。
所以我们一般通过著名机构公开的 DID 地址来确认 issuer 是否我们认为的机构。
但是如果是相对不知名的 issuer, 或者 issuer 公布自己 DID 地址的方式被人攻击篡改(例如黑掉大学的网页修改他们公布的 DID 地址),那么我们就无法 100%确认 issuer 的身份。
补充说明
在整理这个文章的时候,我发现 W3C 网站更新了一篇 2024-1-13 的文章 Verifiable Credentials Data Model v2.0。
等我学习后再来补充这篇文档。