我对 W3C DID 1.0 标准的理解

先放官方链接

我对这个东西的理解比较肤浅,仅供参考。

DID 的全称

DID 的全称为 Decentralized Identifiers (去中心化身份)

现有的中心化的应用场景

我喜欢用如下生活体验的场景来解释 DID 的作用:

  • 证明的签署和发放

    (证明的)发行方签署证明后,为(证明的)持有人发放证明

    • 政府公民发放身份证
    • 银行用户发放资产证明
    • 大学学生发放毕业证书
    • 公司员工提供在职证明
  • 证明的使用(提交)

    持有人将自己获得的证明提交给验证方以证明某些信息

    • 公民身份证提交给验证方以证明自己的公民身份 (例如去高铁站身份证买票乘车)
    • 用户资产证明提交给验证方以证明自己的资产 (例如去领事馆办理旅游签证)
    • 学生毕业证书提交给验证方以证明自己的学历 (例如去用人单位面试)
    • 员工在职证明提交给验证方以证明自己的在职状态 (例如去银行办理贷款)
  • 证明的真实性验证

    验证方对证明的真实性进行验证

    • 高铁站需要验证身份证的真实性,以及是否属于持有人
    • 领事馆需要验证资产证明的真实性,以及是否属于持有人
    • 用人单位需要验证毕业证书的真实性,以及是否属于持有人
    • 银行需要验证在职证明的真实性,以及是否属于持有人

这些证明都是由某个发行方签发的,而且都是中心化的。

这里的中心化的意思是,如果验证方需要验证这些证明的有效性,需要联系发行方

对于身份证验证方需要使用设备读取身份证上的信息,然后通过网络连接政府提供的服务器来验证身份证的有效性。 对于资产证明验证方如果只是通过查看公章,那么伪造一枚公章可能就可以欺骗验证方。为了更准确的验证,验证方需要联系银行,通过银行的来验证资产证明的有效性。 其他的证明也是类似的。

中心化的解决方案存在的问题显而易见:

  1. 发行方的提供的验证服务可能被假冒
  2. 发行方的提供的验证服务可能因为异常而中断
  3. 一些小的发行方, 可能根本就没有能力提供验证服务
  4. 对于一些防伪程度不高的证明,发行方本身可能也无法确认是否由自己发放
  5. 其他未详细列出的问题

(一个特殊的例子是, 毕业证书可以去教育部网站查询,虽然不直接由发行方(大学)提供验证,但是这种验证方式也是中心化的)

用流程图描述上面的过程如下:

传统的证明流程

去中心化的解决方案

因为本文的主题是 DID (Decentralized Identifiers), 我们就来看看 DID 是如何解决上面的问题的。

DID 为我们提供的解决方案如下:

参与 DID 流程的三方分别叫做 Issuer, Holder, Verifier

  1. Issuer 为 Holder 颁发 VC (Verifiable Credential)

  2. Holder 拿到 VC 后, 可以按需将 VC 提供给 Verifier 进行验证。

  3. Verifier 收到 Holder 发来的 VC 之后, 可以在不需要 Issuer 配合,甚至不需要知会 Issuer 的情况下,验证 VC 的有效性。

    即如下内容

    • 这份 VC 是否由对应的 Issuer 签发

    • VC 是签发给当前提交 VC 的 Holder,而不是其他 Holder

    • VC 里的内容是否被篡改过

  4. Verifier 验证了 VC 的有效性后,可以根据 VC 里的内容,决定是否给 Holder 提供服务

    VC 里的内容在 DID 中称作 claim`

    例如身份证对应的 VC 里包含了以下 claim`

    • 身份证号
    • 姓名
    • 性别
    • 出生日期
    • 发证机构
    • 证件有效期

DID的流程

从步骤中可以看出,第 1、2、4 步都是和传统的流程一样的,只有第 3 步不一样,他是怎么做到的呢?

DID 的实现基础

公私钥对

公私钥对是非对称加密的基础,这里不再赘述。 相关文档网络上很多,例如这篇文章

主要场景有两种, 一种是加密解密, 一种是签名验证

  1. 加密解密过程 对于数据 data

    • 用公钥对数据 data 进行加密后的结果为 encrypted_data = encrypt(data, public_key)

    • 私钥对加密后的数据进行解密后的结果为 decrypted_data = decrypt(encrypted_data, private_key)

    • 如果加密的公钥和解密的私钥不对应,那么解密会失败

    • 一旦解密成功,那么 decrypted_data 就和 data 的内容一致

  2. 签名验证 对于数据 data

    • 用私钥对数据签名后的结果对 singature = sign(data, private_key)

    • 用公钥+data+签名 singature, 可以验证这个签名结果 verify(data, signature, public_key)

    • 如果签名的私钥和公钥不对应,或者数据被篡改了,那么验签结果会失败。

所以当乙需要验证甲的身份时,可以通过如下方式解决

  • 甲生成公私钥对

  • 甲自己持有私钥,然后将公钥提供给乙。

  1. 通过加密方式验证身份

    • 乙随机产生一份 data, 用公钥加密

    • 乙将加密后的数据发送给甲

    • 甲用私钥解密,如果解密成功,则身份验证通过

    • (解密后的数据可能是用于某个系统的登录 token, 这样乙就完成了对”甲是否真的解密成功”的验证)

  2. 通过签名方式验证身份

    • 乙随机生成一个 data

    • 乙将 data 的明文发送给甲

    • 甲用私钥对 data 进行签名,然后将签名后的结果发送给乙

    • 乙用公钥+data+签名结果,验证签名的有效性,如果验证成功,则身份验证通过

公私钥对验证身份的这两种方式,侧重点不同

  • 加密解密侧重于信息的保密性

    信息传输过程中数据是加密的, 所以即使被截获, 也无法知道数据的内容

  • 签名验证侧重于信息的来源和完整性

    数据原文是明文传输的, 接收方无需解密,但可以通过签名验证数据的来源和完整性

在 DID 中需要用到的特性为:

持有公钥的一方,可以验证对方是否持有对应的私钥

区块链

区块链+智能合约有如下特性

  • 对信息的存储和获取

    任何人都可以将信息存储到区块链的去中心化存储体系上,任何人都可以从区块链上获取信息

  • 不可篡改

    在区块生成后,即使是上传方也无法恶意修改自己提交过的信息。

  • 透明性

    任何人都可以根据智能合约的代码,验证智能合约的行为是否符合预期

  • 身份验证

    上传信息到区块链时,可以通过智能合约的代码,验证上传者的身份,避免信息被伪造

在 DID 中需要用到的特性为:

对于某个固定的 key, 可以往区块链上存储指定的信息,任何人也可以通过这个 key 查询回该信息,

DID 的实现原理

  1. Issuer 和 Holder 如下一次性准备工作:

    在参与到 DID 流程之前需要进行的准备工作, 且只需要操作一次即可

    • 生成公私钥对

    • 生成 DID

      格式如 did:example:123456789abcdefghi

      DID格式

      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

  2. 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"
        }
      }
      
  3. Holder 提交 VC 给 Verifier

    DID 协议 1.0 中并未规定 Holder 如何提交 VC 给 Verifier,只是提到以双方认可的安全的方式提交。

  4. 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

等我学习后再来补充这篇文档。