去中心化标识符(DID)是一种用于可验证的“自我主权”数字身份的新型标识符。DID完全由DID控制者控制,独立于任何中心化注册机构、身份提供者或证书颁发机构。DID解析为DID文档——描述如何使用该特定DID的简单文档。
本文档规定了解析DID和解引用DID URL的算法和指南。
欢迎对本文档提出意见。请直接在 GitHub 上提交问题, 或发送至 public-did-wg@w3.org (订阅, 存档)。
本规范的部分工作由美国国土安全部科学技术局资助,合同号为 HSHQDC-17-C-00019。本规范的内容不一定反映美国政府的立场或政策,也不应推断为官方认可。
本规范的工作也得到了由 Christopher Allen、Shannon Appelcline、Kiara Robles、Brian Weller、Betty Dhamers、Kaliya Young、Kim Hamilton Duffy、Manu Sporny、Drummond Reed、Joe Andrieu 和 Heather Vescent 主持的“重启 Web 信任”社区的支持。
DID解析是获取给定 DID 的 DID文档的过程。这是可以对任何DID执行的四个必需操作之一(“读取”;其他操作包括“创建”、“更新”和“停用”)。这些操作的细节因 DID方法而异。 在 DID解析的基础上,DID URL解引用是获取给定 DID URL 的资源的表示的过程。能够执行这些过程的软件和/或硬件称为 DID解析器。
本规范定义了 DID解析和 DID URL解引用过程的通用要求、算法(包括其输入和结果)、架构选项和各种注意事项。
请注意,虽然本规范定义了DID解析的一些基本功能,但与DID的 可验证数据注册表通信所需的实际步骤由适用的 DID方法规范定义。
“解析” DID 和“解引用” DID URL 之间的区别正在被社区深入讨论。例如,参见 此评论。
本规范有三个主要受众:符合规范的DID方法的实现者;符合规范的DID解析器的实现者;以及希望使用DID解析器解析DID的系统和服务实现者。目标受众包括但不限于软件架构师、数据建模师、应用程序开发人员、服务开发人员、测试人员、操作人员和用户体验(UX)专家。参与与去中心化身份、可验证凭证和安全存储相关的广泛标准工作的其他人也可能对本规范感兴趣。
DID URL 语法支持一种简单的参数格式 (参见 [[DID-CORE]] 中的 查询 部分)。向 DID URL 添加DID参数意味着该参数成为 资源 标识符的一部分。
did:example:123?versionTime=2021-05-10T17:00:00Z
did:example:123?service=files&relativeRef=/resume.pdf
一些DID参数完全独立于任何特定的 DID方法,并且对所有 DID 的功能相同。其他DID参数并非所有 DID方法 都支持。在支持可选参数的情况下,期望这些参数在支持它们的 DID方法 中统一操作。下表提供了在所有 DID方法 中功能相同的常见DID参数。支持所有 DID参数 是可选的。
参数名称 | 描述 |
---|---|
service
|
通过服务 ID 从 DID文档 中识别服务。 如果存在,关联的值必须是一个 ASCII 字符串。 |
relativeRef
|
根据 RFC3986 第 4.2 节 的相对 URI 引用,它标识了 服务端点 上的 资源,该服务端点通过使用 service 参数从 DID文档 中选择。
如果存在,关联的值必须是一个 ASCII 字符串,并且必须使用 RFC3986 第 2.1 节 中指定的百分号编码。
|
versionId
|
标识要解析的 DID文档 的特定版本(版本 ID 可以是顺序的、UUID或方法特定的)。 如果存在,关联的值必须是一个 ASCII 字符串。 |
versionTime
|
标识要解析的 DID文档 的特定版本时间戳。即,在指定的 `versionTime` 之前对 DID 有效的 DID文档 的最新版本。如果存在,关联的值必须是一个 ASCII 字符串,它是有效的 XML 日期时间值,如 W3C XML Schema 定义语言 (XSD) 1.1 第 2 部分:数据类型 [[XMLSCHEMA11-2]] 第 3.3.7 节中所定义。此日期时间值必须规范化为 UTC 00:00:00,并且不包含亚秒级小数精度。
例如:2020-12-20T19:17:47Z 。
|
hl
|
DID文档 的资源哈希,用于添加完整性保护,如 [[?HASHLINK]] 中所指定。此参数是非规范性的。 如果存在,关联的值必须是一个 ASCII 字符串。 |
实现者以及 DID方法 规范作者可能会使用此处未列出的其他DID参数。为了最大程度的互操作性,建议DID参数使用DID规范注册机制 [[?DID-SPEC-REGISTRIES]],以避免与具有不同语义的相同DID参数的其他用途发生冲突。
如果存在明确的用例,其中参数需要成为 URL 的一部分以更精确地引用 资源,则可以使用DID参数。如果相同的功能可以通过将输入元数据传递给 DID解析器 来表达,则预计不会使用DID参数。
DID解析 和 DID URL解引用 功能可以通过传递 或 给 DID解析器 来影响,这些选项不是 DID URL 的一部分。这与 HTTP 类似,某些参数可以包含在 HTTP URL 中,或者作为 HTTP 头在解引用过程中传递。重要的区别在于,作为 DID URL 一部分的DID参数应该用于指定 正在识别的 资源,而不作为 DID URL 一部分的输入元数据应该用于控制 如何解析或解引用该 资源。
DID解析 功能通过使用适用的 DID方法 的“读取”操作将 DID 解析为 DID文档,如 方法操作 中所述。所有符合规范的 DID解析器 都实现了以下函数,其抽象形式如下:
resolve(did, resolutionOptions) → «DIDResolutionMetadata,DIDDocument,DIDDocumentMetadata »
所有符合规范的 DID解析器 必须为至少一种 DID方法 实现 DID解析 功能,并且必须能够返回至少一种符合规范的 表示 的 DID文档。
符合规范的 DID解析器 实现不会以任何方式更改此函数的签名。DID解析器 实现可能会将 resolve
函数映射到方法特定的内部函数以执行实际的 DID解析 过程。DID解析器 实现可能会实现并暴露具有不同签名的其他函数,除了此处指定的 resolve
函数。
resolve
函数的输入变量如下:
此函数返回多个值,并且对这些值如何一起返回没有限制。resolve
的返回值包括 didResolutionMetadata、didDocument 和 didDocumentMetadata。这些值描述如下:
resolve
函数的调用之间变化,因为它表示解析过程本身的数据。此结构是必需的,并且在解析过程中出现错误时,此结构不能为空。此元数据由 定义。如果解析不成功,此结构必须包含一个描述错误的 error
属性。
id
值必须与解析的 DID 匹配。如果解析不成功,此值必须为空。
didDocument
属性中包含的 DID文档 的元数据。此元数据通常在 resolve
函数的调用之间不会变化,除非 DID文档 发生变化,因为它表示 DID文档 的元数据。如果解析不成功,此输出必须是一个空的 元数据结构。此规范定义的属性在 中。
此结构中的可能属性及其可能值在DID规范注册表 [[?DID-SPEC-REGISTRIES]] 中注册。本规范定义了以下常见属性。
didDocument
的 表示,如果支持并可用此类 表示。此属性是可选的。
此结构中的可能属性及其可能值在DID规范注册表 [[?DID-SPEC-REGISTRIES]] 中注册。本规范定义了以下DID解析元数据属性:
didDocument
的媒体类型。此属性是可选的。如果存在,此属性的值必须是一个 ASCII 字符串,它是符合规范的 表示 的媒体类型。在这种情况下,resolve
函数的调用者必须使用此值来确定如何解析和处理 didDocument
。
accept
输入元数据属性请求的 表示 不受 DID方法 和/或 DID解析器 实现支持,则返回此错误代码。
此结构中的可能属性及其可能值应在DID规范注册表 [[?DID-SPEC-REGISTRIES]] 中注册。本规范定义了以下常见属性。
created
属性,以指示 创建操作 的时间戳。属性的值必须是一个 字符串,格式化为 XML 日期时间,规范化为 UTC 00:00:00,并且不包含亚秒级小数精度。例如:2020-12-20T19:17:47Z
。
updated
属性,以指示解析的文档版本的最后一次 更新操作 的时间戳。属性的值必须遵循与 created
属性相同的格式化规则。如果从未对 DID文档 执行过更新操作,则省略 updated
属性。如果存在 updated
属性,它可以与 created
属性具有相同的值,当两个时间戳之间的差异小于一秒时。
true
。如果DID未被停用,此属性是可选的,但如果包含,则必须具有布尔值 false
。
nextUpdate
属性,指示下一次 更新操作 的时间戳。属性的值必须遵循与 created
属性相同的格式化规则。
versionId
属性,以指示解析的文档版本的最后一次 更新操作 的版本。属性的值必须是一个 ASCII 字符串。
nextVersionId
属性,指示下一次 更新操作 的版本。属性的值必须是一个 ASCII 字符串。
一个 DID方法 可以定义不同形式的 DID,这些形式在逻辑上是等价的。例如,一个 DID 在注册到 可验证数据注册表 之前可能采用一种形式,而在注册后采用另一种形式。在这种情况下,DID方法 规范可能需要将解析的 DID 的一个或多个逻辑等价的 DID 作为 DID文档 的属性表达出来。这就是 equivalentId
属性的目的。
DID文档 元数据可以包含一个 equivalentId
属性。如果存在,值必须是一个 集合,其中每个项目是一个 字符串,符合 中的规则。关系是每个 equivalentId
值在逻辑上等同于 id
属性值,因此指的是相同的 DID主体。每个 equivalentId
DID值必须由与 id
属性值相同的 DID方法 生成,并且是该 DID方法 的一种形式。(例如,did:example:abc
== did:example:ABC
)
一个符合规范的 DID方法 规范必须保证每个 equivalentId
值在逻辑上等同于 id
属性值。
请求方应保留 id
和 equivalentId
属性的值,以确保与它们包含的任何值的后续交互都被正确处理为逻辑等价(例如,在数据库中保留所有变体,以便与任何一个交互都映射到相同的底层账户)。
equivalentId
是一种比 alsoKnownAs
更强的等价形式,因为等价性必须由治理的 DID方法 保证。equivalentId
表示一个完整的图合并,因为相同的 DID文档 描述了 equivalentId
DID 和 id
属性 DID。
如果请求方不保留 id
和 equivalentId
属性的值,并确保与它们包含的任何值的后续交互都被正确处理为逻辑等价,可能会出现负面或意外的问题。强烈建议实现者遵守与此元数据属性相关的指示。
canonicalId
属性与 equivalentId
属性相同,除了:a) 它与单个值而不是集合相关联,b) DID 被定义为包含 DID文档 范围内的 DID主体 的规范 ID。
DID文档 元数据可以包含一个 canonicalId
属性。如果存在,值必须是一个 字符串,符合 中的规则。关系是 canonicalId
值在逻辑上等同于 id
属性值,并且 canonicalId
值由 DID方法 定义为包含 DID文档 范围内的 DID主体 的规范 ID。一个 canonicalId
值必须由与 id
属性值相同的 DID方法 生成,并且是该 DID方法 的一种形式。(例如,did:example:abc
== did:example:ABC
)。
一个符合规范的 DID方法 规范必须保证 canonicalId
值在逻辑上等同于 id
属性值。
请求方应使用 canonicalId
值作为其 DID主体 的主要 ID 值,并将所有其他等价值视为次要别名(例如,更新其系统中的相应主要引用以反映新的规范 ID 指示)。
canonicalId
是与 equivalentId
相同的等价性声明,除了它被约束为单个值,该值被定义为包含 DID文档 范围内的 DID主体 的规范。与 equivalentId
一样,canonicalId
表示一个完整的图合并,因为相同的 DID文档 描述了 canonicalId
DID和 id
属性 DID。
如果解析方不使用 canonicalId
值作为其 DID主体 的主要 ID 值,并将所有其他等价值视为次要别名,可能会出现与用户体验相关的负面或意外问题。强烈建议实现者遵守与此元数据属性相关的指示。
以下 DID解析 算法必须由符合规范的 DID解析器 实现。
«[ "error" → "invalidDid", ... ]»
null
«[ ]»
«[ "error" → "methodNotSupported", ... ]»
null
«[ ]»
«[ "error" → "notFound", ... ]»
null
«[ ]»
«[ ... ]»
null
«[ "deactivated" → true, ... ]»
true
的 expandRelativeUrls
选项:
«[ ... ]»
«[ "contentType" →
输出DID文档媒体类型, ... ]»
关于如何处理已被 停用 的DID的讨论正在进行中。
指定在DID解析过程中如何验证DID文档上的签名/证明。
我们是否应该定义功能,使客户端能够发现 DID解析器 支持的 DID方法 列表或其他功能?或者这是实现特定的,超出本规范的范围?例如,参见 这里 和 这里。
DID URL解引用 功能将 DID URL 解引用为 资源,其内容取决于 DID URL 的组件,包括 DID方法、方法特定的标识符、路径、查询和片段。此过程依赖于 DID解析 包含在 DID URL 中的 DID。DID URL解引用 可能涉及多个步骤(例如,当被解引用的DID URL包含片段时),并且该函数定义为在所有步骤完成后返回最终资源。下图描述了上述关系。
图的左上部分包含一个黑色轮廓的矩形,标记为 "DID"。
图的左下部分包含一个黑色轮廓的矩形,标记为 "DID URL"。 此矩形包含四个较小的黑色轮廓矩形,水平排列相邻。这些较小的矩形分别标记为 "DID"、"路径"、"查询" 和 "片段"。
图的右上部分包含一个黑色轮廓的矩形,标记为 "DID文档"。 此矩形包含三个较小的黑色轮廓矩形。这些较小的矩形分别标记为 "id"、"(属性 X)" 和 "(属性 Y)",并被多个省略号(...)包围。一个弯曲的黑色箭头,标记为 "DID文档 - 相对片段解引用",从标记为 "(属性 X)" 的矩形延伸到标记为 "(属性 Y)" 的矩形。
图的右下部分包含一个黑色轮廓的椭圆形,标记为 "资源"。
一个黑色箭头,标记为 "解析为DID文档",从图的左上部分标记为 "DID" 的矩形指向图的右上部分标记为 "DID文档" 的矩形。
一个黑色箭头,标记为 "引用",从图的右上部分标记为 "DID文档" 的矩形指向图的右下部分标记为 "资源" 的椭圆形。
一个黑色箭头,标记为 "包含",从图的左下部分标记为 "DID" 的小矩形指向图的左上部分标记为 "DID" 的矩形。
一个黑色箭头,标记为 "解引用为DID文档",从图的左下部分标记为 "DID URL" 的矩形指向图的右上部分标记为 "DID文档" 的矩形。
一个黑色箭头,标记为 "解引用为资源",从图的左下部分标记为 "DID URL" 的矩形指向图的右下部分标记为 "资源" 的椭圆形。
所有符合规范的 DID解析器 都实现了以下函数,其抽象形式如下:
dereference(DID URL, dereferenceOptions) → « dereferencingMetadata, contentStream, contentMetadata »
dereference
函数的输入变量如下:
虽然任何 DID URL
都可以传递给DID URL解引用器,但实现者应参考 以进一步了解 DID URL 如何被解引用的常见模式。
DID URL
本身之外的 dereference
函数的输入选项。此规范定义的属性在 中。此输入是必需的,但结构可能为空。
此函数返回多个值,并且对这些值如何一起返回没有限制。dereference
的返回值包括 dereferencingMetadata
、contentStream
和 contentMetadata
:
error
属性。
dereferencing
函数被调用并成功,这必须包含与 DID URL 对应的 资源。contentStream
可以是 资源,例如可以以符合规范的 表示 之一序列化的 DID文档、验证方法、服务,或任何其他可以通过媒体类型标识并通过解析过程获得的资源格式。如果解引用不成功,此值必须为空。
contentStream
的元数据。如果 contentStream
是 DID文档,这必须是 didDocumentMetadata 结构,如 DID解析 中所述。如果解引用不成功,此输出必须是一个空的 元数据结构。
符合规范的 DID URL解引用 实现不会以任何方式更改这些函数的签名。DID URL解引用 实现可能会将 dereference
函数映射到方法特定的内部函数以执行实际的 DID URL解引用 过程。DID URL解引用 实现可能会实现并暴露具有不同签名的其他函数,除了此处指定的 dereference
函数。
此结构中的可能属性及其可能值应在DID规范注册表 [[?DID-SPEC-REGISTRIES]] 中注册。本规范定义了以下常见的解引用选项属性:
contentStream
的媒体类型。媒体类型必须表示为 ASCII 字符串。DID URL解引用 实现应使用此值来确定返回的 表示 的 contentType
,如果支持并可用此类 表示。
此结构中的可能属性及其可能值已在DID规范注册表 [[?DID-SPEC-REGISTRIES]] 中注册。本规范定义了以下常见属性。
contentStream
的媒体类型应使用此属性表示。媒体类型值必须表示为 ASCII 字符串。
contentStream
。
以下 DID URL解引用 算法必须由符合规范的 DID解析器 实现。根据 [[RFC3986]],它包含以下三个步骤:解析DID;解引用资源;以及解引用片段(仅当 输入 DID URL 包含 DID片段 时):
«[ "error" → "invalidDID URL" ]»
null
«[ ]»
«[ "error" → "notFound", ... ]»
null
«[ ]»
did:example:1234DID URL解引用器 必须返回 解析的 DID文档 和 解析的 ,如下所示:
«[ ... ]»
resolvedDIDdocument
«[ resolvedDIDdocument metadata
]»
hl
:
did:example:1234?hl=zQmWvQxTqbG2Z9HPJgG57jjwR154cKhbtJenbyYTWkjgF3e
TODO: 指定处理 `hl`DID参数的算法。
service
和可选的 relativeRef
DID参数:
did:example:1234?service=files&relativeRef=%2Fmyresume%2Fdoc%3Fversion%3Dlatest
did:example:1234/custom/path?customquery
«[ "error" → "notFound" ]»
null
«[ ]»
除了DID参数 service
之外,是否还可以有一个DID参数 serviceType
来根据服务的类型而不是 ID 选择服务。参见 Dave Longley 的评论 关于 `serviceType`。
如果 输入 DID URL 包含 DID片段,则片段的解引用取决于资源的媒体类型 ([[RFC2046]]),即 的结果。
did:example:1234?service=files&relativeRef=%2Fmyresume%2Fdoc%3Fversion%3Dlatest#intro
application/did
的DID文档表示,则片段根据与 JSON-LD 1.1: application/ld+json 媒体类型 [JSON-LD11] 相关的规则进行处理。
DID片段 的这种使用方式与 [[RFC3986]] 中片段标识符的定义一致。它标识了 主资源(即 DID文档)的一个 子资源。
DID片段 的这种行为类似于在 HTTP URL 中解引用片段时的处理方式,当解引用它返回带有 Location
头的 HTTP 3xx
(重定向)响应时(参见 [[RFC7231]] 的第 7.1.2 节)。
给定以下 输入 DID URL:
did:example:123456789abcdefghi#keys-1
... 以及以下 解析的 DID文档:
{ "@context": "https://www.w3.org/ns/did/v1", "id": "did:example:123456789abcdefghi", "verificationMethod": [{ "id": "did:example:123456789abcdefghi#keys-1", "type": "Ed25519VerificationKey2018", "controller": "did:example:123456789abcdefghi", "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" }], "service": [{ "id": "did:example:123456789abcdefghi#agent", "type": "AgentService", "serviceEndpoint": "https://agent.example.com/8377464" }, { "id": "did:example:123456789abcdefghi#messages", "type": "MessagingService", "serviceEndpoint": "https://example.com/messages/8377464" }] }
{ "@context": "https://www.w3.org/ns/did/v1", "id": "did:example:123456789abcdefghi#keys-1", "type": "Ed25519VerificationKey2018", "controller": "did:example:123456789abcdefghi", "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" }
给定以下 输入 DID URL 和与上述相同的 解析的 DID文档:
did:example:123456789abcdefghi?service=messages&relativeRef=%2Fsome%2Fpath%3Fquery#frag
... 那么 算法的结果是以下 输出 服务端点 URL:
https://example.com/messages/8377464/some/path?query#frag
更改图表和/或示例以使其一致。
在 DID解析、DID URL解引用 和其他DID相关过程中,通常涉及输入和输出元数据。用于传达此元数据的结构必须是一个 映射 属性。每个属性名称必须是一个 字符串。每个属性值必须是一个 字符串、映射、列表、集合、布尔值 或 null。任何复杂数据结构(如映射和列表)中的值也必须是这些数据类型之一。在DID规范注册表 [[?DID-SPEC-REGISTRIES]] 中注册的所有元数据属性定义必须定义值类型,包括该值的任何其他格式或限制(例如,格式化为日期或十进制整数的字符串)。建议属性定义使用字符串作为值。整个元数据结构必须根据 [[INFRA]] 规范中的 JSON 序列化规则 可序列化。实现可以将元数据结构序列化为其他数据格式。
所有使用元数据结构作为输入或输出的函数的实现都能够以确定性的方式完全表示此处描述的所有数据类型。由于使用元数据结构的输入和输出是根据数据类型而不是其序列化定义的,因此 表示 的方法是函数实现内部的,不在本规范的范围内。
以下示例演示了可能用作 DID解析输入元数据 的 JSON 编码元数据结构。
{ "accept": "application/did+ld+json" }
此示例对应于以下格式的元数据结构:
«[ "accept" → "application/did+ld+json" ]»
下一个示例演示了可能用作 DID解析元数据 的 JSON 编码元数据结构,如果未找到 DID。
{ "error": "notFound" }
此示例对应于以下格式的元数据结构:
«[ "error" → "notFound" ]»
下一个示例演示了可能用作 DID文档元数据 的 JSON 编码元数据结构,用于描述与 DID文档 关联的时间戳。
{ "created": "2019-03-23T06:35:22Z", "updated": "2023-08-10T13:40:06Z" }
此示例对应于以下格式的元数据结构:
«[ "created" → "2019-03-23T06:35:22Z", "updated" → "2023-08-10T13:40:06Z" ]»
TODO: 描述 DID解析器 如何实现和使用,描述 DID方法 的相关性。解释“方法架构”和“解析器架构”之间的区别。
DID解析 算法涉及根据其 DID方法 对 DID 执行 读取 操作(参见 )。
“读取”操作的机制在 DID方法 之间可能有很大差异。特别是,不应假设:
例如,提到“解析”对等/离链/微链/边缘链DID的含义(例如,参见 [[DID-PEER]] 和 这里)。
例如,提到“解析”仅仅是包装的公钥的DID的含义(例如,参见 [[DID-KEY]] 和 这里)。
根据 DID方法 的“读取”操作的确切性质,DID解析器 与 可验证数据注册表 之间的交互可以实现为 可验证读 或 不可验证读:
可验证读 最大限度地提高了对“读取”操作结果的完整性和正确性的信心——在适用的 DID方法 下尽可能做到这一点。它可以通过多种方式实现,例如:
不可验证读没有这样的保证,因此不太理想,例如:
是否可以进行可验证读不仅取决于DID方法本身,还取决于DID解析器的实现方式。DID方法可以定义多种不同的“读取”操作实现方式,并且应该至少提供一种实现可验证读的指导。
可验证读的保证仍然始终受到底层可验证数据注册表的架构、协议、加密和其他方面的限制。最强的可验证读实现形式被认为是不需要与远程网络进行任何交互的形式(例如,参见[[DID-KEY]]),或者将依赖特定网络基础设施的需求降到最低,并将“信任根”仅归结为经过验证的熵和加密(例如,参见[[KERI]])。
TODO: 描述客户端如何在不信任DID解析器的情况下独立验证“读取”操作的结果(例如,使用状态证明)。
一个DID解析器必须支持至少一种DID方法的DID解析算法,并且可以支持多种DID方法:
DID解析和DID URL解引用的算法被定义为抽象函数(参见和)。
这些算法由DID解析器实现。客户端通过绑定调用DID解析器。绑定定义了如何使用具体的编程或通信接口实现这些抽象函数。可以区分本地绑定(例如本地命令行工具或库API)和远程绑定(例如HTTP(S)绑定)。TODO: 讨论在受限用户代理(如移动应用和浏览器)中的DID解析。
一个DID解析器可以调用另一个DID解析器,后者作为代理执行DID解析算法,如中定义。
第一个DID解析器然后充当客户端,并选择适当的绑定来调用第二个DID解析器。例如,一个DID解析器可以通过本地绑定(例如命令行工具)调用,而后者又通过远程绑定(例如HTTP(S)绑定)调用另一个DID解析器。
这类似于DNS架构中的“存根解析器”调用“递归解析器”,尽管概念并不完全可比(DNS解析使用单一的具体协议,而DID解析是由不同的DID方法和不同的绑定实现的抽象函数)。
DID URL解引用算法的不同部分可以由解析器架构的不同组件执行。
具体来说,当解引用带有DID片段的DID URL时,解引用资源由DID解析器完成,而解引用片段由客户端完成。
示例:给定DID URL did:xyz:1234#keys-1
,可以通过本地绑定调用DID解析器来解引用资源(即DID文档),而客户端可以通过解引用片段(即DID文档的一部分)来完成DID URL解引用算法。
示例:给定DID URL did:xyz:1234#keys-1
,可以通过本地绑定调用DID解析器,后者又通过远程绑定调用另一个DID解析器来解引用资源(即DID文档),而客户端可以通过解引用片段(即DID文档的一部分)来完成DID URL解引用算法。
示例:给定DID URL did:xyz:1234?service=agent&relativeRef=%2Fsome%2Fpath%3Fquery#frag
,可以调用DID解析器来解引用资源(即服务端点 URL),而客户端可以通过解引用片段(即带有片段的服务端点 URL)来完成DID URL解引用算法。
本节定义了一个数据结构,表示中描述的算法的结果。DID解析结果包含DID文档以及DID解析元数据和DID文档元数据。
此数据结构的媒体类型定义为`application/ld+json;profile="https://w3id.org/did-resolution"`。
{ "@context": "https://w3id.org/did-resolution/v1", "didDocument": { "@context": "https://www.w3.org/ns/did/v1", "id": "did:example:123456789abcdefghi", "authentication": [{ "id": "did:example:123456789abcdefghi#keys-1", "type": "Ed25519VerificationKey2018", "controller": "did:example:123456789abcdefghi", "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" }], "service": [{ "id":"did:example:123456789abcdefghi#vcs", "type": "VerifiableCredentialService", "serviceEndpoint": "https://example.com/vc/" }] }, "didResolutionMetadata": { "contentType": "application/did+ld+json", "retrieved": "2024-06-01T19:73:24Z", }, "didDocumentMetadata": { "created": "2019-03-23T06:35:22Z", "updated": "2023-08-10T13:40:06Z", "method": { "nymResponse": { "result": { "data": "{\"dest\":\"WRfXPg8dantKVubE3HX8pw\",\"identifier\":\"V4SGRU86Z58d6TV7PBUe6f\",\"role\":\"0\",\"seqNo\":11,\"txnTime\":1524055264,\"verkey\":\"H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV\"}", "type": "105", "txnTime": 1.524055264E9, "seqNo": 11.0, "reqId": 1.52725687080231475E18, "identifier": "HixkhyA4dXGz9yxmLQC4PU", "dest": "WRfXPg8dantKVubE3HX8pw" }, "op": "REPLY" }, "attrResponse": { "result": { "identifier": "HixkhyA4dXGz9yxmLQC4PU", "seqNo": 12.0, "raw": "endpoint", "dest": "WRfXPg8dantKVubE3HX8pw", "data": "{\"endpoint\":{\"xdi\":\"http://127.0.0.1:8080/xdi\"}}", "txnTime": 1.524055265E9, "type": "104", "reqId": 1.52725687092557056E18 }, "op": "REPLY" } } } }
参见相应的开放问题。
需要定义此数据结构的确切工作方式,以及它是否始终包含DID文档,或者也可以包含其他结果。
这是一个元数据结构(参见[[DID-CORE]]中的元数据结构部分),包含有关DID解析过程的元数据。
此元数据通常在DID解析函数的调用之间变化,因为它表示解析过程本身的数据。
此元数据的来源是DID解析器。
DID解析元数据的示例包括:
另请参见[[DID-CORE]]中的DID解析元数据部分。
这是一个元数据结构(参见[[DID-CORE]]中的元数据结构部分),包含有关DID文档的元数据。
此元数据通常在DID解析函数的调用之间不会变化,除非DID文档发生变化,因为它表示有关DID文档的数据。
DID文档元数据的示例包括:
DID文档元数据还可以包括方法特定的元数据,例如:
另请参见[[DID-CORE]]中的DID文档元数据部分。
对于某些数据,可能存在争议,它是否应该属于DID文档(即描述DID主体的数据),或者它是否是元数据(即关于DID文档或DID解析过程的数据)。例如BTCR方法中的“延续DID文档”的URL。
本节定义了一个数据结构,用于表示在中描述的算法的结果。DID URL解引用结果包含任意内容以及 DID解析元数据和内容元数据。
参见相关的开放问题。
此数据结构的媒体类型定义为`application/ld+json;profile="https://w3id.org/did-resolution"`。
{ "@context": "https://w3id.org/did-resolution/v1", "content": { "@context": "https://www.w3.org/ns/did/v1", "id": "did:example:123456789abcdefghi", "authentication": [{ "id": "did:example:123456789abcdefghi#keys-1", "type": "Ed25519VerificationKey2018", "controller": "did:example:123456789abcdefghi", "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" }], "service": [{ "id":"did:example:123456789abcdefghi#vcs", "type": "VerifiableCredentialService", "serviceEndpoint": "https://example.com/vc/" }] }, "DID URLDereferencingMetadata": { "contentType": "application/did+ld+json", "retrieved": "2024-06-01T19:73:24Z", }, "contentMetadata": { "created": "2019-03-23T06:35:22Z", "updated": "2023-08-10T13:40:06Z", "method": { "nymResponse": { "result": { "data": "{\"dest\":\"WRfXPg8dantKVubE3HX8pw\",\"identifier\":\"V4SGRU86Z58d6TV7PBUe6f\",\"role\":\"0\",\"seqNo\":11,\"txnTime\":1524055264,\"verkey\":\"H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV\"}", "type": "105", "txnTime": 1.524055264E9, "seqNo": 11.0, "reqId": 1.52725687080231475E18, "identifier": "HixkhyA4dXGz9yxmLQC4PU", "dest": "WRfXPg8dantKVubE3HX8pw" }, "op": "REPLY" }, "attrResponse": { "result": { "identifier": "HixkhyA4dXGz9yxmLQC4PU", "seqNo": 12.0, "raw": "endpoint", "dest": "WRfXPg8dantKVubE3HX8pw", "data": "{\"endpoint\":{\"xdi\":\"http://127.0.0.1:8080/xdi\"}}", "txnTime": 1.524055265E9, "type": "104", "reqId": 1.52725687092557056E18 }, "op": "REPLY" } } } }
与DID URL关联的任意内容。的结果。
这是一个元数据结构(参见[[DID-CORE]]中的元数据结构部分),包含有关DID URL解引用过程的元数据。
此元数据通常在DID URL解引用函数的调用之间发生变化,因为它表示有关解引用过程本身的数据。
添加更多关于DID URL解引用元数据如何工作的细节。
另见[[DID-CORE]]中的DID URL解引用元数据部分。
这是一个元数据结构(参见[[DID-CORE]]中的元数据结构部分),包含有关内容的元数据。
此元数据通常在DID URL解引用函数的调用之间不会发生变化,除非内容发生变化,因为它表示有关内容的数据。
添加更多关于内容元数据如何工作的细节。
如果在DID解析过程中检测到无效的DID, DID解析元数据error属性的值必须为invalidDid, 如部分所定义。
如果在DID解析或DID URL解引用过程中检测到无效的DID URL, DID解析或DID URL解引用元数据error属性的值必须为invalidDID URL, 如部分所定义。
如果在DID解析或DID URL解引用过程中DID或DID URL不存在, DID解析或DID URL解引用元数据error属性的值必须为notFound, 如和部分所定义。
如果在DID解析或DID URL解引用过程中不支持DID文档的表示形式, DID解析元数据error属性的值必须为representationNotSupported, 如部分所定义。
如果在DID解析或DID URL解引用过程中不支持DID方法, DID解析或DID URL解引用元数据error属性的值必须为methodNotSupported。
当在DID解析或DID URL解引用过程中发生意外错误时, DID解析或DID URL解引用元数据error属性的值必须为internalError。
如果在DID解析或DID URL解引用过程中检测到无效的公钥值, DID解析或DID URL解引用元数据error属性的值必须为invalidPublicKey。
如果在DID解析或DID URL解引用过程中,rawPublicKeyBytes的字节长度与关联的multicodecValue的预期公钥长度不匹配, DID解析或DID URL解引用元数据error属性的值必须为invalidPublicKeyLength。
如果在DID解析或DID URL解引用过程中检测到无效的公钥类型, DID解析或DID URL解引用元数据error属性的值必须为invalidPublicKeyType。
如果在DID解析或DID URL解引用过程中检测到不支持的公钥类型, DID解析或DID URL解引用元数据error属性的值必须为unsupportedPublicKeyType。
本节定义了一个DID解析器的绑定,通过HTTP(S)端点暴露DID解析和/或DID URL解引用功能(包括所有解析/解引用选项和元数据)。参见。
HTTP(S)绑定是一个远程绑定。它需要一个已知的HTTP(S) URL,远程DID解析器可以在该URL上被调用。此URL称为DID解析器 HTTP(S) 端点。
使用此绑定,DID解析功能(参见)和/或DID URL解引用功能(参见)可以按以下方式执行:
https://resolver.example/1.0/identifiers/
https://resolver.example/1.0/identifiers/did:example:1234
Accept
HTTP 请求头设置为`application/ld+json;profile="https://w3id.org/did-resolution"`以请求完整的,或者Accept
HTTP 请求头设置为解析选项中的accept值。https://resolver.example/1.0/identifiers/did%3Aexample%3A1234?option1=value1&option2=value2
https://resolver.example/1.0/identifiers/did:example:1234?service=files&relativeRef=/resume.pdf
Accept
HTTP 请求头设置为`application/ld+json;profile="https://w3id.org/did-url-dereferencing"`以请求完整的,或者Accept
HTTP 请求头设置为解引用选项中的accept值。https://resolver.example/1.0/identifiers/did%3Aexample%3A1234%3Fservice%3Dfiles%26relativeRef%3D%2Fresume.pdf?option1=value1&option2=value2
GET
请求。这将调用远程DID解析器上的DID解析或DID URL解引用功能。错误 | HTTP 状态码 |
---|---|
invalidDid
|
400
|
invalidDID URL
|
400
|
notFound
|
404
|
representationNotSupported
|
406
|
methodNotSupported
|
501
|
internalError
|
500
|
(其他值) |
500
|
true
:
410
。Content-Type
HTTP 响应头的值为`application/ld+json;profile="https://w3id.org/did-resolution"`:
200
。Content-Type
HTTP 响应头。其值必须为didResolutionMetadata中的contentType元数据属性的值(参见)。Content-Type
HTTP 响应头。Content-Type
HTTP 响应头的值为`application/ld+json;profile="https://w3id.org/did-url-dereferencing"`:
text/uri-list
:
303
。Location
头。该头的值必须为输出 服务端点 URL。200
。Content-Type
HTTP 响应头。其值必须为dereferencingMetadata中的contentType元数据属性的值(参见)。Content-Type
HTTP 响应头。参见此处的OpenAPI定义。
给定以下DID解析器 HTTP(S) 端点:
https://resolver.example/1.0/identifiers/
以及以下输入 DID:
did:sov:WRfXPg8dantKVubE3HX8pw
则请求HTTP(S) URL为:
https://resolver.example/1.0/identifiers/did:sov:WRfXPg8dantKVubE3HX8pw
可以通过以下方式调用HTTP(S)绑定:
curl -X GET https://resolver.example/1.0/identifiers/did:sov:WRfXPg8dantKVubE3HX8pw
HTTP(S)绑定的其他示例:
HTTP(S)绑定的其他示例:
本节定义了服务端点构建的输入和算法,该算法返回一个服务端点 URL作为输出。此算法在DID URL解引用过程中选择服务端点时使用(参见)。
在本节中,path
、query
和fragment
的定义遵循[[RFC3986]]。
服务端点构建算法的输入是一个输入 DID URL和一个输入 服务端点 URL。
服务端点构建算法的输入要求如下:
query
组件,则移除该组件fragment
组件,则移除该组件path
组件追加到输出服务端点URL中query
组件,则在输出服务端点URL后追加?
加上query
query
组件,则在输出服务端点URL后追加?
加上query
fragment
组件,则在输出服务端点URL后追加#
加上fragment
fragment
组件,则在输出服务端点URL后追加#
加上fragment
我们可能允许输入DID URL和输入服务端点URL同时包含query
组件,前提是它们都包含可以合并的键/值参数列表。
服务端点构建算法的细节已在2019年4月的CCG邮件列表中讨论过,例如这里或这里。
我们可以考虑复用[[RFC3986]]中定义的“相对解析”算法,而不是定义自己的算法。
参见对应的开放问题。
给定以下输入服务端点URL:
https://example.com/messages/8377464
以及以下输入DID URL:
did:example:123456789abcdefghi?service=messages&relativeRef=%2Fsome%2Fpath%3Fquery#frag
则输出服务端点URL为:
https://example.com/messages/8377464/some/path?query#frag
DID解析和DID URL解引用不涉及任何认证或授权功能。类似于DNS解析,任何人都可以执行此过程,无需任何凭据或非公开知识。
说明DID不一定是全局可解析的,例如成对或N-wise的“对等”DID。
参见[[RFC3339]]: URI具有全局范围,无论上下文如何,其解释都是一致的,尽管解释结果可能与最终用户的上下文相关。
一个高级的想法是,DID解析的结果可能是上下文相关的或依赖于策略,参见此评论。
一个相关主题是DID文档(或部分)是否可以加密,例如w3c/did-core/issues/25。另见IPIDDID方法中片段的使用。
DID解析器可以维护DID文档的通用缓存,也可以维护特定于某些DID方法的缓存。
可以使用noCache
解析选项来请求特定的缓存行为。
此解析选项是可选的。
该属性的可能值包括:
缓存行为可以通过DID解析器的配置、noCache
解析选项或DID文档内容(例如`cacheMaxTtl`字段)或其组合来控制。
参见对应的开放问题。
或许我们可以复用其他协议(如HTTP)的缓存机制。
如果提供了versionId
或
versionTime
DID参数,
则DID解析算法会返回DID文档的特定版本。
DID参数versionId
和versionTime
是互斥的。
versionId
DID参数的使用是特定于DID方法的。
其可能值包括顺序号、随机UUID、内容哈希等。
DID文档元数据可能包含versionId
属性,该属性会随着每次对DID文档执行的更新操作而改变。
虽然大多数DID方法支持更新操作, 但DID方法并不需要保留所有先前的DID文档版本,因此并非所有DID方法都支持版本控制。
参见对应的开放问题。
关于DID解析与非DID标识符(如域名、HTTP URI或电子邮件地址)解析之间关系的讨论正在进行中。这包括如何从非DID标识符中发现DID,以及如何使标识符之间的链接可验证。
描述DID解析器应支持哪些方法,以及潜在的影响。
本节列出了正在讨论中但尚未纳入算法的其他DID URL解引用功能。
服务端点可能具有
一个serviceEndpoint
属性,其值本身是一个DID。这被解释为从输入DID到另一个DID的“DID重定向”。在这种情况下,可以启动一个“子”DID解析过程以到达“最终”服务端点。
客户端可以提供follow-redirect
解析选项作为提示,指示是否应遵循重定向。此解析选项是可选的。
参见对应的开放问题。
DID重定向不仅可以应用于单个服务端点,还可以应用于整个DID文档,从而实现可移植性用例。
{ "id": "did:example:123456789abcdefghi#hub1", "type": "HubService", "serviceEndpoint": "did:example:xyz" }
DID文档可能包含“代理”服务类型,该类型将提供一个需要遵循的映射,以解析到最终的服务URL。
{ "id": "did:example:123456789abcdefghi", "type": "ProxyService", "serviceEndpoint": "https://mydomain.com/proxy" }