Skip to content

Latest commit

 

History

History
948 lines (773 loc) · 45.9 KB

Elastos-DID-Method-Specification_cn.md

File metadata and controls

948 lines (773 loc) · 45.9 KB

亦来云DID方法规范 v2.0

区块链驱动的智能万维网


亦来云基金会

2019年11月30日

版本

2.0

内容说明

此文档是亦来云DID方法技术规范,由亦来云基金会发布并维护。主要说明了亦来云DID的通用数据模型和格式,以及相关的操作。未来我们会持续升级此文档,以体现亦来云DID技术最新发展状态。

版权声明

此文档著作权归亦来云基金会所有,保留所有权利。

概述

当下互联网上身份标示系统都是中心化系统,大都是由互联网服务巨头提供,在这种情况下,我们不得不选择信任这些互联网服务商(无论是公司、机构还是其他组织),他们收集我们的数据,于此同时也有保护数据安全的义务。看似本身没有什么问题,但数据安全的问题时有发生,用户身份被泄露的情况非常严重,个人对自己的身份信息没有任何控制力,甚至服务商可以在用户完全不知情的状况下恶意泄露个人身份信息。

随着区块链技术的发展,技术社区提出了基于区块链技术实现的去中心ID系统,数字身份不再由中心化的服务商提供,而是记录在去中心的区块链上。同时数字身份完全由用户控制,不再依赖于中心化机构对数据的控制,而且DID是可验证的,可以同时用于身份验证和数据加密等多种场景。

DID完全由DID主体控制,不依赖于任何集中式注册机构、身份提供商或证书颁发机构。DID通过DID文档来描述,每个DID文档至少包含两个组件:加密材料、身份验证套件。与身份验证套件相结合的加密材料提供了一组身份验证机制(如公钥、匿名生物识别协议等),其它的可选部分可以根据应用和用户的需求来使用。

本规范的目的

制定本规范有两个目的,首先是定义一个亦来云体系内标准的DID文档描述格式和基本DID属性集,使得亦来云生态上的应用可以理解标准集中定义的基本数字身份信息,从而实现数字身份在亦来云生态体系内的标准化;其次是定义一组通用的操作方法,这些操作可以为任何dApp使用,实现对亦来云DID服务的引用。

设计目标

本规范的设计是基于W3C DID规范讨论稿,同时参考了DIF相关的文档和代码,采用了W3C DID的一个子集,符合W3C DID规范要求。

简洁性和易用性也是本设计的一个重要考量因素,希望DID文档能够在人类可读性、结构化、便于处理和使用等方面达到一个合理的平衡。DID相关操作方法有良好的易用性,降低dApp中使用DID的工程成本。

W3C DID规范讨论稿中的一些术语本文不再重复说明,可参阅原文。

DID方法

亦来云DID method固定为elastos。在亦来云应用体系内可以省略method,直接使用did:specific-idstring,应用默认识别为elastos的method,即有效的亦来云DID。

目标系统

亦来云DID的DLT后端采用亦来云ID侧链,并且适用于亦来云所有系统和dApps。

DID相关的操作行为由DID主题持有者通过DID客户端发起交易来实现,DID相关的操作和DID文档都保存在交易的payload中。

DID描述符

亦来云DID采用W3C DID规范讨论稿中的定义的描述格式,是符合RFC3986标准的URI,它由DID后跟可选路径和或片段组成。

下面是使用RFC5234语法的亦来云DID描述符的ABNF定义:

did                = "did:" method ":" specific-idstring ;
method             = "elastos"
specific-idstring  = idstring *( ":" idstring ) ;
idstring           = BASE58 / 1*idchar ;

did-url            = did [ "/" did-path ] [ "#" did-fragment ] ;
did-path           = path-rootless ;
path-rootless      = segment-nz *( "/" segment ) ;
segment            = *pchar ;
segment-nz         = 1*pchar ;
did-fragment       = fragment ;
fragment           = *( pchar / "/" / "?" ) ;
idchar             = unreserved / pct-encoded ;
pchar              = unreserved / pct-encoded / sub-delims / ":" / "@" ;

unreserved         = ALPHA / DIGIT / "-" / "." / "_" / "~" ;
pct-encoded        = "%" HEXDIG HEXDIG
sub-delims         = "!" / "$" / "&" / "'" / "(" / ")"
                     / "*" / "+" / "," / ";" / "=" ;

    ALPHA          =  %x41-5A / %x61-7A ;
    DIGIT          =  %x30-39 ;
    HEXDIG         = DIGIT / "A" / "B" / "C" / "D" / "E" / "F" ;
    BASE58         =  Bitcoin style base58 encoded string ;

DID字符串

亦来云DID中的ID字符串支持两种格式:第一种是默认标识符,使用Bitcoin风格Base58编码的ID侧链地址,并且以字母i开始,如icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN,ID字符串区分大小写;第二种是用户自定义标识符,也具有唯一性。本文档中支持默认标识符的DID称为普通DID(primitive DID),支持自定义标识符的DID被称为自定义DID(customized DID)。

DID文档

DID文档格式

DID文档必须是符合RFC8259的单个JSON对象,同时在ID侧链上存储的DID文档数据也是基于JSON格式的。亦来云DID文档不采用W3C DID规范讨论稿指定的JSON-LD格式,仅使用简单的JSON,这样的设计是为了保持DID文档的简洁和应用开发的方便。相关的属性、命名采用和W3C DID规范一致的定义;同时为了和W3C DID标准互操作,亦来云DID将提供到W3C DID文档的映射机制。

DID文档属性

主题

主题是DID文档的唯一标识符,用来表示对应的DID文档。主题的规则如下:

  • DID文档必须有一个且只有一个DID主题。
  • 主题的key必须是id
  • 主题的值必须是一个有效的DID描述符。

例如:

普通DID:

{
  "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN"
}

自定义DID:

{
  "id": "did:elastos:example"
}

持有者/Controller(可选)

持有者是一组普通DID集,即每个持有者是一个独立的普通DID,具备最基本的认证属性,可代表主题DID实现签名和认证操作,亦可被视为主题DID的委托者。亦来云现仅支持自定义DID包含持有者(普通DID不支持持有者)。持有者可更改主题DID文档,支持主题DID上链等相关操作。

持有者的规则是:

  • 自定义DID必须且仅包含一个controller属性。
  • controller必须是普通DID字符串或者普通DID数组。

持有者属性至少包含一个普通DID;多个持有者之间功能相等,无主次无优先。

例如:

多持有者DID

{
  "id": "did:elastos:example",
  "controller": [
        "did:elastos:iWFAUYhTa35c1fPe3iCJvihZHx6quumnym",
        "did:elastos:ijSM3fffVzAtAWM4DSypiFBY2mZSmN7JPv",
        "did:elastos:ir31cZZbBQUFbp4pNpMQApkAyJ9dno3frB"
   ],
   "multisig": "2:3",
  ...
}

单持有者DID

{
  "id": "did:elastos:example",
  "controller": "did:elastos:iWFAUYhTa35c1fPe3iCJvihZHx6quumnym",
  ...
}

多重签名/Multisig(可选)

多重签名是基于多持有者(非单持有者)的DID而设定的,建立DID文档多签的基本准则。

多重签名的规则是:

  • 自定义DID在多持有者情况下,必须包含多重签名。
  • multisig属性的值是基本格式为"m/n"的字符串,其中n为持有者个数(n > 1),m为多重签名者个数(m <= n)。

例如:

{
  "id": "did:elastos:example",
  "controller": [
        "did:elastos:iWFAUYhTa35c1fPe3iCJvihZHx6quumnym",
        "did:elastos:ijSM3fffVzAtAWM4DSypiFBY2mZSmN7JPv",
        "did:elastos:ir31cZZbBQUFbp4pNpMQApkAyJ9dno3frB"
   ],
   "multisig": "2:3",
  ...
}

公钥/Public Keys(可选)

公钥用于数字签名、加密等操作,主要的目的是实现身份认证,或与服务端点建立安全通信。 此外,公钥也可用于DID授权和委托,并在DID CRUD操作中用来验证操作的合法性。

公钥的规则是:

  • 普通DID文档必须包含一个publicKey属性;自定义DID文档可以不包含该属性。
  • publicKey属性的值必须是公钥数组。
  • 每个公钥必须包含idtype属性。 公钥数组不应该包含具有相同id和具有不同格式的不同值属性的重复条目。
  • id属性值由该DID标识符和一个自定义的URI片段构成,如did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#master-key,当DID标识符和文档subject相同的情况下,出于保持数据紧凑的目的,可以省略前面的DID标识符,而仅使用URI片段部分,如#master-key
  • 亦来云公钥的type默认是ECDSAsecp256r1
  • 每个公钥可以包含一个controller属性,表示相应私钥控制者的DID;默认为所在文档的DID,这种情况可省略该属性。
  • 每个公钥必须包含一个publicKeyBase58 属性,用于存放Base58编码的公钥。

亦来云普通DID文档中至少需要包含一个主公钥(default key)。

例如:

{
  "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN",
  "publicKey": [{ // 和DID地址对应的公钥
    "id": "#primary",
    "type": "ECDSAsecp256r1",
    "controller": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN",
    "publicKeyBase58": "zNxoZaZLdackZQNMas7sCkPRHZsJ3BtdjEvM2y5gNvKJ"
  }, { // 本DID持有者持有的第二个公钥,此处省略了type和controller
    "id": "#key-2",
    "publicKeyBase58": "273j8fQ1ZZVM6U6d5XE3X8SyULuJwjyYXbxNopXVuftBe"
  }, { // 用于恢复的公钥,本DID持有者的可信的第三方持有
    "id": "#recovery-key",
    "type": "ECDSAsecp256r1",
    "controller": "did:elastos:ip7ntDo2metGnU8wGP4FnyKCUdbHm4BPDh",
    "publicKeyBase58": "zppy33i2r3uC1LT3RFcLqJJPFpYuZPDuKMeKZ5TdAskM"
  }],
  ...
}

认证/Authentication (可选)

认证是实体可以通过加密方式证明他们与DID相关联的机制。 认证属性可以指定哪些DID的公钥可以被用来进行身份认证。基于ID侧链的技术实现特征,DID主题对应的公钥在默认的情况下具备身份认证功能,即使没有显式的声明。

身份验证的规则是:

  • 普通DID文档必须包含且最多一个authentication属性;自定义DID文档可以不包含该属性。
  • authentication属性的值是一个验证方法数组,即可用于身份验证的公钥数组。
  • 可以嵌入或引用验证方法。 在引用时是一个完整的公钥URI,或者仅仅是片段部分,如:did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#primary#primary相同,都是同一个公钥的引用。如果使用嵌入的公钥,公钥的书写规则和[公钥属性](#公钥/Public Keys)一致。
  • 普通DID文档的authentication数组至少有一个公钥,即为主公钥。

例如:

{
  "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN",
  ...
  "authentication": [
    // 可以用于认证的公钥引用
    "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#primary",
    // 可以用于认证的公钥引用
    "#key-2",
    // *仅仅用于* 认证的公钥,采用内嵌的形式书写在authentication中,
    // 这个公钥不能被用于其他的目的
    {
      "id": "#keys-3",
      "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
    }
  ],
  ...
}

授权和委托/Authorization and Delegation(可选)

授权是用于说明如何代表DID主题执行操作的机制。 委托是指DID主题可以授权他人代表他们行事的机制。 这对于DID密钥丢失情况下的DID安全善后事宜尤其重要,当主体不再能够访问其密钥或密钥泄露时,DID持有者授权的可信第三方可以声明停用该DID,从而禁止在密钥泄露的情况下导致的一些恶意行为。

亦来云DID的授权和委托仅支持必要的最小授权,即授权可信第三方用于停用目标DID,不支持其它操作。

授权和委托的规则是:

  • 普通DID文档可以包含最多一个authorization属性;自定义DID文档不可包含该属性,其由持有者来实现该功能。
  • authorization属性的值应该是一个验证方法数组,即可用于委托的公钥数组。
  • 可以嵌入或引用每种验证方法。 在引用时可以是一个完整的公钥URI,或者仅仅是片段部分,如:did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#recovery-key#recovery-key相同,都是同一个公钥的引用。如果使用嵌入的公钥,公钥的书写规则和公钥属性一致。
{
  "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN",
  ...
  "authorization": [
    // 委托的目标公钥引用,也可以简写为 "#recovery-key"
    "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#recovery-key",
    // *仅仅用于* 委托的公钥,采用内嵌的形式书写在authorization中,
    // 这个公钥不能被用于其他的目的
    {
      "id": "#keys-3",
      "controller": "did:elastos:iZUeeATkmBwLuEx4B41P6cvvFQYuzSQJxf",
      "publicKeyBase58": "cheFmhCj9DcSvjYEFeCQQFrrVJnG8sg3xvXRPeP1xRxi"
    }
  ],
  ...
}

可验证凭证/VerifiableCredential(可选)

按照DID设计的初衷,原则上DID文档不应该携带任何个人信息/PII(Personally-Identifiable Information),或者携带可以关联到具体实体的关键信息。但是从现实世界的需求看,有些DID实体具有公开身份的需求,比如作为well-known的Crendential Issuers等,所以亦来云DID文档可以内嵌公开的可验证凭证,来支持有DID公开绑定实体信息的需求。可验证凭证详细定义可以参[亦来云可验证声明规范](Elastos Verifiable Claims Specification.md)。

可验证凭证的规则是:

  • DID文档可以包含最多一个verifiableCredential属性。
  • verifiableCredential属性的值应该是一个可验证凭证(Verifiable Credential)的数组。
  • id属性值的格式是由该DID标识符和一个自定义的URI片段构成,如did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#recovery-key,当DID标识符和文档subject相同的情况下,出于保持数据紧凑的目的,可以省略前面的DID标识符,而仅使用URI片段部分,如#recovery-key
  • 在可验证凭证中可以省略credentialSubject中的id属性,默认是当前DID主题。

例如:

{
  "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN",
  ...
  "verifiableCredential": [{
    // specify the identifier for the credential, in long format
    "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#crdential-1",
    // the credential types, which declare what data to expect in the credential
    "type": ["SelfProclaimedCredential", "BasicProfileCredential"],
    // when the credential was issued
    "issuanceDate": "2019-01-01T19:20:18Z",
    "credentialSubject": {
      // assertion about the subject of the credential
      "nickname": "woohah",
      "nation": "Singapore",
      "language": "English"
    },
    // this proof can be omitted, because it's a self proclaimed credential
    "proof": {
      // the cryptographic signature suite that was used to generate the signature
      "type": "ECDSAsecp256r1",
      // the public key identifier that created the signature
      "created": "2019-01-01T19:20:18Z",
      "verificationMethod": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#master-key",
      "signatureValue": "pYw8XNi1..Cky6Ed="
    }
  }, {
    // specify the identifier for the credential, in short format
    "id": "#crdential-2",
    // the credential types, which declare what data to expect in the credential
    "type": ["ElastosIDteriaCredential", "InternetAccountCredential"],
    // the entity that issued the credential
    "issuer": "did:elastos:iY3PF8u1bYMujq6Z4bk2iAnmRFyD1cqbSw",
    // when the credential was issued
    "issuanceDate": "2019-01-01T19:20:18Z",
    // when the credential will expire
    "expirationDate": "2020-01-01T19:23:24Z",
    // claims about the subject of the credential
    "credentialSubject": {
      "email": "[email protected]",
      "phone": "+16693553638",
      "googleAccount": "[email protected]",
      "twitter": "@woohah"
    },
    // digital proof that makes the credential tamper-evident
    "proof": {
      // the cryptographic signature suite that was used to generate the signature
      "type": "ECDSAsecp256r1",
      // the public key identifier that created the signature
      "created": "2019-01-01T19:20:18Z",
      "verificationMethod": "did:elastos:iY3PF8u1bYMujq6Z4bk2iAnmRFyD1cqbSw#sign-key",
      // the digital signature value
      "signature": "BavEll0...W3JT24="
    }
  }],
  ...
}

服务端点/Service Endpoints(可选)

除了发布身份验证和授权机制之外,DID文档的另一个主要目的是发布DID主题对应的服务端点 。服务端点可以表示主体希望通告的任何类型的服务,包括用于进一步发现,认证,授权或交互的分散身份管理服务。

服务端点的规则是:

  • DID文档可以包含最多一个service属性。
  • service属性的值应该是服务端点的数组。
  • 每个服务端点必须包含idtypeserviceEndpoint属性,同时支持应用自定义属性。
  • 服务端点协议应该以开放标准规范发布。
  • serviceEndpoint属性的值必须是符合RFC3986的有效URI,并根据RFC3986第6节中的规则进行规范化。

例如:

{
  "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN",
  ...
  "service": [{
    "id": "#openid",
    "type": "OpenIdConnectVersion1.0Service",
    "serviceEndpoint": "https://openid.example.com/"
  }, {
    "id": "#vcr",
    "type": "CredentialRepositoryService",
    "serviceEndpoint": "https://did.elastos.org/credential"
  }, {
    "id": "#carrier",
    "type": "CarrierAddress",
    "serviceEndpoint": "carrier://X2tDd1ZTErwnHNot8pTdhp7C7Y9FxMPGD8ppiasUT4UsHH2BpF1d"
    "description": "My public social inbox", // extra property
    "spamCost": { // extra property
      "amount": "0.50", 
      "currency": "USD" 
    }
  }],
  ...
}

创建/Created(无)

亦来云DID文档中不包含创建属性,因为采用ID侧链交易进行记录,所以天然具时间戳,无需文档中显式的声明创建时间。亦来云的DID解析器在从链上获取DID文档时,会自动补充该属性。

更新/Updated(无)

亦来云DID文档中不包含更新属性,因为采用ID侧链交易进行记录,所以天然具时间戳,无需文档中显示的声明更新时间。亦来云的DID解析器在从链上获取DID文档时,会自动补充该属性。

证据/Proof

DID文档的Proof属性是用来对DID文档的完整性提供加密证明的信息。为了保证DID文档的可信以及完整性,Proof中需要包含针对该DID文档的签名,从而保证文档的完整性,以及防止中间人攻击。普通DID文档的签名必须使用DID主题对应的密钥生成,自定义DID文档的签名根据多重签名规则由持有者使用主公钥签名完成。

Proof的规则是:

  • DID文档必须包含最多一个proof属性。
  • proof属性的值是单个签名或者多个签名的数组。
  • 每个proof必须包含createdcreatorsignatureValue属性。
  • type默认是ECDSAsecp256r1,可以省略。
  • created表示签名创建时间。
  • creator表示验证签名的密钥引用。
  • signatureValue表示签名的值,使用Base64URL编码。

例如,普通DID文档:

{
  "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN",
  ...
  "proof": {
    "type": "ECDSAsecp256r1",
    "created": "2020-01-01T19:23:24Z",    
    "creator": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#primary",
    "signatureValue": "QNB13Y7Q9...1tzjn4w"
  }
}

自定义多持有者DID文档如下:

{
    "id": "did:elastos:example",
    "controller": [
        "did:elastos:iWFAUYhTa35c1fPe3iCJvihZHx6quumnym",
        "did:elastos:ijSM3fffVzAtAWM4DSypiFBY2mZSmN7JPv",
        "did:elastos:ir31cZZbBQUFbp4pNpMQApkAyJ9dno3frB"
    ],
    "multisig": "2:3",
    ...
    "proof": [
        {
            "type": "ECDSAsecp256r1",
            "created": "2020-12-10T07:13:57Z",
            "creator": "did:elastos:ijSM3fffVzAtAWM4DSypiFBY2mZSmN7JPv#primary",
            "signatureValue": "d9loBxvR_Zpt-TgAJSquCQjXSi36m4YMw1tuIdrYmNSj4XkTw4u1e0MlyrqphXFQ1psYSGPQ_qr970882BBMzw"
        },
        {
            "type": "ECDSAsecp256r1",
            "created": "2020-12-10T07:13:57Z",
            "creator": "did:elastos:ir31cZZbBQUFbp4pNpMQApkAyJ9dno3frB#primary",
            "signatureValue": "hSa0apINKgyuh49wZ2dnr-h5zwBGlevY8IUHyIWP-BIkZuBKkQqQIOBJc5Ef4lvs1DMjy3GS8QLqFsx1m2k2mQ"
        }
    ]
}

过期/Expires

出于安全的考虑,亦来云DID主题具有有效期,最长有效期可以设定为5年,用户也可以根据自身需求设定为更短的有效期。超出有效期的DID主题则会被DID解析器识别为无效DID主题。

过期的规则是:

  • DID文档必须包含一个expires属性。
  • 此键的值必须是有效的RFC3339组合日期和时间的字符串值。
  • 该日期时间值必须标准化为UTC时间,尾随“Z”。

例如:

{
  "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN",
  ...
  "expires": "2024-02-10T17:00:00Z"
}

可扩展性

应用可以在遵循上述文档定义的标准属性之外,根据应用的需要对DID文档进行扩展。扩展的部分应该遵循上述文档格式的约定,在增加应用自定义属性时,建议使用JSON-LD声明扩展属性的context,以便于亦来云DID客户端将亦来云DID文档规范化为W3C标准兼容的DID文档时,正确的处理应用扩展属性;否则,应用的扩展属性将被忽略,不被包含在规范化的DID文档结果中。

关于扩展属性的处理以及JSON-LD的context的约束,目前在没有实际应用的情况下,上述的规则只是一个设想,后续可以根据应用的需求以及DID文档的规范化处理情况再进行调整。

DID操作

亦来云DID文档存储是基于ID侧链的,所以相关的操作都需要在支持ID侧链的客户端中操作。普通DID需要使用对应DID主题的认证公钥给自己发起交易来实现;自定义DID可以使用对应DID主题的公钥或者持有者的认证公钥来发起交易。但是普通DID停用例外,允许DID主题授权和委托的DID公钥发起相关操作。

DID操作和对应的文档采用JSON格式保存在交易的payload中,DID操作JSON文档的属性定义如下:

  • 必须包含一个header属性,该属性包含DID操作的基本信息。header的属性定义如下:
    • 必须包含一个specification属性,表示DID操作所符合的规范和版本,该规范支持elastos/did/1.0
    • 必须包含一个operation属性,用来说明执行何种操作,属性值参见具体操作。
    • 根据操作需要,可以包含一个previousTxid属性。属性定义参见具体操作。
    • 根据操作需要,可以包含一个ticket属性。属性定义参见具体操作。
  • 必须包含一个payload属性,属性值是操作的目标DID文档或者DID主题。
  • 必须包含一个proof属性,该属性包含对应DID主题的公钥或者持有者的认证公钥和签名,用于证明是持有者本人或者委推人的操作。proof属性定义如下:
    • type默认是ECDSAsecp256r1,可以省略。
    • verificationMethod表示证明方法,值是颁发者DID文档中用于签名和验证的公钥引用。
    • signature表示签名的值,使用Base64URL编码。

因为区块链是经济驱动的,交易需要手续费,并且payload也需要根据大小额外收费,所以从经济性的角度考虑,DID文档的要尽量紧凑,控制上链的大小,所以一般而言,上链的DID文档可以省略默认的属性,如公钥的type,文档内属性引用的URI尽量减写等等,可以有效降低DID操作的费用。

创建/Create DID

创建DID需要DID客户端基于本地生成DID文档,使用相关密钥对生成上链内容,完成创建操作。

创建DID的规则是:

  • 必须包含一个header属性,其中operation属性值是create,表示新创建DID。
  • 必须包含payload属性,值是目标DID文档采用Base64URL模式编码的文档。
  • 必须包含一个proof属性,包含公钥引用和签名,用于证明该操作是DID本身或者持有者发起。

例如:

{
  "header": {
    "specification": "elastos/did/1.0",
    "operation": "create"
  },
  "payload": "ICAiZG9jIjogewogICAgImlkIjogImRpZDplbGFzdG9zOmljSjR6MkRVTHJIRXpZU3ZqS05KcEt5aHFGRHh2WVY3cE4iLAogICAgInB1YmxpY0tleSI6IFt7CiAgICAgICJpZCI6ICIjbWFzdGVyLWtleSIsCiAgICAgICJwdWJsaWNLZXlCYXNlNTgiOiAiek54b1phWkxkYWNrWlFOTWFzN3NDa1BSSFpzSjNCdGRqRXZNMnk1Z052S0oiCiAgICB9LCB7CiAgICAgICJpZCI6ICIja2V5LTIiLAogICAgICAicHVibGljS2V5QmFzZTU4IjogIjI3M2o4ZlExWlpWTTZVNmQ1WEUzWDhTeVVMdUp3anlZWGJ4Tm9wWFZ1ZnRCZSIKICAgIH0sIHsKICAgICAgImlkIjogIiNyZWNvdmVyeS1rZXkiLAogICAgICAiY29udHJvbGxlciI6ICJkaWQ6ZWxhc3RvczppcDdudERvMm1ldEduVTh3R1A0Rm55S0NVZGJIbTRCUERoIiwKICAgICAgInB1YmxpY0tleUJhc2U1OCI6ICJ6cHB5MzNpMnIzdUMxTFQzUkZjTHFKSlBGcFl1WlBEdUtNZUtaNVRkQXNrTSIKICAgIH1dLAogICAgImF1dGhlbnRpY2F0aW9uIjogWwogICAgICAibWFzdGVyLWtleXMiLAogICAgICAiI2tleS0yIiwKICAgIF0sCiAgICAuLi4KICB9LA",
  "proof": {
    "type": "ECDSAsecp256r1",
    "verificationMethod": "#master-key",
    "signature": "JCAlfEBh...I3NSwg="
  }
}

其中payload是以下DID文档通过Base64URL编码后的结果:

{
    "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN",
    "publicKey": [{
      "id": "#master-key",
      "publicKeyBase58": "zNxoZaZLdackZQNMas7sCkPRHZsJ3BtdjEvM2y5gNvKJ"
    }, {
      "id": "#key-2",
      "publicKeyBase58": "273j8fQ1ZZVM6U6d5XE3X8SyULuJwjyYXbxNopXVuftBe"
    }, {
      "id": "#recovery-key",
      "controller": "did:elastos:ip7ntDo2metGnU8wGP4FnyKCUdbHm4BPDh",
      "publicKeyBase58": "zppy33i2r3uC1LT3RFcLqJJPFpYuZPDuKMeKZ5TdAskM"
    }],
    "authentication": [
      "master-keys",
      "#key-2",
    ],
    ...
}

更新/Update DID

DID只有DID本身或者持有者具有更新DID的权力。对于自定义DID,更换持有者不属于更新操作。非DID主题持有者发起的更新DID交易都会被ID侧链丢弃,不对目标DID产生任何影响。更新DID时不支持增量更新,需要在更新交易中附加完整的DID文档。

更新DID的规则是:

  • 必须包含一个header属性,其中 operation属性值是update,表示更新DID。
  • header需要包含previousTxid 属性,值是前一个DID文档操作的交易ID。用来避免不必要的错误更新操作。
  • 必须包含payload属性,值是新的DID文档。
  • 必须包含一个proof属性,包含公钥引用和签名,用于证明该操作是DID本身或者DID持有者发起。

例如:

{
  "header": {
    "specification": "elastos/did/1.0",
    "operation": "update",
    "previousTxid": "3641de55f368583c...8917756a872093d2"
  },
  "payload": "ICAiZG9jIjogewogICAgImlkIjogImRpZDplbGFzdG9zOmljSjR6MkRVTHJIRXpZU3ZqS05KcEt5aHFGRHh2WVY3cE4iLAogICAgInB1YmxpY0tleSI6IFt7CiAgICAgICJpZCI6ICIjbWFzdGVyLWtleSIsCiAgICAgICJwdWJsaWNLZXlCYXNlNTgiOiAiek54b1phWkxkYWNrWlFOTWFzN3NDa1BSSFpzSjNCdGRqRXZNMnk1Z052S0oiCiAgICB9LCB7CiAgICAgICJpZCI6ICIja2V5LTIiLAogICAgICAicHVibGljS2V5QmFzZTU4IjogIjI3M2o4ZlExWlpWTTZVNmQ1WEUzWDhTeVVMdUp3anlZWGJ4Tm9wWFZ1ZnRCZSIKICAgIH0sIHsKICAgICAgImlkIjogIiNyZWNvdmVyeS1rZXkiLAogICAgICAiY29udHJvbGxlciI6ICJkaWQ6ZWxhc3RvczppcDdudERvMm1ldEduVTh3R1A0Rm55S0NVZGJIbTRCUERoIiwKICAgICAgInB1YmxpY0tleUJhc2U1OCI6ICJ6cHB5MzNpMnIzdUMxTFQzUkZjTHFKSlBGcFl1WlBEdUtNZUtaNVRkQXNrTSIKICAgIH1dLAogICAgImF1dGhlbnRpY2F0aW9uIjogWwogICAgICAibWFzdGVyLWtleXMiLAogICAgICAiI2tleS0yIiwKICAgIF0sCiAgICAuLi4KICB9LA",
  "proof": {
    "verificationMethod": "#master-key",
    "signature": "ZGhscJxw...tCAgQA="
  }
}

所有权转移/Transfer DID

自定义DID支持添加,删除持有者(自定义DID必须包含一个持有者)以及更改多重签名规则,当自定义DID文档发生持有者更改或者更改多重签名规则,就需要通过所有权转移交易来完成文档上链操作。

更改持有者是较为谨慎和严谨的操作,鉴于此特性,该交易必须同时基于修改后的文档和转移凭证(ticket),使用DID原持有者主密钥对来完成该交易。其中转移凭证的内容为DID主题,转移凭证的接收者和前一个DID文档操作的交易ID,转移凭证需要原持有者根据多重签名规则共同签名完成,以表示原持有者对更换持有者的认可。

转移凭证ticket的规则是:

  • 必须包含did属性,表示更换持有者的主体。
  • 必须包含to属性,表示转移凭证的接收者,必须为更改后的持有者之一,且更改后的文档包含该接收者的签名。
  • 必须包含txid属性,值是前一个DID文档操作的交易ID。
  • 必须包含proof属性,值是单一签名或者多个签名的数组。
  • 每个proof必须包含creatorsignature属性。
  • type默认是createdECDSAsecp256r1,可以省略。
  • created表示签名创建时间。
  • creator表示持有者主密钥引用。
  • signature表示签名的值,使用Base64URL编码。

例如:

{
	 "id":"did:elastos:littlefish",
	 "to":"did:elastos:ijSM3fffVzAtAWM4DSypiFBY2mZSmN7JPv",
	 "txid":"0fY6Fv74LOLX4oHlJZjcArySGzqklsJe",
	 "proof":[{
		 "type":"ECDSAsecp256r1",
		 "created":"2021-01-20T07:16:38Z",
		 "verificationMethod":"did:elastos:iWFAUYhTa35c1fPe3iCJvihZHx6quumnym#primary",
		 "signature":"02A7qf9mth6qjtlCC01LNrQK9pzxLwF16cOSIVU-YOWzgA9OaVwpPlDvzW68jKRdjLNg758ha69svrb_SrAhrA"
	  },{
		 "type":"ECDSAsecp256r1",
		 "created":"2021-01-20T07:16:38Z",
		 "verificationMethod":"did:elastos:ijSM3fffVzAtAWM4DSypiFBY2mZSmN7JPv#primary",
		 "signature":"1lR1zIwX7NAVVv1k-5vdGArl5XoQBAo-t91Km0ZSrnozuigulfel_ei_1PbpwvRwQvvZRfRtCn7fUNeGw2iKfg"
	 }, {
		 "type":"ECDSAsecp256r1",
		 "created":"2021-01-20T07:16:38Z",
		 "verificationMethod":"did:elastos:ir31cZZbBQUFbp4pNpMQApkAyJ9dno3frB#primary",
		 "signature":"TLBseQ6n5Qobg48vTWM03hS_PZv3nghRzPJMsGFqmueDcwf_YFlXBykKy8RLElE1F64crU2x04tinQWTWdb92A"
	}]
}

转移凭证采用Base64URL模式编码方式加入交易内容。

所有权转移的规则是:

  • 必须包含header属性,其中operation属性值是transfer,表示所有权转移。
  • header必须包含tikcet属性,值为转移凭证的Base64URL编码内容。
  • 必须包含payload属性,值是更改持有者后的新DID文档。
  • 必须包含一个proof属性,包含公钥引用和签名,用于证明该操作是DID本身或者DID持有者发起。

例如:

{
	"header":{
		 "specification":"elastos/did/1.0",
		 "operation":"transfer",
		 "ticket":"eyJpZCI6ImRpZDplbGFzdG9zOmphY2siLCJ0byI6ImRpZDplbGFzdG9zOmlqU00zZmZmVnpBdEFXTTREU3lwaUZCWTJtWlNtTjdKUHYiLCJ0eGlkIjoiMGZZNkZ2NzRMT0xYNG9IbEpaamNBcnlTR3pxa2xzSmUiLCJwcm9vZiI6W3sidHlwZSI6IkVDRFNBc2VjcDI1NnIxIiwiY3JlYXRlZCI6IjIwMjEtMDEtMjBUMDc6MjY6MTFaIiwidmVyaWZpY2F0aW9uTWV0aG9kIjoiZGlkOmVsYXN0b3M6aVdGQVVZaFRhMzVjMWZQZTNpQ0p2aWhaSHg2cXV1bW55bSNwcmltYXJ5Iiwic2lnbmF0dXJlVmFsdWUiOiJUS3ExeHA2NUViNDJtRmVGSEc2M05RMDNHSGRnSkZqd3B3WUNmZHJtTDJCbUtpZGZKRDBIa1Njcll2QnAxbi1Zd2VlbnRBN3JTNzB0LXRmVmtmbG5PZyJ9LHsidHlwZSI6IkVDRFNBc2VjcDI1NnIxIiwiY3JlYXRlZCI6IjIwMjEtMDEtMjBUMDc6MjY6MTFaIiwidmVyaWZpY2F0aW9uTWV0aG9kIjoiZGlkOmVsYXN0b3M6aWpTTTNmZmZWekF0QVdNNERTeXBpRkJZMm1aU21ON0pQdiNwcmltYXJ5Iiwic2lnbmF0dXJlVmFsdWUiOiJpMWhyb1lQX1J3dkJGdzdLcWhLY2d0bDNNNVo3UmJ5T2JCMDRwcDdMb0tKcjBZTUNEcnFVQ0ExdTZaVnRaUUs0UGUzNVdfTXVacERqWm9jdEYzdTl4USJ9XX0"
	 },
    "payload":"eyJpZCI6ImRpZDplbGFzdG9zOmphY2siLCJjb250cm9sbGVyIjpbImRpZDplbGFzdG9zOmlqU00zZmZmVnpBdEFXTTREU3lwaUZCWTJtWlNtTjdKUHYiLCJkaWQ6ZWxhc3RvczppcjMxY1paYkJRVUZicDRwTnBNUUFwa0F5Sjlkbm8zZnJCIl0sIm11bHRpc2lnIjoiMjoyIiwicHVibGljS2V5IjpbeyJpZCI6ImRpZDplbGFzdG9zOmphY2sja2V5MSIsInR5cGUiOiJFQ0RTQXNlY3AyNTZyMSIsImNvbnRyb2xsZXIiOiJkaWQ6ZWxhc3RvczpqYWNrIiwicHVibGljS2V5QmFzZTU4IjoielNlUXlFTkQ3a0tRNDc0Y2FwcTU0bmtzeTRxaXV2S25zVm50aHhrTXpxOWIifSx7ImlkIjoiZGlkOmVsYXN0b3M6amFjayNrZXkyIiwidHlwZSI6IkVDRFNBc2VjcDI1NnIxIiwiY29udHJvbGxlciI6ImRpZDplbGFzdG9zOmphY2siLCJwdWJsaWNLZXlCYXNlNTgiOiJkbjJ6ZjNvajJMWEg5blZuVnRKRDNnbmRUc2NtNEVYcWZxeENrN256b0RvNiJ9XSwiYXV0aGVudGljYXRpb24iOlsiZGlkOmVsYXN0b3M6amFjayNrZXkxIiwiZGlkOmVsYXN0b3M6amFjayNrZXkyIl0sInZlcmlmaWFibGVDcmVkZW50aWFsIjpbeyJpZCI6ImRpZDplbGFzdG9zOmphY2sjY3JlZC0xIiwidHlwZSI6WyJCYXNpY1Byb2ZpbGVDcmVkZW50aWFsIiwiU2VsZkNsYWltZWRDcmVkZW50aWFsIl0sImlzc3VlciI6ImRpZDplbGFzdG9zOmphY2siLCJpc3N1YW5jZURhdGUiOiIyMDIxLTAxLTIwVDA3OjI2OjExWiIsImV4cGlyYXRpb25EYXRlIjoiMjAyNi0wMS0xOVQyMzoyNjoxMFoiLCJjcmVkZW50aWFsU3ViamVjdCI6eyJpZCI6ImRpZDplbGFzdG9zOmphY2siLCJuYW1lIjoiamFjayJ9LCJwcm9vZiI6eyJ0eXBlIjoiRUNEU0FzZWNwMjU2cjEiLCJ2ZXJpZmljYXRpb25NZXRob2QiOiJkaWQ6ZWxhc3RvczppalNNM2ZmZlZ6QXRBV000RFN5cGlGQlkybVpTbU43SlB2I3ByaW1hcnkiLCJzaWduYXR1cmUiOiJhN2hWOFNwWlUyeWVJSnhFUTZ1SkpsemM3Sm5YbFZtZHE0TzFLOXZDcUV1ZEs4WDRvM0tQYS11ZXl6bF8takVzQTJ4Sk8yQUNjeFVycUVZRHVERWNwUSJ9fV0sImV4cGlyZXMiOiIyMDI2LTAxLTE5VDIzOjI2OjEwWiIsInByb29mIjpbeyJ0eXBlIjoiRUNEU0FzZWNwMjU2cjEiLCJjcmVhdGVkIjoiMjAyMS0wMS0yMFQwNzoyNjoxMVoiLCJjcmVhdG9yIjoiZGlkOmVsYXN0b3M6aWpTTTNmZmZWekF0QVdNNERTeXBpRkJZMm1aU21ON0pQdiNwcmltYXJ5Iiwic2lnbmF0dXJlVmFsdWUiOiJ3LXdZazB0QVZtNm15ZVlwaGtyZ2l5MUI2Y042aGZiT2xLR1dsZ1g5aW42bEdma1BaUGVld1VZMVNhQXp2RUl3d1cyT3pVMWlmZ2xWbTRHeDBCc2lHQSJ9LHsidHlwZSI6IkVDRFNBc2VjcDI1NnIxIiwiY3JlYXRlZCI6IjIwMjEtMDEtMjBUMDc6MjY6MTFaIiwiY3JlYXRvciI6ImRpZDplbGFzdG9zOmlyMzFjWlpiQlFVRmJwNHBOcE1RQXBrQXlKOWRubzNmckIjcHJpbWFyeSIsInNpZ25hdHVyZVZhbHVlIjoicWU3SE5DclBXTW5IU0RybDh6bEJCNUNVczFRcXkwRWpFZzljZkdmODFaeXFmY25tTjd2YTE3QlNaZzlVLUVFY3NNMC1lUjladHUwWmxZNDZqcUV6MUEifV19",
	"proof":{ 
	    "verificationMethod":"did:elastos:ijSM3fffVzAtAWM4DSypiFBY2mZSmN7JPv#primary",  
	    "signature":"TTRcnw7OvLIINbEqPswmS0govaKTzXwzzjN-te80MalWw0SIrvAMSMUIVE5SLt-O7zoVH-nm-pea3KaJA9dwOA"
     }
}

停用/Deactivate DID

DID所有者或者持有者可以主动停用DID,比如普通DID所有者或者自定义DID持有者不再使用该DID,或者认为DID对应私钥泄漏,都可以选择停用DID。

如果普通DID所有者的私钥遗失,那么他将失去该DID的控制权,无法直接对DID进行任何更新操作,包括停用。若普通DID文档中包含了授权和委托,那么委托的可信第三方可以向该DID对应的地址发起停用交易,用来代替DID持有者停用DID,从而避免DID被恶意使用。自定义DID授权和委托持有者停用DID。

停用DID的规则是:

  • 必须包含一个header属性,其中operation属性值是deactivate,表示停用DID。
  • 必须包含payload属性,值是目标DID主题。
  • 必须包含一个proof属性,内含DID持有者或者委托人的公钥引用和签名,用于证明该操作是DID持有者或者委托人发起。其中:普通DID仅有主公钥和委托者公钥可以发起该交易;自定义DID仅有持有者的主公钥可以发起该交易。

例如:

{
  "header": {
    "specification": "elastos/did/1.0",
    "operation": "deactivate"
  },
  "payload": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN",
  "proof": {
    "verificationMethod": "#recovery-key",
    "signature": "dkODxARE...hMUFRY="
  }
}

读取/验证DID

DID文档存储在ID侧链上,任何ID侧链节点可以读取任意DID主题对应的文档,只需读取DID对应的交易即可。其中需要验证有效的DID交易,有效交易包含:DID持有者发起的对自己的交易,以及DID文档中授权委托的DID持有者使用委托的公钥发起的停用DID交易。

在实际的使用中,一般DID读取和验证是由DID解析器来实现的。

DID解析器

DID解析器是是对DID进行读取和验证的功能组件,其API设计用于接受DID查找请求并执行相应的DID方法以检索权威DID文档。 为了符合W3C规范,亦来云DID解析器的处理过程如下:

  1. 从链上读取和DID主题关联的所有交易,并按照历史顺序依次处理;
  2. 处理过程中将非法交易(可以理解为未授权交易)剔除;
  3. 然后生成最终的DID文档;
  4. 根据DID方法规范验证DID是否有效,无效则产生错误;
  5. 根据请求返回DID文档的相应属性或者服务。

目前的解析器设计依赖于SPV客户端,是一个完全去中心的设计,具有良好的安全性,但同时在DID解析时可能会相对比较耗时。应用开发者可以根据需求,针对自己的应用提供可信的链外DID解析服务,该服务的设计要充分考虑安全设计,避免重放,消息插入,删除,修改,模拟和中间人之类的攻击。

安全考虑

亦来云DID以ID侧链作为DID的去中心存储系统,ID侧链通过亦来云主链与比特币联合挖矿获得的哈希算力作为安全保障,并在此基础上充分考虑DID的自我主权需求。

DID的操作是基于区块链上的交易来完成,以交易的安全来支持DID操作的安全;同时严格限定了DID操作主体,保证DID不会被重放,消息插入,删除,修改,模拟和中间人之类的攻击,从而保证DID的安全。

在上述安全策略的基础上,通过授权和委托机制,实现了DID在持有者将密钥丢失后的异常情况下的DID停用机制,最大程度的保证了DID不被恶意使用。

隐私考虑

隐私和自我主权是DID设计的基础原则,亦来云DID的隐私保护策略遵循了W3C的约定。原则上DID文档不应该携带任何实体信息、或者可以关联到具体实体的关键信息。实体的个人信息凭证一般都是由实体或者个人在终端设备上管理和存储,由自己全权掌控,然后通过可验证声明的形式提供给验证方;但有些应用、场景、实体需要公开实体信息,为了便于类似需求,亦来云DID中增加了可选的内嵌可验证凭证属性,由DID主题的持有实体自主决定是否使用。这样的也体现了DID的自我主权精神,同时也符合GDPR的要求。

示例

一个最简单的普通DID文档

{
  "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN",
  "publicKey": [{
    "id": "#key",
    "publicKeyBase58": "zNxoZaZLdackZQNMas7sCkPRHZsJ3BtdjEvM2y5gNvKJ"
  }],
  "authentication": ["#key"],
  "proof": { 
     "type": "ECDSAsecp256r1",
     "created": "2020-01-01T19:23:24Z",
     "creator": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#key",
     "signatureValue": "QNB13Y7Q9...1tzjn4w" 
   }
}

该DID文档中默认有一个主公钥,即和DID主题对应的公钥;其它DID默认属性如下:

  • 公钥#keytypeECDSAsecp256r1
  • 公钥#keycontroller是目标DID主题did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN持有者。
  • 公钥#key可以用于认证DID主题持有者身份。
  • 有效期为5年。

一个复杂/冗长的普通DID文档

{
  "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN",

  "publicKey": [{
    "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#primary",
    "type": "ECDSAsecp256r1",
    "controller": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN",
    "publicKeyBase58": "zNxoZaZLdackZQNMas7sCkPRHZsJ3BtdjEvM2y5gNvKJ"
  }, {
    "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#key2",
    "type": "ECDSAsecp256r1",
    "controller": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN",
    "publicKeyBase58": "273j8fQ1ZZVM6U6d5XE3X8SyULuJwjyYXbxNopXVuftBe"
  }, {
    "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#recovery",
    "type": "ECDSAsecp256r1",
    "controller": "did:elastos:ip7ntDo2metGnU8wGP4FnyKCUdbHm4BPDh",
    "publicKeyBase58": "zppy33i2r3uC1LT3RFcLqJJPFpYuZPDuKMeKZ5TdAskM"
  }],

  "authentication": [
    "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#default",
    "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#key2",
    {
      "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#keys3",
      "type": "ECDSAsecp256r1",
      "controller": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN",
      "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
    }
  ],

  "authorization": [
    "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#recovery"
  ],

  "credential": [{
    // specify the identifier for the credential
    "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#crdential-1",
    // the credential types, which declare what data to expect in the credential
    "type": ["SelfProclaimedCredential", "BasicProfileCredential"],
    // when the credential was issued
    "issuanceDate": "2019-01-01T19:20:18Z",
    "credentialSubject": {
      // assertion about the subject of the credential
      "nickname": "woohah",
      "nation": "Singapore",
      "language": "English"
    },
    "proof": {
      // the cryptographic signature suite that was used to generate the signature
      "type": "ECDSAsecp256r1",
      // the public key identifier that created the signature
      "created": "2019-01-01T19:20:18Z",
      "verificationMethod": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#master-key",
      "signature": "pYw8XNi1..Cky6Ed="
    }
  }, {
    // specify the identifier for the credential
    "id": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#crdential-2",
    // the credential types, which declare what data to expect in the credential
    "type": ["ElastosIDteriaCredential", "InternetAccountCredential"],
    // the entity that issued the credential
    "issuer": "did:elastos:iY3PF8u1bYMujq6Z4bk2iAnmRFyD1cqbSw",
    // when the credential was issued
    "issuanceDate": "2019-01-01T19:20:18Z",
    // when the credential will expire
    "expirationDate": "2020-01-01T19:23:24Z",
    // claims about the subject of the credential
    "credentialSubject": {
      "email": "[email protected]",
      "phone": "+16693553638",
      "googleAccount": "[email protected]",
      "twitter": "@woohah"
    },
    // digital proof that makes the credential tamper-evident
    "proof": {
      // the cryptographic signature suite that was used to generate the signature
      "type": "ECDSAsecp256r1",
      // the public key identifier that created the signature
      "created": "2019-01-01T19:20:18Z",
      "verificationMethod": "did:elastos:iY3PF8u1bYMujq6Z4bk2iAnmRFyD1cqbSw#sign-key",
      // the digital signature value
      "signature": "BavEll0...W3JT24="
    }
  }],
  "service": [{
    "id": "#openid",
    "type": "OpenIdConnectVersion1.0Service",
    "serviceEndpoint": "https://openid.example.com/"
  }, {
    "id": "#vcr",
    "type": "CredentialRepositoryService",
    "serviceEndpoint": "https://did.elastos.org/credential"
  }, {
    "id": "#carrier",
    "type": "CarrierAddress",
    "serviceEndpoint": "carrier://X2tDd1ZTErwnHNot8pTdhp7C7Y9FxMPGD8ppiasUT4UsHH2BpF1d"
  }],

  "expires": "2020-02-10T17:00:00Z",
  "proof": { 
     "type": "ECDSAsecp256r1",
     "created": "2020-01-01T19:23:24Z",
     "creator": "did:elastos:icJ4z2DULrHEzYSvjKNJpKyhqFDxvYV7pN#primary",
     "signatureValue": "QNB13Y7Q9...1tzjn4w" 
   }
}

一个最简单的自定义DID文档

{
  "id": "did:elastos:example",
  "controller": "did:elastos:iWFAUYhTa35c1fPe3iCJvihZHx6quumnym",
  "expires": "2025-10-12T05:50:59Z",
  "proof": {
    "type": "ECDSAsecp256r1",
    "created": "2020-10-12T05:50:59Z",
    "creator": "did:elastos:iWFAUYhTa35c1fPe3iCJvihZHx6quumnym#primary",
    "signatureValue": "2xiR4877Zq-0pLJ1U5v81vB6vsj-61YVcbFahEs-8Xy7V0-i--3hGagloJLtePYIUAdOcqZfwRQSSbh88eeJfA"
  }
}

一个复杂的自定义DID文档

{
    "id": "did:elastos:littlefish",
    "controller": [
        "did:elastos:iWFAUYhTa35c1fPe3iCJvihZHx6quumnym",
        "did:elastos:ijSM3fffVzAtAWM4DSypiFBY2mZSmN7JPv",
        "did:elastos:ir31cZZbBQUFbp4pNpMQApkAyJ9dno3frB"
    ],
    "multisig": "2:3",
    "publicKey": [
        {
            "id": "did:elastos:littlefish#k1",
            "type": "ECDSAsecp256r1",
            "controller": "did:elastos:littlefish",
            "publicKeyBase58": "2A8BJmhntxq2sq4Vn97nQNUqGZ8vs3BaKcY49c9Ntz6HU"
        },
        {
            "id": "did:elastos:littlefish#k2",
            "type": "ECDSAsecp256r1",
            "controller": "did:elastos:littlefish",
            "publicKeyBase58": "ysCadrpAziAZYGKaSAem5dtUgLKeGfRRRzuZmM6hupKo"
        }
    ],
    "authentication": [
        "did:elastos:littlefish#k2"
    ],
    "verifiableCredential": [
        {
            "id": "did:elastos:littlefish#vc-1",
            "type": [
                "BasicProfileCredential",
                "SelfProclaimedCredential"
            ],
            "issuer": "did:elastos:littlefish",
            "issuanceDate": "2020-12-10T07:13:57Z",
            "expirationDate": "2025-12-09T23:13:57Z",
            "credentialSubject": {
                "id": "did:elastos:littlefish",
                "nation": "Singapore",
                "passport": "S653258Z07"
            },
            "proof": {
                "type": "ECDSAsecp256r1",
                "created": "2020-12-10T07:13:57Z",
                "verificationMethod": "did:elastos:iWFAUYhTa35c1fPe3iCJvihZHx6quumnym#primary",
                "signature": "_nSR6HkkmFnHTe2kOb2atk_EMLX424Js5ZKX5quTeV4M-EcXPiEXHtisSgXhGF6_7pBRVOGGDl-WL8pIICNRBA"
            }
        }
    ],
    "service": [
        {
            "id": "did:elastos:littlefish#test-svc-1",
            "type": "Service.Testing",
            "serviceEndpoint": "https://www.elastos.org/testing1"
        },
        {
            "id": "did:elastos:littlefish#test-svc-2",
            "type": "Service.Testing",
            "serviceEndpoint": "https://www.elastos.org/testing2"
        }
    ],
    "expires": "2025-12-09T23:13:57Z",
    "proof": [
        {
            "type": "ECDSAsecp256r1",
            "created": "2020-12-10T07:13:57Z",
            "creator": "did:elastos:ijSM3fffVzAtAWM4DSypiFBY2mZSmN7JPv#primary",
            "signatureValue": "d9loBxvR_Zpt-TgAJSquCQjXSi36m4YMw1tuIdrYmNSj4XkTw4u1e0MlyrqphXFQ1psYSGPQ_qr970882BBMzw"
        },
        {
            "type": "ECDSAsecp256r1",
            "created": "2020-12-10T07:13:57Z",
            "creator": "did:elastos:ir31cZZbBQUFbp4pNpMQApkAyJ9dno3frB#primary",
            "signatureValue": "hSa0apINKgyuh49wZ2dnr-h5zwBGlevY8IUHyIWP-BIkZuBKkQqQIOBJc5Ef4lvs1DMjy3GS8QLqFsx1m2k2mQ"
        }
    ]
}