去中心化标识符解析(DID Resolution)v0.3

解析 DID 和解引用 DID URL 的算法与指南

W3C 工作草案

关于本文档的更多详细信息
本版本:
https://www.w3.org/TR/2026/WD-did-resolution-20260710/
最新发布版本:
https://www.w3.org/TR/did-resolution/
最新编辑草案:
https://w3c.github.io/did-resolution/
历史:
https://www.w3.org/standards/history/did-resolution/
提交历史
编辑:
Markus Sabadello (Danube Tech), 至 2025-12-10
Dmitri Zagidulin (MIT DCC)
Stephen Curran (Cloud Compass Computing Inc.)
Joe Andrieu (Legendary Requirements)
作者:
Markus Sabadello (Danube Tech)
Dmitri Zagidulin (MIT DCC)
反馈:
GitHub w3c/did-resolution (拉取请求, 新议题, 未关闭议题)
public-did-wg@w3.org 主题行请写为 [did-resolution] … 消息主题 …归档

摘要

去中心化标识符(DID)解析是为特定 DID 获取 DID 文档及随附元数据的过程。该过程以一个 DID 和一组选项作为输入,并返回一个 DID 文档以及 有关已解析文档和解析请求的相关元数据。已解析的 DID 文档 是一组信息,可支持与 DID 主体进行可通过密码学验证的 交互,包括密码学公钥等机制。本规范涵盖 DID 解析所使用的算法和指南,并依赖于核心 DID 规范 去中心化 标识符(DID)v1.0,该规范完整详细地描述了底层 DID 架构。

本文档状态

本节描述本文档在发布时的状态。当前 W3C 出版物列表以及本技术报告的最新修订版可在 W3C 标准和草案 索引中找到。

欢迎就本文档提出意见。请直接在 GitHub 上提交议题,或将 意见发送至 public-did-wg@w3.org订阅归档)。

(存在风险的功能)议题 1

DID URL 解引用功能的定义 当前被标记为 存在风险,并且 很可能会从本规范中更改或移除。 工作组正在征求实现者关于本规范所定义的该功能 价值的反馈。

本规范部分工作的资金由美国国土安全部 科学与技术局根据合同 HSHQDC-17-C-00019 提供。本规范内容 不一定反映美国政府的立场或政策,也不应推断为 得到了官方认可。

本规范的工作还得到了 Rebooting the Web of Trust 社区的支持,该社区由 Christopher Allen、Shannon Appelcline、Kiara Robles、Brian Weller、Betty Dhamers、Kaliya Young、Kim Hamilton Duffy、Manu Sporny、Drummond Reed、Joe Andrieu 和 Heather Vescent 推动。

本文档由 去中心化标识符 工作组发布为 工作草案,并使用 推荐标准 轨道

作为 工作草案发布并不意味着 W3C 及其成员认可该文档。

这是一份草案文档,可能随时被其他文档 更新、替换或废弃。除作为正在进行中的工作外, 不宜引用本文档。

本文档由一个依据 W3C 专利 政策运行的工作组制作。 W3C 维护着一份与该组交付成果相关的 任何专利披露的公开列表; 该页面还包括 披露专利的说明。实际知晓某项专利,且其认为该专利包含 必要权利要求的个人, 必须按照 W3C 专利政策第 6 节披露该信息。

本文档受 2025 年 8 月 18 日 W3C 流程文档管辖。

1. 引言

DID 解析是为给定 DID 获取 DID 文档 的过程。这是可对任何 DID 执行的四项必需 操作之一(“读取”;其他操作为 “创建”、“更新”和“停用”)。这些操作的细节会因 DID 方法而异。在 DID 解析的基础上,DID URL 解引用是为给定 DID URL 检索资源 表示的过程。能够执行这些过程的软件 和/或硬件称为 DID 解析器

本规范定义了一个标准接口,客户端可使用该接口来执行 DID 解析DID URL 解引用请求,而不依赖于 DID 解析器 所支持的任何特定 DID 方法的 “Resolve” 操作。此外,本规范还定义了实现 DID 解析器DID URL 解引用器时相关的要求、 算法(包括其输入和结果)、架构选项,以及 各种安全和隐私考量。

请注意,虽然本规范为 DID 解析定义了一些基础级功能,但与 DID 的 可验证数据 注册表通信所需的实际步骤由适用的 DID 方法规范定义。

1.1 实现者概览

本节为非规范性内容。

通过使用标准 resolve(did, resolutionOptions) 接口(如 DID 解析一节中所定义)调用 DID 解析器,即可获得 DID 文档 以及随附元数据(例如 contentType、证明、版本信息),应用程序 可使用这些信息来验证用户的密码学密钥、服务端点 或状态。

例如,若要检索 DID did:example:123 在过去某个 时间点的状态,客户端应用可以使用 versionTime 解析选项来解析该 DID,如下所示:
resolve("did:example:123", {"versionTime":"2021-05-10T17:00:00Z"}) 或者,客户端可以解引用 诸如 did:example:123?service=files&relativeRef=/resume.pdf 的 DID URL(详细示例见此处), 以获取通过 DID 文档中声明的服务存储的用户简历。

此外,本规范的 DID URL 解引用算法 展示了客户端如何跟随片段(例如 #key-1),从 DID 文档 中提取特定验证方法(详细示例见此处)。 在实践中,实现者会根据 DID Resolution Test Suite 验证其解析器,该测试套件会测试规范性的 MUST 要求和错误条件(例如无效 DID、 已停用 DID、不支持的方法、相对 URL 展开等),以确保 客户端应用能够可靠地依赖不同 DID 方法上的正确解析行为。

1.2 一致性

除标记为非规范性的章节外,本规范中的所有编写指南、图表、示例和注释均为非规范性内容。除此之外,本规范中的所有内容均为规范性内容。

本文档中的关键词 MAYMUSTMUST NOTNOT REQUIREDOPTIONALRECOMMENDEDREQUIREDSHOULD 应按 BCP 14 [RFC2119] [RFC8174] 中的说明解释,且仅当它们如本文所示全部以 大写字母出现时才如此解释。

一致性 DID 解析器是指任何 以软件和/或硬件实现、并符合 4. DID 解析中相关规范性陈述的算法。

一致性基于网络的 DID 解析器 是一种 一致性 DID 解析器,并且还符合 12.1 HTTP(S) 绑定中的 规范性陈述。

一致性 DID URL 解引用器是指 任何以软件和/或硬件实现、并符合 5. DID URL 解引用中相关规范性陈述的算法。

一致性基于网络的 DID URL 解引用器 是一种 一致性 DID URL 解引用器,并且还 符合 12.1 HTTP(S) 绑定中的规范性陈述。

1.3 受众

本节为非规范性内容。

本规范有三类主要受众:一致性 DID 方法的实现者;一致性 DID 解析器的实现者;以及希望使用 DID 解析器 解析 DID 的系统和服务实现者。预期 受众包括但不限于软件架构师、数据建模人员、 应用开发人员、服务开发人员、测试人员、运维人员以及用户 体验(UX)专家。参与去中心化身份、可验证凭证和安全 存储相关广泛标准化工作的其他人员也可能有兴趣阅读本规范。

1.4 用例

本节为非规范性内容。

DID 解析规范旨在通过定义标准化接口来支持广泛的用 例,该接口可独立于任何特定 DID 的 DID 方法来解析 DID 并解引用 DID URL。这些用例 包括:

2. 术语

本节定义了本规范以及整个 去中心化标识符 基础设施中使用的术语。每当这些术语在本规范中出现时, 都会包含指向这些术语的链接。

绑定
客户端调用 DID 解析器的具体机制。这可以是 本地绑定,例如本地命令行工具或库 API;也可以是 远程绑定,例如 HTTP(S) 绑定。参见第 8.2 解析器架构节。
客户端
调用 DID 解析器以执行 DID 解析和/或 DID URL 解引用 算法的软件和/或硬件。此调用通过 绑定完成。术语 客户端并不意味着任何 特定网络拓扑。
DID 解析结果
表示 DID 解析算法结果的数据结构。 可以包含 DID 文档。参见第 9. DID 解析结果节。
DID URL 解引用结果
表示 DID URL 解引用 算法结果的数据结构。 可以包含 DID 文档或其他内容。参见第 10. DID URL 解引用结果节。
资源
如 [RFC3986] 所定义:“……术语 ‘资源’以一般意义使用,指任何可由 URI 标识的事物。”同样,任何资源都可以作为 DID 主体, 并由 DID 标识。
表示
如 [RFC9110] 针对 HTTP 所定义:“旨在反映 给定资源过去、当前或期望状态的信息,其格式可通过协议 方便地传达。表示由一组 表示元数据和一个可能无界的表示 数据流组成。”DID 文档是描述 DID 主体的信息表示。参见 去中心化标识符(DID)v1.0
本地绑定
一种 绑定,其中 客户端调用运行在同一 网络主机上的 DID 解析器,例如通过本地命令行工具或库 API。 在这种情况下,DID 解析器有时也称为“本地 DID 解析器”。 参见第 8.2 解析器 架构节。
远程绑定
一种 绑定,其中 客户端调用运行在 不同网络主机上的 DID 解析器,例如通过 HTTP(S) 绑定。 在这种情况下,DID 解析器有时也称为“远程 DID 解析器”。 参见第 8.2 解析器 架构节。
服务
通过一个或多个 DID 服务端点DID 主体或 相关实体进行通信或交互的手段。 示例包括发现服务、代理服务、社交网络 服务、文件存储服务以及可验证凭证仓库服务。
不可验证解析
DID 方法的 “Resolve” 操作在 DID 解析器可验证数据 注册表之间的一种低置信度实现,用于获取 DID 文档。 对结果的完整性和正确性没有保证。参见第 8.1 方法 架构节。
验证 方法

一组参数,可与某个过程一起使用,以独立 验证证明。例如,密码学公钥可作为 数字签名的验证方法;在这种用法中,它 验证签名者拥有相关联的密码学私钥。

此定义中的“验证”和“证明”旨在作广义理解。例如, 密码学公钥可在 Diffie-Hellman 密钥 交换期间用于协商用于加密的共享对称密钥。这保证了 密钥协商过程的完整性。因此,即使对该过程的描述可能不使用 “验证”或“证明”这些词,它也是另一类验证 方法。

可验证解析
DID 方法的 “Resolve” 操作在 DID 解析器可验证数据 注册表之间的一种高置信度实现,用于获取 DID 文档。 在适用 DID 方法所能达到的范围内, 对结果的完整性和正确性有保证。 参见第 8.1 方法 架构节。
通用唯一标识符 (UUID)
一类由 [RFC4122] 定义的全局唯一标识符。UUID 与 DID 类似,因为它们不需要集中式注册机构。UUID 与 DID 的不同之处在于,它们不可解析,也不可通过密码学验证。
统一资源标识符 (URI)
万维网上所有资源的标准标识符格式,如 [RFC3986] 所定义。DID 是一种 URI 方案。

3. DID 参数

DID URL 语法支持 一种简单的参数格式(见 [DID-CORE] 中的 Query 一节)。向 DID URL 添加 DID 参数,意味着该参数 成为 资源标识符的一部分。

示例 1:带有 'versionTime' DID 参数的 DID URL
did:example:123?versionTime=2021-05-10T17:00:00Z
示例 2:带有 'service' 和 'relativeRef' DID 参数的 DID URL
did:example:123?service=files&relativeRef=/resume.pdf

对于存在的每个 DID 参数,其关联值 MUST 是一个 标量值 字符串,并根据 RFC3987 第 3.1 节序列化为 ASCII。

一些 DID 参数完全独立于任何特定 DID 方法,并且对所有 DID 都以相同方式发挥作用。其他 DID 参数并非由所有 DID 方法支持。在支持 可选参数的地方,预期这些参数会在支持它们的 DID 方法之间 统一运作。下表提供了常见 DID 参数,它们 在所有 DID 方法中以相同方式发挥作用。支持所有 DID 参数OPTIONAL

参数 名称 描述
service 通过服务 ID 标识 DID 文档中的一个 服务
serviceType 通过服务类型标识 服务集合中的一个或多个 服务,这些服务来自 DID 文档
relativeRef 根据 RFC3986 第 4.2 节的相对 URI 引用,它标识 DID 服务端点上的 一个 资源, 该服务端点通过使用 service 参数从 DID 文档中选择。
versionId 标识要解析的 DID 文档 的特定版本(该版本 ID 可以是顺序编号、或 UUID, 或方法特定的)。
versionTime 标识要解析的 DID 文档的某个版本时间戳。也就是说,在指定 versionTime 之前,对某个 DID 有效的 DID 文档的最新 版本。如果存在,关联值 MUST3.1 日期时间 中定义的日期时间格式表示。

实现者以及 DID 方法规范作者 可以使用此处未列出的其他 DID 参数。为实现最大 互操作性,RECOMMENDED DID 参数使用 DID Document Properties Extensions 机制 [DID-EXTENSIONS-PROPERTIES],以避免 与同一 DID 参数在不同语义下的其他用法发生 冲突。

可以通过向 DID 解析器DID URL 解引用器传递 DID 解析选项DID URL 解引用选项,来影响DID 解析DID URL 解引用函数。此类 选项不是DIDDID URL的一部分。这与 HTTP 类似,在 HTTP 中, 某些参数既可以包含在 HTTP URL 中,也可以 在解引用过程中作为 HTTP 标头传递。

3.1 日期时间

本规范中的所有日期时间值 MUST 是一个 ASCII 字符串,且是 [VC-DATA-MODEL] 在 可验证凭证数据模型 v2.0中定义的有效 XML 日期时间值。 此外,DID Resolution 中使用的时间戳 MUST 调整为 UTC,且不得具有亚秒十进制精度。例如: 2020-12-20T19:17:47Z

3.2 查询规范化

DID URL 查询字符串 通常会在解析流水线中的多个独立组件之间被构造、解析、 记录、缓存和比较——例如客户端、缓存代理、下游 解析器以及 DID 方法特定解析器(见 8.2 解析器 架构)。这些组件之间对 DID URL 查询字符串 的规范化不一致,可能会 悄然产生错误的解析结果、缓存污染或破坏 互操作性。本节列举了鼓励实现者和 DID 方法规范作者明确处理的边界情形。

:DID URL 查询 字符串规范化

本节中的指南涉及如何为 解析、比较和转发的目的规范化 DID URL 查询字符串。它不同于 哪些参数应作为解析选项传递、哪些应 嵌入到 DID URL 中这一问题;该问题已在 3. DID 参数末尾关于 DID 参数与解析选项区别的注释中处理。

3.2.1 百分号编码 规范化

本节为非规范性内容。

DID URL 查询 字符串中字符的百分号编码不会改变被标识资源的身份,但 同一逻辑值的不同编码可能会被执行朴素字符串比较的实现 视为不同字符串。

鼓励比较、缓存或转发 DID URL 的实现,在比较或存储之前 规范化百分号编码。以下规则 与 RFC3986 第 6.2.2 节:基于语法的规范化一致, 可作为基线:

  1. 与非保留字符(如 RFC3986 第 2.3 节:非保留 字符中定义)相对应的百分号编码八位组, 可以解码为其字面字符形式。
  2. 所有剩余的百分号编码八位组最好使用大写 十六进制数字表示(例如使用 %2F 而不是 %2f)。
  3. 避免解码作为查询组件内保留分隔符的百分号编码字符 (例如 %26 表示 &%3D 表示 =),因为这样做会 改变查询字符串的已解析结构。

鼓励 DID 方法规范记录其 方法特定 DID 参数中哪些字符可在规范化期间安全解码。

: relativeRef 百分号编码

relativeRef DID 参数值通常会包含百分号编码的 路径分隔符和查询字符(例如 relativeRef=%2Fresume.pdf%3Fversion%3D2)。避免将这些字符作为 查询级规范化的一部分进行解码,因为编码形式是有意的,并且对于 该值在解引用期间被正确解释为相对引用是必要的 (见解引用资源)。

3.2.2 重复参数 处理

DID URL 语法 并不禁止在单个 DID URL 中重复出现 同一个查询参数名(例如 did:example:123?service=files&service=agent)。当存在重复参数时, 解析和解引用函数的行为在其他方面未由本文档规定。

鼓励实现者定义并记录其实现 在 DID URL 包含重复查询 参数名时的行为。由于本规范中定义的所有 DID 参数都具有 标量值(见 3. DID 参数),因此这些参数的任何重复出现都表示 一个歧义输入,没有明确定义的 解析行为。一种合理做法是将这样的 DID URL 视为无效, 并返回 INVALID_DID_URL 错误 (见 11. 错误)。

鼓励定义方法特定查询参数的 DID 方法规范 明确说明这些参数是否允许重复出现, 若允许,则定义解析语义(例如第一个值 优先、最后一个值优先、集合并集)。

3.2.3 按 DID 方法规范化

3. DID 参数中定义的查询参数集合并非 穷尽。DID 方法可以定义其他方法特定查询参数, 而这些参数的规范形式(包括其名称、值 格式和顺序)可能因方法而异。

鼓励 DID 方法规范为其定义的任何 方法特定查询参数指定规范形式,涵盖以下 考量:

  1. 值格式: 每个参数所期望的编码、字符 集以及有效值范围。
  2. 参数顺序: 查询参数的相对顺序 是否具有语义意义;若有,规范 顺序是什么。在没有明确指南的情况下, 在比较 DID URL 的逻辑等价性时,将参数顺序视为无关紧要 是合理的。
  3. 大小写敏感性: 参数名或 值是否区分大小写。本 规范中定义的参数名是区分大小写的 ASCII 字符串。在缺少 DID 方法规范相反指南的情况下,参数 值最好视为区分大小写。

需要测试两个 DID URL 逻辑等价性的实现(例如,用于 缓存查找)在应用 3.2.1 百分号编码规范化所述的百分号编码 规范化之后,鼓励采用与参数顺序无关的比较, 除非适用的 DID 方法规范定义了具有语义意义的规范参数 顺序。

4. DID 解析

DID 解析 函数通过使用适用 DID 方法的 “Resolve” 操作, 将一个 DID 解析为 DID 文档,如 方法操作中 所述。

DID 解析DID URL 解引用的一部分,如 5. DID URL 解引用中所述。

要能够解引用 DID URL,首先需要一个 DID 文档,它 是 DID 解析 过程的结果。DID 文档会在 DID URL 解引用过程中以多种方式使用。 术语 DID 解析RFC3986 第 1.2.2 节中定义的 “URI 解析”一致,因为它提供了 “解引用 URI 所必需的适当参数”。

所有 一致性 DID 解析器都实现以下函数, 其抽象形式如下:

resolve(did, resolutionOptions) →
   « didResolutionMetadata, didDocument, didDocumentMetadata »

所有 一致性 DID 解析器 MUST 至少为一个 DID 方法实现 DID 解析 函数,并且 MUST 能够返回一个 DID 文档

一致性 DID 解析器 实现不得以任何方式更改 此函数的签名。 DID 解析器 实现可以将 resolve 函数映射到特定方法的内部函数,以 执行实际的 DID 解析过程。 DID 解析器 实现除了此处指定的 resolve 函数外,还可以实现并 暴露具有不同签名的其他函数。

resolve 函数的输入变量如下:

did
这是要解析的 DID。此输入 是 REQUIRED, 且该值 MUST去中心化标识符(DID)v1.0中定义的一致性 DID
resolutionOptions
一个 元数据结构,由传递给 resolve 函数的 输入选项组成,并且包含 did 本身之外的内容。此结构在 4.1 DID 解析 选项中进一步定义。此输入是 REQUIRED,但该 结构 MAY 为空。

此函数返回多个值,且不限制 这些值如何一起返回。 resolve 的返回值为 didResolutionMetadatadidDocumentdidDocumentMetadata。 这些值说明如下:

didResolutionMetadata
一个 元数据结构,由与 DID 解析过程结果相关的值组成。此结构 是 REQUIRED,并且在解析过程中发生错误时, 此结构 MUST NOT 为空。此结构在 4.2 DID 解析 元数据中进一步定义。如果解析不成功, 此结构 MUST 包含一个描述 错误的 error 属性。参见第 11. 错误节。
didDocument
如果解析成功,此值 MUST 是一个 DID 文档,且 能够以 去中心化标识符(DID)v1.0 规范的一种一致性 表示 来表示。已解析 DID 文档中的 idMUST 与已解析的 DID 字符串相等。如果 解析不成功,此值 MUST 为空。
didDocumentMetadata
如果解析成功,此值 MUST 是一个 元数据结构。 此结构包含关于 didDocument 属性中所含 DID 文档的元数据。 如果解析不成功,此输出 MUST 是一个 空的 元数据结构。 此结构在 4.3 DID 文档元数据中进一步定义。

4.1 DID 解析选项

这是一个 元数据结构,其中包含 DID 解析过程的输入选项。

此结构中的可能属性及其可能值 SHOULD 注册到 DID Resolution Extensions [DID-EXTENSIONS-RESOLUTION]。 本规范定义以下常见输入选项:

accept
调用者首选的 DID 文档 表示的媒体类型。 该值 MUSTHTTP 语义 第 12.5.1 节中定义的 Accept 标头值来表示。DID 解析器 实现 SHOULD 使用此值来确定返回的 didDocument表示, 前提是此类 表示 受支持且可用。此属性是 OPTIONAL
expandRelativeUrls
一个布尔标志,指示 DID 解析器相对 DID URLDID 文档中展开为符合 DID URL 语法的一致性绝对 DID URL。
versionId
定义见 3. DID 参数
versionTime
定义见 3. DID 参数

4.2 DID 解析元数据

这是一个 元数据结构,其中包含关于 DID 解析过程的元数据。

此元数据通常会在每次调用 DID 解析 函数时发生变化,因为它表示关于 解析过程本身的数据。

此元数据的来源是 DID 解析器

DID 解析元数据的示例包括:

此结构中的可能属性及其可能值 SHOULD 注册到 DID Resolution Extensions [DID-EXTENSIONS-RESOLUTION]。 本规范定义以下常见元数据属性:

contentType
返回的 didDocument 的媒体类型。此 属性是 OPTIONAL。如果存在,此属性的值 MUST 是 一个 ASCII 字符串,并且是 一致性 表示的媒体类型。在这种情况下, resolve 函数的调用者 MUST 在 确定如何解析和处理 didDocument 时使用此值。
error
错误数据结构定义于 [RFC9457]。本 规范定义的错误可见第 11. 错误节。 其他错误 SHOULD 注册到 DID Resolution Extensions [DID-EXTENSIONS-RESOLUTION]。
proof

一些 DID 解析器DID URL 解引用器 在执行 DID 解析DID URL 解引用 函数时使用证明。详情见 8.2 解析器架构

DID 解析元数据 MAY 包含 proof 属性。 如果存在,该值 MUST 是一个 集合,其中每个 项都是表示证明的 映射。此属性的使用 和证明类型与 DID 方法无关。

4.3 DID 文档元数据

这是一个 元数据结构,其中包含关于 DID 解析过程的元数据。

此元数据通常不会在每次调用 DID 解析 函数时发生变化,除非 DID 文档 发生变化,因为它表示关于 DID 文档的数据。

此元数据的来源是 DID 控制者和/或 DID 方法。由 DID 控制者证明的 DID 文档元数据本身并不天然保证准确性。建议客户端在依赖 DID 文档元数据来指导业务 逻辑时谨慎行事。

DID 文档元数据的示例包括:

此结构中的可能属性及其可能值 SHOULD 注册到 DID Document Properties Extensions [DID-EXTENSIONS-PROPERTIES]。本 规范定义以下常见 元数据属性。

created
DID 文档 元数据 SHOULD 包含 created 属性, 用于指示 Create 操作的时间戳。该 属性的值 MUST3.1 日期时间中定义的日期时间格式表示。
updated
DID 文档 元数据 SHOULD 包含 updated 属性,用于指示已解析文档版本的最后一次 Update 操作 的时间戳。该属性的值 MUST3.1 日期时间中定义的日期时间格式表示。 如果从未对该 DID 文档执行过 Update 操作,则省略 updated 属性。如果存在 updated 属性,当两个时间戳之间的差异 小于一秒时,它可以与 created 属性具有相同值。
deactivated
如果 DID 已被 停用DID 文档 元数据 MUST 包含此属性, 且布尔值为 true。如果 DID 尚未被停用, 此属性是 OPTIONAL,但如果包含,则 MUST 具有布尔值 false
nextUpdate
如果已解析文档版本不是文档的最新版本, DID 文档 元数据 MAY 包含 nextUpdate 属性。它表示下一次 Update 操作的时间戳。 该属性的值 MUST3.1 日期时间中定义的日期时间格式 表示。
versionId
DID 文档 元数据 SHOULD 包含 versionId 属性,用于指示已解析文档 版本的最后一次 Update 操作的版本。该属性的值 MUSTASCII 字符串
nextVersionId
如果已解析文档版本 不是文档的最新版本,DID 文档 元数据 MAY 包含 nextVersionId 属性。它表示下一次 Update 操作的版本。 该属性的值 MUSTASCII 字符串
equivalentId

DID 方法 可以定义逻辑等价的 DID的不同形式。 一个示例是,当某个 DID 在注册到 可验证数据 注册表之前采用一种形式, 而在完成此类注册之后采用另一种形式。在这种情况下, DID 方法 规范可能需要将一个或多个与已解析 DID逻辑等价的 DID 表达为 DID 文档的属性。这就是 equivalentId 属性的目的。

DID 文档元数据 MAY 包含 equivalentId 属性。如果存在,该值 MUST 是 一个 集合,其中每一项都是符合 字符串规则且符合 去中心化标识符(DID) v1.0一节的字符串。该关系是一项 声明,表示每个 equivalentId 值都与 id 属性值在逻辑上 等价,因此指向同一 DID 主体。每个 equivalentId DID 值 MUST 由与 id 属性 值相同的 DID 方法 产生,并且是该方法的一种形式。(例如 did:example:abc == did:example:ABC

一致性 DID 方法规范 MUST 保证每个 equivalentId 值都与 id 属性值在逻辑上 等价。

请求方预期保留 idequivalentId 属性中的值,以确保 与它们包含的任何值的后续交互 都会被正确处理为逻辑等价(例如,在数据库中保留所有 变体,以便与其中任意一个的交互都映射到同一 底层账户)。

: 更强的等价性

equivalentId 是一种比 alsoKnownAs 强得多的等价形式,因为 这种等价性 MUST 由管辖性的 DID 方法保证。使用 equivalentId 意味着同一个 DID 文档 同时描述 equivalentId DIDid 属性的 DID

如果请求方不保留 idequivalentId 属性中的值,并确保 与它们包含的任何值的后续交互 都被正确处理为逻辑等价,则可能会 出现负面或意外问题。强烈建议实现者 遵守与此元数据属性相关的指令。

canonicalId

canonicalId 属性与 equivalentId 属性相同,但有以下区别:a) 它关联的是单个值而不是一个集合;b) 该 DID 被定义为 所含 DID 文档范围内该 DID 主体的规范 ID。

DID 文档元数据 MAY 包含 canonicalId 属性。 如果存在,该值 MUST 是一个 字符串,且 符合 去中心化标识符(DID)v1.0一节中的规则。 该关系是一项声明,表示 canonicalId 值与 id 属性值在逻辑上等价,并且 该 canonicalId 值由 DID 方法 定义为所含 DID 文档范围内 DID 主体的规范 ID。一个 canonicalIdMUST 由与 id 属性值相同的 DID 方法产生,并且是该方法的一种形式。 (例如 did:example:abc == did:example:ABC)。

一致性 DID 方法规范 MUST 保证 canonicalId 值与 id 属性值在逻辑上等价。

请求方预期将 canonicalId 值用作该 DID 主体的主要 ID 值,并将所有 其他等价值视为次要别名(例如,更新 其系统中的相应主要引用,以反映新的 规范 ID 指令)。

: 规范等价性

canonicalIdequivalentId 是相同的等价性声明, 只是它被限制为单个值, 且该值被定义为 DID 主体DID 文档范围内的规范值。与 equivalentId 一样,使用 canonicalId 意味着同一个 DID 文档 同时描述 canonicalId DID 和 id 属性的 DID

如果解析方不将 canonicalId 值用作 DID 主体的主要 ID 值,并将所有其他等价值 视为次要别名,则可能会出现与用户体验相关的负面或意外问题。 强烈建议实现者遵守与此元数据 属性相关的指令。

proof

许多 DID 方法在执行 方法操作时使用证明。详情见 8.1 方法 架构

DID 文档元数据 MAY 包含 proof 属性。如果存在,该值 MUST 是一个 集合,其中每一项都是表示证明的 映射。此属性的使用 以及证明类型是 DID 方法特定的。

4.4 DID 解析算法

DID 解析器 实现以下 DID 解析 算法。

  1. 验证 input DID 是否符合 DID 语法did 规则。 如果不符合,DID 解析器 MUST 返回以下结果:
    1. didResolutionMetadataerror object,其 type 设为 https://www.w3.org/ns/did#INVALID_DID
    2. didDocumentnull
    3. didDocumentMetadata«[ ]»
  2. 确定实现此算法的 DID 解析器 是否支持 input DID 的 DID 方法。如果 不支持,DID 解析器 MUST 返回以下 结果:
    1. didResolutionMetadataerror object,其 type 设为 https://www.w3.org/ns/did#METHOD_NOT_SUPPORTED
    2. didDocumentnull
    3. didDocumentMetadata«[ ]»
  3. 确定 input DID 解析选项 是否受实现此算法的 DID 解析器支持。 如果不支持,DID 解析器 MUST 返回以下结果:
    1. didResolutionMetadataerror object,其 type 设为 https://www.w3.org/ns/did#FEATURE_NOT_SUPPORTED
    2. didDocumentnull
    3. didDocumentMetadata«[ ]»
  4. 确定 input DID 解析选项 是否有效。如果无效,DID 解析器 MUST 返回以下结果:
    1. didResolutionMetadataerror object,其 type 设为 https://www.w3.org/ns/did#INVALID_OPTIONS
    2. didDocumentnull
    3. didDocumentMetadata«[ ]»
  5. 通过执行由 input DID 方法定义的 Resolve 操作,获取 input DIDDID 文档
    1. 如果 input DID 不存在,则返回以下结果:
      1. didResolutionMetadataerror object,其 type 设为 https://www.w3.org/ns/did#NOT_FOUND
      2. didDocumentnull
      3. didDocumentMetadata«[ ]»
    2. 如果 input DID 已被 停用,则返回以下结果:
      1. didResolutionMetadata«[ ... ]»
      2. didDocumentnull
      3. didDocumentMetadata«[ "deactivated" → true, ... ]»
    3. 否则,Resolve 操作的结果称为 output DID 文档。 此结果 MUST一致性表示来表示。
  6. 如果 input DID 解析选项 包含值为 trueexpandRelativeUrls 选项:
    1. 遍历 output DID 文档中的所有 服务验证方法验证 关系 以及任何扩展定义的属性。
    2. 对于每一项,如果该项是对象,并且 id 属性的值是 相对 DID URL, 或者如果某个 验证 关系相对 DID URL
      1. 根据 去中心化标识符(DID) v1.0相对 DID URL一节的规则,将该 相对 DID URL 解析为符合 DID URL 语法的一致性绝对 DID URL
    3. 通过将 相对 DID URL替换为已解析的 绝对 DID URL,更新 output DID 文档
  7. 返回以下结果:
    1. didResolutionMetadata«[ ... ]»
    2. didDocumentoutput DID document
    3. didDocumentMetadata«[ "contentType" → output DID document media type, ... ]»

如果 DID 解析器 在执行 DID 解析算法期间 遇到任何意外错误,它 MUST 返回以下 结果:

  1. didResolutionMetadataerror object,其 type 设 为 https://www.w3.org/ns/did#INTERNAL_ERROR
  2. didDocumentnull
  3. didDocumentMetadata«[ ]»

5. DID URL 解引用

(存在风险的功能)议题 2

整个章节当前存在风险,并且很可能会被大幅修改或 从本规范中移除。工作组正在征求实现者关于 本章节 价值的反馈。

DID URL 解引用函数将一个 DID URL 解引用为一个 资源, 其内容取决于 DID URL 的各个组成部分, 包括 DID 方法、 方法特定标识符、路径、 查询和片段。此过程依赖于对 DID URL 中所含 DIDDID 解析DID URL 解引用可能涉及 多个步骤(例如,当被解引用的 DID URL 包含片段时), 并且该函数被定义为在所有步骤完成后返回最终资源。 下图描绘了上述关系。


DID 解析为 DID 文档;DID URL 包含 DID;DID URL 解引用为 DID 文档片段或
外部资源。
1 DID URL 解引用概览。另请参见:叙述性描述

图的左上部分包含一个黑色轮廓的矩形, 标记为“DID”。

图的左下部分包含一个黑色轮廓的矩形, 标记为“DID URL”。该矩形包含四个较小的黑色轮廓 矩形,水平相邻排列。这些较小的 矩形依次标记为“DID”、“path”、“query”和“fragment”。

图的右上部分包含一个黑色轮廓的矩形, 标记为“DID document”。该矩形包含三个较小的黑色轮廓 矩形。这些较小的矩形标记为“id”、“(property X)”和 “(property Y)”,并被多组三个点(省略号)围绕。 一条标记为“DID document - relative fragment dereference”的黑色弯曲箭头 从标记为“(property X)”的矩形延伸,并指向 标记为“(property Y)”的矩形。

图的右下部分包含一个黑色轮廓的椭圆形, 标记为“Resource”。

一条标记为“resolves to a DID document”的黑色箭头,从图左上部分 标记为“DID”的矩形延伸,并指向图右上部分 标记为“DID document”的矩形。

一条标记为“refers to”的黑色箭头,从图右上 部分标记为“DID document”的矩形延伸,并指向图 右下部分标记为“Resource”的椭圆形。

一条标记为“contains”的黑色箭头,从图左下部分标记为“DID URL”的矩形内部、标记为 “DID”的小矩形延伸,并指向图左上部分标记为 “DID”的矩形。

一条标记为“dereferences to a DID document”的黑色箭头,从图 左下部分标记为“DID URL”的矩形延伸,并指向图右上部分 标记为“DID document”的矩形。

一条标记为“dereferences to a resource”的黑色箭头,从图 左下部分标记为“DID URL”的矩形延伸,并指向图 右下部分标记为“Resource”的椭圆形。

所有 一致性 DID URL 解引用器都实现 以下函数,其 抽象形式如下:

dereference(didUrl, dereferenceOptions) →
   « dereferencingMetadata, contentStream, contentMetadata »

所有 一致性 DID URL 解引用器 MUST 至少为一个 DID 方法实现 DID URL 解引用函数。 dereference 函数除 contentStream 之外的所有输入和 输出 MUST 可序列化为 JSON。

dereference 函数的输入变量 如下:

didUrl
作为单个 字符串的一致性 DID URL。 这是要 解引用的 DID URL。要解引用 DID 片段MUST 使用包含该 DID 片段在内的完整 DID URL。 此输入是 REQUIRED
:DID URL 解引用器模式

虽然任何 didUrl 都可以传递给 DID URL 解引用器,但预期实现者参考 5. DID URL 解引用 以进一步理解关于 DID URL 预期如何被 解引用的常见模式。

dereferencingOptions
一个 元数据结构, 由传递给 dereference 函数的输入选项组成,并且包含 didUrl 本身之外的内容。此结构在 5.1 DID URL 解引用选项中进一步定义。此输入是 REQUIRED,但该 结构 MAY 为空。

此函数返回多个值,且不限制 这些值如何一起返回。 dereference 的返回值为 dereferencingMetadatacontentStreamcontentMetadata。 这些值说明如下:

dereferencingMetadata
一个 元数据结构, 由与 DID URL 解引用过程结果相关的值组成。 此结构 是 REQUIRED,并且在解引用过程中发生错误时, 此结构 MUST NOT 为空。此结构在 5.2 DID URL 解引用元数据中进一步定义。如果解引用不成功, 此结构 MUST 包含一个描述 错误的 error 属性。参见第 11. 错误节。
contentStream
如果调用 dereferencing 函数且成功, 此值 MUST 包含与 DID URL 对应的 资源contentStream MAY 是一个 资源, 例如可序列化为一种一致性 表示DID 文档验证方法服务,或 任何其他可通过媒体类型标识并可通过 解析过程获得的资源格式。如果解引用 不成功,此值 MUST 为空。
contentMetadata
如果解引用成功,此值 MUST 是一个 元数据结构,但该结构 MAY 为空。此 结构包含关于 contentStream 的元数据。如果 contentStream 是一个 DID 文档, 则此值 MUST 是一个 didDocumentMetadata 结构,如 DID 解析中所述。如果 解引用不成功, 此输出 MUST 是一个空的 元数据 结构。此 结构在 5.3 DID URL 内容元数据中进一步定义。

一致性 DID URL 解引用实现不得以任何方式更改 这些函数的签名。 DID URL 解引用实现可以将 dereference 函数映射到特定方法的内部函数, 以执行实际的 DID URL 解引用过程。 DID URL 解引用实现除了此处指定的 dereference 函数外,还可以实现并 暴露具有不同签名的其他函数。

5.1 DID URL 解引用选项

这是一个 元数据结构,其中包含 DID URL 解引用过程的输入选项。

此结构中的可能属性及其可能值 SHOULD 注册到 DID Resolution Extensions [DID-EXTENSIONS-RESOLUTION]。 本规范定义以下常见输入选项:

accept
调用者首选用于 contentStream 的媒体类型。该值 MUSTHTTP 语义 第 12.5.1 节中定义的 Accept 标头值来表示。DID URL 解引用器 实现 SHOULD 使用此值来确定返回值中所含 表示contentType,前提是此类 表示受支持且可用。
verificationRelationship
调用者期望从 DID URL 解引用得到的 verificationMethod 被授权用于的 verificationRelationship。如果存在,关联值 MUST 是一个 ASCII 字符串。如果 DID URL 未 解引用到 verificationMethod,或者 DID 文档未针对指定的 verificationRelationship 授权该 verificationMethod,则 MUST 引发错误。

5.2 DID URL 解引用元数据

这是一个 元数据结构,其中包含关于 DID URL 解引用过程的元数据。

此元数据通常会在每次调用 DID URL 解引用函数时发生变化,因为它表示关于 解引用过程本身的数据。

此元数据的来源是 DID URL 解引用器

此结构中的可能属性及其可能值 SHOULD 注册到 DID Resolution Extensions [DID-EXTENSIONS-RESOLUTION]。 本规范定义以下常见元数据属性:

contentType
返回的 contentStream 的媒体类型在解引用成功时 SHOULD 使用此属性来表示。该 媒体类型值 MUST 表示为 ASCII 字符串
error
定义于 [RFC9457] 的错误数据结构。当 解引用过程中出现错误时,此属性 是 REQUIRED。本 规范定义的错误可见第 11. 错误节。 其他错误 SHOULD 注册到 DID Resolution Extensions [DID-EXTENSIONS-RESOLUTION]。
proof

一些 DID 解析器DID URL 解引用器在执行 DID 解析DID URL 解引用 函数时使用证明。详情见 8.2 解析器架构

DID URL 解引用元数据 MAY 包含 proof 属性。如果存在,该值 MUST 是一个 集合,其中每一项都是表示证明的 映射。此属性的使用 和证明类型与 DID 方法无关。

5.3 DID URL 内容元数据

这是一个 元数据结构,其中包含关于 DID URL 解引用过程的元数据。

此元数据通常不会在每次调用 DID URL 解引用函数时发生变化,除非内容发生变化,因为它 表示关于内容的数据。

此元数据的来源是 DID 控制者和/或 DID 方法

此结构中的可能属性及其可能值 SHOULD 注册到 DID Resolution Extensions [DID-EXTENSIONS-RESOLUTION]。 本规范未定义任何通用属性。

5.4 DID URL 解引用 算法

DID URL 解引用器实现以下 DID URL 解引用算法。按照 [RFC3986],它包括 以下三个步骤:解析 DID;解引用资源;以及解引用片段(仅当 input DID URL 包含 DID 片段时):

5.4.1 解引用资源

  1. 验证 input DID URL 是否符合 DID URL 语法did-url 规则。 如果不符合,DID URL 解引用器 MUST 返回以下结果:
    1. dereferencingMetadataerror object,其 type 设为 https://www.w3.org/ns/did#INVALID_DID_URL
    2. contentStreamnull
    3. contentMetadata«[ ]»
  2. 通过执行 4. DID 解析中定义的 DID 解析算法,获取 input DIDDID 文档input DID URL 的所有 dereferencing options 和所有 DID 参数 MUST 作为 resolution options 传递给 DID 解析算法。
  3. 如果 input DID 不存在于 VDR 中,则 DID URL 解引用器 MUST 返回 以下结果:
    1. dereferencingMetadataerror object,其 type 设为 https://www.w3.org/ns/did#NOT_FOUND
    2. contentStreamnull
    3. contentMetadata«[ ]»
  4. 否则, DID 解析算法的 didDocument 结果称为 resolved DID document
  5. 如果存在,从 input DID URL 中分离 DID 片段,并继续使用 调整后的 input DID URL
  6. 如果 input DID URL 不包含 DID 路径且 不包含 DID 查询
    did:example:1234
    DID URL 解引用器 MUST 按如下方式返回 resolved DID documentresolved 4.3 DID Document Metadata
    1. dereferencingMetadata«[ ... ]»
    2. contentStreamresolved DID document
    3. contentMetadata«[ resolved DID document metadata
  7. 如果 input DID URL 包含 DID 参数 service 和/或 DID 参数 serviceType,以及 可选的 DID 参数 relativeRef
    did:example:1234?service=files&relativeRef=%2Fmyresume%2Fdoc%3Fversion%3Dlatest
    1. resolved DID document 中,选择所有满足 以下条件的 服务
      1. 如果 input DID URL 包含 DID 参数 service: 当 serviceid 属性与 service DID 参数的值匹配时,选择该服务。如果 id 属性或 service DID 参数,或两者都包含相对引用,则 MUST 解析相应的绝对 URI 并使用它们来 确定匹配,使用 RFC3986 第 5 节: 引用解析以及 去中心化标识符(DID) v1.0相对 DID URL一节所指定的规则。
      2. 如果 input DID URL 包含 DID 参数 serviceType:当 servicetype 属性与 serviceType DID 参数的值匹配时,选择该服务。
      被选择的 服务是一个列表, 称为 selected services
    2. 如果 input DID URL 包含 DID 参数 relativeRef
      1. 对于每个 selected service
        1. 如果 selected serviceserviceEndpoint 属性值是 一个 映射,则跳过此 selected service
        2. 如果 selected serviceserviceEndpoint 属性值 是一个 字符串,则将 此值添加 到 selected DID service endpoint URLs 列表。
        3. 如果 selected serviceserviceEndpoint 属性值是 一个 集合,则将其中所有 为 字符串的项添加到 selected DID service endpoint URLs 列表。
      2. 对于每个 selected DID service endpoint URL, 按如下方式执行 RFC3986 第 5 节: 引用解析中指定的算法:
        1. base URI 值是 selected DID service endpoint URL
        2. relative referenceDID 参数 relativeRef 的值。
        3. selected DID service endpoint URL 更新为 “Reference Resolution”算法的结果。

        解引用一个 DID 服务端点—— 尤其是本身为 DID 的服务端点——可能导致 解引用 循环,即一组 导致无限循环的步骤。例如,一个 DID 服务端点可能通过一系列解引用过程 间接指回 先前已解引用的标识符。建议 DID URL 解引用器在递归 解引用 DID 服务端点时 检测并处理此类循环,以防止无限 循环或解引用失败。更多指导, 见 解引用 循环一节。

    3. 如果 accept input DID URL dereferencing option 缺失,或者其值是 表示的媒体类型,且该表示属于 DID 文档
      1. 更新 resolved DID document 中的 服务,使其 仅包含 selected services
      2. 返回以下结果:
        1. dereferencingMetadata«[ ... ]»
        2. contentresolved DID document with selected services
        3. contentMetadata«[ resolved DID document metadata
    4. 如果 accept input DID URL deferencing option 的值是 text/uri-list
      1. 返回以下结果:
        1. dereferencingMetadata«[ ... ]»
        2. content« selected service endpoint URLs »
        3. contentMetadata«[ "contentType" → "text/uri-list", ... ]»
    5. 否则,返回以下结果:
      1. dereferencingMetadataerror object,其 type 设为 https://www.w3.org/ns/did#REPRESENTATION_NOT_SUPPORTED
      2. contentnull
      3. contentMetadata«[ ]»
  8. 否则,如果 input DID URL 包含 DID 路径和/或 DID 查询
    did:example:1234/custom/path?customquery
    1. 适用的 DID 方法 MAY 指定如何 解引用 input DID URLDID 路径和/或 DID 查询
      did:example:1234/resources/1234
    2. 扩展规范 MAY 指定如何解引用 input DID URLDID 路径
      did:example:1234/whois
    3. 扩展规范 MAY 指定如何解引用 input DID URLDID 查询
      did:example:1234?transformKey=JsonWebKey
    4. 客户端 MAY 能够以应用特定方式解引用 input DID URL
  9. 如果此算法、适用的 DID 方法、 扩展以及客户端 均无法解引用 input DID URL,则返回 以下结果:
    1. dereferencingMetadataerror object,其 type 设为 https://www.w3.org/ns/did#NOT_FOUND
    2. contentStreamnull
    3. contentMetadata«[ ]»

5.4.2 解引用片段

如果 input DID URL 包含 DID 片段, 则片段的解引用 取决于资源的媒体类型([RFC2046]),也就是 5.4.1 解引用资源的结果。

  1. 如果 5.4.1 解引用资源的结果是一个 output DID document,并且 input DID URL dereferencing options 包含 verificationRelationship 选项:
    1. verificationRelationshipverificationRelationship 选项的值。
    2. verificationMethod 为 根据 DID document 媒体类型的规则,从 output DID document 中解引用 DID 片段的结果。
    3. 如果 verificationMethod 不是一个 一致性 验证方法, 则 MUST 引发错误,并且 SHOULD 传达错误类型 INVALID_VERIFICATION_METHOD
    4. 如果 verificationMethod 未通过 引用(URL)或值(对象)与 output DID document 中由 verificationRelationship 标识的 verification relationship 数组相关联, 则 MUST 引发错误,并且 SHOULD 传达错误类型 INVALID_RELATIONSHIP_FOR_VERIFICATION_METHOD
    5. 返回 verificationMethod
  2. 如果 5.4.1 解引用资源的结果是一个 selected DID service endpoint URL,并且 input DID URL 包含一个 DID 片段
    did:example:1234?service=files&relativeRef=%2Fmyresume%2Fdoc%3Fversion%3Dlatest#intro
    1. 如果 selected DID service endpoint URL 包含 fragment 组件,则引发错误。
    2. DID 片段追加到 select DID service endpoint URL。换言之, select DID service endpoint URL “继承” input DID URLDID 片段
    3. 返回 select DID service endpoint URL
  3. 否则,按资源的媒体 类型([RFC2046]) 所定义的方式解引用 DID 片段。例如,如果资源 是媒体类型为 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 节)。

5.5 示例

5.5.1 示例: 解引用到验证方法

给定以下 input DID URL

did:example:123456789abcdefghi#keys-1

……以及以下 resolved DID document

{
	"@context":[
		"https://www.w3.org/ns/did/v1.1",
		"https://didcomm.org/messaging/contexts/v2",
		"https://identity.foundation/linked-vp/contexts/v1"
	],
	"id": "did:example:123456789abcdefghi",
	"verificationMethod": [{
		"id": "did:example:123456789abcdefghi#keys-1",
		"type": "Multikey",
		"controller": "did:example:123456789abcdefghi",
		"publicKeyMultibase": "z6MkmM42vxfqZQsv4ehtTjFFxQ4sQKS2w6WR7emozFAn5cxu"
	}],
	"service": [{
		"id": "did:example:123456789abcdefghi#messages",
		"type": "DIDCommMessaging",
		"serviceEndpoint": "https://example.com/messages/8377464"
	}, {
		"id": "did:example:123456789abcdefghi#linkedvp",
		"type": "LinkedVerifiablePresentation",
		"serviceEndpoint": "https://example.com/verifiable-presentation.jsonld"
	}]
}

……则 5. DID URL 解引用算法的结果 是以下 output resource

{
	"@context": "https://www.w3.org/ns/did/v1.1",
	"id": "did:example:123456789abcdefghi#keys-1",
	"type": "Multikey",
	"controller": "did:example:123456789abcdefghi",
	"publicKeyMultibase": "z6MkmM42vxfqZQsv4ehtTjFFxQ4sQKS2w6WR7emozFAn5cxu"
}
显示 DID URL 如何被解引用到验证方法的图示
2 将 DID URL 解引用到验证方法。

5.5.2 示例:解引用到服务端点 URL

给定以下 input DID URL

did:example:123456789abcdefghi?service=messages&relativeRef=%2Fsome%2Fpath%3Fquery#frag

……以及与上一节相同的 resolved DID document

……则 5. DID URL 解引用算法的结果 是以下 selected DID service endpoint URL

https://example.com/messages/8377464/some/path?query#frag
显示 DID URL 如何被解引用到服务端点 URL 的图示
3 将 DID URL 解引用到服务端点 URL。

6. 暂定 - DID URL 解引用

(存在风险的功能)议题 3

本节中的解引用算法是上一节所述算法的另一种方案,当前被标记为存在风险。 工作组很可能会就本规范中的解引用算法修订方案达成一致,该方案正在 此处讨论

工作组目前正在探索这种新的 DID URL 解引用算法,它采用比先前算法更模块化的 方法,基于“检索 策略”或“处理策略”。

6.1 DID URL 解引用 算法

6.1.1 准备解析

解引用 DID URL 的第一步是准备 DID 以进行 解析。这涉及验证 DID URL 语法、选择适当的 DID 解析器,并为解析请求准备 DID 及任何随附的 DID 解析选项

工作组目前正在讨论是否将 DID 解析函数的输入 从 DID 改为 DID URL

6.1.2 执行解析请求

下一步是选择一个 DID 解析器,并使用它以准备好的输入执行 解析 请求。这可能涉及向外部服务发出网络请求, 也可能涉及本地解析过程, 具体取决于 DID 解析器的特定实现。其 结果是一个 DID 解析结果,其中 包含已解析的 DID 文档及相关元数据,或错误信息。

6.1.3 确定检索 策略

成功解析 DID 文档及随附元数据之后, 下一步是确定用于检索 DID URL 所标识资源的适当策略。这涉及分析 DID 解析结果的 内容,包括 DID 文档及 其元数据,以及 DID URL 的路径和查询组件, 以确定检索该资源的方法。

6.1.4 检索资源

下一步是使用已确定的检索策略,检索 DID URL 所标识的资源。 检索策略可以在外部 规范中定义。客户端需要自行判断其是否能够 使用指定策略检索该资源。

6.1.5 使用资源

最后一步是在调用解引用的上下文中,使用检索到的资源来完成 DID URL 解引用过程。 这可能涉及将片段标识符应用于检索到的资源, 将生成的资源提供给调用方应用程序进程, 或者在无法完成解引用时产生错误。

7. 元数据结构

输入和输出元数据通常会参与 DID 解析DID URL 解引用以及其他 DID 相关过程。用于传达此元数据的结构 MUST 是一个 属性 映射。每个属性名 MUST 是一个 字符串。每个属性值,以及任何 复杂数据结构(例如映射或列表)中的每个值,MUST字符串数字映射列表集合布尔值,或 null。整个元数据结构 MUST 能够按照 [INFRA] 规范中的 JSON 序列化 规则 进行序列化。实现 MAY 将元数据结构序列化为其他数据格式。

所有使用元数据结构作为输入或输出的函数实现, 都能够以确定性的方式完整表示此处描述的所有数据类型。 由于使用元数据结构的输入和输出是根据数据类型而非其序列化来 定义的,因此 表示方法属于该函数实现的内部事项, 不在本规范范围内。

以下示例展示了一个 JSON 编码的元数据结构,它可能 用作 DID 解析选项

示例 15:JSON 编码的 DID 解析选项示例
{
"accept": "application/did"
}

此示例对应于以下格式的元数据结构:

示例 16:DID 解析选项示例
«[
"accept""application/did"

下一个示例展示了一个 JSON 编码的元数据结构,如果 未找到某个 DID, 它可能用作 DID 解析元数据

示例 17:JSON 编码的 DID 解析元数据示例
{
"error": "notFound"
}

此示例对应于以下格式的元数据结构:

示例 18:DID 解析元数据示例
«[
"error""notFound"

下一个示例展示了一个 JSON 编码的元数据结构,它可能 用作 DID 文档元数据,以描述 与 DID 文档相关联的时间戳。

示例 19:JSON 编码的 DID 文档元数据示例
{
"created": "2019-03-23T06:35:22Z",
"updated": "2023-08-10T13:40:06Z"
}

此示例对应于以下格式的元数据结构:

示例 20:DID 文档元数据示例
«[
"created""2019-03-23T06:35:22Z",
"updated""2023-08-10T13:40:06Z"

8. DID 解析架构

(存在风险的功能)议题 4

本节当前被标记为存在风险,并且很可能会被 DID 解析威胁模型中的内容取代。

8.1 方法架构

DID 解析 算法涉及根据某个 DIDDID 方法执行其上的 Resolve 操作(见 4. DID 解析)。

每种 DID 方法都会定义此方法操作,即 DID 解析器如何 从 DID 获得 DID 文档。底层数据格式、协议、技术基础设施和过程在 各种 DID 方法之间可能 差异很大。

DID 方法考量示例包括以下内容:

基于上述考量,并结合 DID 方法的 “Resolve” 操作的性质, DID 解析器可验证数据注册表 之间的交互 可以被视为 可验证解析不可验证解析

显示 DID 方法的“可验证解析”实现的图示。
4 DID 方法的 可验证解析实现。
显示 DID 方法的“不可验证解析”实现的图示。
5 DID 方法的 不可验证解析实现。

可验证解析会在适用 DID 方法可达到的范围内,最大化对 “Resolve” 操作结果完整性和 正确性的信心。这可以通过多种方式完成, 例如以下方式:

不可验证解析不具有此类保证, 因此 较不理想,例如:

: 实现细节

可验证解析是否可能,不仅取决于 DID 方法 本身,还取决于 DID 解析器 实现该 DID 方法的方式。 DID 方法 MAY 允许多种方式来实现其 “Resolve” 操作,并且 SHOULD 就至少一种 实现 可验证解析的方式提供指导。

:可验证数据注册表的 局限性

可验证解析相关的保证 总是受到 DID 方法底层 可验证数据 注册表的架构、协议、密码学元素和其他 方面的限制。被认为最强的 可验证解析 实现形式,是那些不需要与任何远程网络交互的形式 (例如,参见 [DID-KEY]), 以及那些 最大限度减少对特定网络基础设施依赖、将 “信任根”缩减为已证明的熵和密码学的形式(例如,参见 [KERI])。

为了启用 可验证解析,许多 DID 方法使用数字 签名、状态证明、Merkle 树中的包含证明、密码学 事件日志或其他类型的证明。如果 DID 方法使用 此类证明,则它 MUST 在其 DID 方法规范中说明如何使用这些证明 来验证 “Resolve” 操作结果的正确性。

DID 方法 MAY 也将此类证明包含在 DID 文档 本身中,或包含在 DID 文档元数据proof 属性中。 即使 客户端不信任 DID 解析器, 这也可能使其能够独立验证 DID 解析 过程的结果。

请注意,源自 DID 方法的证明是 DID 方法特定的, 并且必须在适用 DID 方法的技术范围内理解。对 DID 文档DID 文档元数据 的简单签名并不一定证明对 DID 的控制,也不保证该 DID 文档就是 该 DID的 正确文档。 这些证明有助于在 DID 方法 本身所关涉的范围内,验证 DID 解析过程结果的完整性和 真实性。然而,它们并不 保证 客户端DID 解析器之间的 绑定是 安全的。另请参见 8.2 解析器 架构

8.2 解析器架构

DID 解析DID URL 解引用算法被定义为抽象函数(见 4. DID 解析5. DID URL 解引用)。

这些算法由 DID 解析器DID URL 解引用器实现,并由 客户端通过 绑定调用。绑定 定义了如何使用具体的编程或 通信接口访问抽象函数。

绑定示例包括以下内容:

基于上述考量,并结合绑定的性质, 客户端DID 解析器DID URL 解引用器之间的交互 可以被视为 本地绑定远程绑定

显示具有“本地绑定”的 DID 解析器的图示。
6 用于 DID 解析器本地绑定
显示具有“远程绑定”的 DID 解析器的图示。
7 用于 DID 解析器远程绑定

在可能的情况下,优先使用 本地绑定,因为它们 最大限度减少对第三方和中介的依赖,降低安全 风险,并最大化对 DID 解析DID URL 解引用 函数结果完整性和正确性的信心。

在某些情况下,可能无法使用 本地绑定;例如,在受限的 IoT(物联网) 环境中,或当 DID 方法需要复杂 基础设施时,或当需要支持许多不同 DID 方法时。

如果 客户端 使用 远程绑定,则适用 以下考量:

DID 解析器 MAY 也可以在 DID 解析元数据proof 属性中包含证明。

请注意,源自 DID 解析器的证明 与 DID 方法无关,并且可由 DID 解析器 跨所有 DID 方法统一应用。这些证明有助于 在 DID 解析器本身 所关涉的范围内,验证 DID 解析 过程结果的完整性和真实性。然而,它们并不 保证适用 DID 方法的 “Resolve” 操作结果本身是 正确的。另请参见 8.1 方法架构

8.2.1 多种方法

DID 解析器 可能支持用于多种 DID 方法DID 解析 算法:

显示支持多种 DID 方法的 DID 解析器的图示。
8 支持多种 DID 方法DID 解析器

在这种情况下,8.1 方法架构中关于 可验证解析不可验证解析 实现的上述考量,分别适用于每个受支持的 DID 方法

8.2.2 代理解析

DID 解析器 MAY 调用另一个 DID 解析器, 后者作为代理执行 DID 解析 算法,如 4. DID 解析中所定义。

第一个 DID 解析器随后充当 客户端, 并选择适合的 绑定来调用第二个 DID 解析器。 例如,DID 解析器 可以通过 本地绑定(例如命令行 工具)调用,而该工具又通过 远程绑定(例如 HTTP(S) 绑定)调用另一个 DID 解析器

使用代理解析时,“下游”解析器 SHOULD 以透明方式保留来自 “上游”解析器的所有 DID 解析元数据DID 文档元数据, 包括可能存在的任何证明。在此过程中,“下游”解析器 MAY 添加其自己的 DID 解析元数据, 包括关于代理解析过程本身的任何元数据。

显示两个 DID 解析器的图示,一个通过“本地绑定”调用,另一个通过“远程绑定”调用。
9 客户端通过 本地绑定调用 DID 解析器,该解析器通过 远程绑定调用另一个 DID 解析器,后者继而执行 DID 方法的解析操作。
: 与 DNS 的比较

这类似于 DNS 架构中的“存根解析器”调用“递归解析器”, 尽管这些概念并不完全可比(DNS 解析 使用单一的具体协议,而 DID 解析是一个抽象函数, 由不同 DID 方法和不同 绑定实现)。

8.2.3 客户端侧解引用

DID URL 解引用算法的不同部分 可以由 解析器架构中的不同组件执行。

具体而言,当解引用带有 DID 片段DID URL 时, 解引用资源DID 解析器完成,而 解引用片段客户端完成。

8.3 示例

给定 DID URL did:xyz:1234#keys-1,可以通过 本地绑定调用 DID 解析器解引用资源 (即 DID 文档),而 客户端可以通过 解引用片段 (即 DID 文档的一部分) 完成 DID URL 解引用算法。

显示由 DID 解析器和客户端对 DID URL 进行客户端侧解引用的图示
10 DID 解析器客户端DID URL进行客户端侧解引用。

给定 DID URL did:xyz:1234?service=agent&relativeRef=%2Fsome%2Fpath%3Fquery#frag, 可以调用 DID 解析器解引用资源 (即 DID 服务端点 URL),而 客户端可以通过 解引用片段 (即带有片段的 DID 服务端点 URL) 完成 DID URL 解引用算法。

显示由 DID 解析器和客户端对 DID URL 进行客户端侧解引用的图示
11 DID 解析器客户端DID URL进行客户端侧解引用。

给定 DID URL did:xyz:1234#keys-1,可以通过 本地绑定调用 DID 解析器,该解析器又通过 远程绑定调用另一个 DID 解析器解引用资源 (即 DID 文档),而 客户端可以通过 解引用片段 (即 DID 文档的一部分) 完成 DID URL 解引用算法。

显示由两个 DID 解析器和一个客户端对 DID URL 进行客户端侧解引用的图示
12 由两个 DID 解析器和 一个 客户端DID URL进行客户端侧解引用 (结合 代理 解析)。

9. DID 解析结果

本节定义了一个 JSON 数据结构,用于表示 4. DID 解析中所述算法的结果。 DID 解析结果包含 DID 文档,以及 DID 解析元数据DID 文档元数据

此数据结构的媒体类型定义为 application/did-resolution

9.1 示例

示例 21:DID 解析结果示例
{
	"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",
		"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"
			}
		}
	}
}

10. DID URL 解引用结果

(存在风险的功能)议题 5

本节当前被标记为存在风险,并且可能会在候选推荐阶段 被大幅修改或从本规范中移除。

本节定义了一个 JSON 数据结构,用于表示 5. DID URL 解引用中所述算法的结果。 DID URL 解引用结果包含内容,以及 DID URL 解引用元数据 DID URL 内容元数据

此数据结构的媒体类型定义为 application/did-url-dereferencing

10.1 示例

示例 22:DID URL 解引用结果示例
{
	"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/"
		}]
	},
	"didUrlDereferencingMetadata": {
		"contentType": "application/did",
		"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"
			}
		}
	}
}

11. 错误

本规范中描述的算法会抛出特定类型的错误。 实现者可能会发现,将这些错误传达给其他库或 软件系统很有用。本节为这些错误提供特定 URL 和描述, 以便实现本规范所述技术的生态系统 在发生错误时可以更有效地互操作。 此外,本规范还使用 [CID] 规范的 第 3.5 节 处理错误 中定义的一些错误。

实现者 SHOULD 使用 [RFC9457] 来编码错误 数据结构。如果使用 [RFC9457]:

INVALID_DID
DID 解析期间检测到无效 DID。 参见 4.4 DID 解析 算法
https://www.w3.org/ns/did#INVALID_DID
INVALID_DID_DOCUMENT
DID 文档 格式不正确。参见 4.4 DID 解析 算法
https://www.w3.org/ns/did#INVALID_DID_DOCUMENT
NOT_FOUND
DID 解析器 无法找到此解析 请求所产生的 DID 文档。 参见 4.4 DID 解析算法
https://www.w3.org/ns/did#NOT_FOUND
REPRESENTATION_NOT_SUPPORTED
通过 accept DID URL 解引用选项请求的 表示不受 DID 方法和/或 DID URL 解引用器实现支持。参见 5.4 DID URL 解引用 算法
https://www.w3.org/ns/did#REPRESENTATION_NOT_SUPPORTED
INVALID_DID_URL
DID URL 解引用期间检测到无效 DID URL。参见 5.4 DID URL 解引用 算法
https://www.w3.org/ns/did#INVALID_DID_URL
METHOD_NOT_SUPPORTED
DID 的 DID 方法不受 DID 解析器支持。参见 4.4 DID 解析 算法
https://www.w3.org/ns/did#METHOD_NOT_SUPPORTED
INVALID_OPTIONS
DID 解析DID URL 解引用提供的一个或多个选项 无效。
https://www.w3.org/ns/did#INVALID_OPTIONS
INTERNAL_ERROR
DID 解析DID URL 解引用期间发生意外错误。
https://www.w3.org/ns/did#INTERNAL_ERROR
FEATURE_NOT_SUPPORTED
DID 解析器 不支持所请求的 特性。detail 字段的值 SHOULD 提供关于解析器不支持的 特性的更长描述。
https://www.w3.org/ns/did#FEATURE_NOT_SUPPORTED

12. 绑定

本节为 4. DID 解析5. DID URL 解引用章节中的 抽象算法定义绑定。

12.1 HTTP(S) 绑定

本节定义了一个 DID 解析器 绑定, 该绑定通过 HTTP(S) 端点暴露 DID 解析 和/或 DID URL 解引用函数 (包括所有解析/解引用选项和元数据)。参见 8.2 解析器 架构

使用 HTTP(S) 解析器会产生对远程方的依赖,请求者的隐私 可能会因包含各种 HTTP 标头而降低,例如 RefererOriginCookiesAuthorization。此外, 客户端DID 解析器 之间某个组件的缓存 可能会进一步降低请求的隐私性。

HTTP(S) 绑定需要一个已知的 HTTP(S) URL,可在该 URL 调用 DID 解析器。此 URL 称为 DID 解析器 HTTP(S) 端点

此绑定通常被视为 远程绑定,但如果 HTTP(S) 端点运行在 本地环境中,例如 localhost 上,也可以是 本地绑定

所有 一致性 DID 解析器 MUST 实现 HTTPS 绑定的 GET 版本, 并且 MAY 实现 POST 版本。所有 HTTPS 绑定 MUST 使用 TLS。不 REQUIRED 在证书中使用 DNS 名称; 解析器 MAY 使用为 IP 地址签发的 TLS 证书。

使用此绑定, DID 解析函数(见 4. DID 解析)和/或 DID URL 解引用函数 (见 5. DID URL 解引用)可以 按如下方式执行:

  1. 使用 DID 解析器 HTTP(S) 端点初始化一个 request HTTP(S) URL
    https://resolver.example/1.0/identifiers/
  2. 对于 DID 解析函数:
    1. input DID 追加到 request HTTP(S) URL
      https://resolver.example/1.0/identifiers/did:example:1234
    2. Accept HTTP request header 设为 application/did-resolution,以请求完整的 9. DID 解析 结果,或者
    3. Accept HTTP request header 设为 accept resolution option 的值,以 仅请求结果中的 didDocument 值。
  3. 对于 DID URL 解引用函数:
    1. input DID URL 追加到 request HTTP(S) URL
      https://resolver.example/1.0/identifiers/did:example:1234?service=files&relativeRef=/resume.pdf
    2. Accept HTTP request header 设为 application/did-url-dereferencing,以请求完整的 10. DID URL 解引用结果,或者
    3. Accept HTTP request header 设为 accept dereferencing option 的值,以仅请求结果中的 contentStream 值。
  4. 对于 HTTP(S) GET 绑定:
    1. 如果提供了除 accept 以外的任何其他 resolution optionsdereferencing options
      1. input DID MUST 进行 URL 编码(如 RFC3986 第 2.1 节所规定)。
      2. 将除 accept 以外的所有 resolution options 编码为 request HTTP(S) URL 中的查询参数。
    2. request HTTP(S) URL 上执行 HTTP GET 请求。这会调用远程 DID 解析器上的 DID 解析DID URL 解引用函数。
      GET https://resolver.example/1.0/identifiers/did%3Aexample%3A1234?option1=value1&option2=value2 HTTP/1.1
      Accept: application/did-resolution
      GET https://resolver.example/1.0/identifiers/did%3Aexample%3A1234%3Fservice%3Dfiles%26relativeRef%3D%2Fresume.pdf?option1=value1&option2=value2 HTTP/1.1
      Accept: application/did-url-dereferencing
  5. 对于 HTTP(S) POST 绑定:
    1. 如果提供了除 accept 以外的任何其他 resolution optionsdereferencing options
      1. 将除 accept 以外的所有 resolution options 编码为 HTTP 请求的 POST 正文中的 JSON 结构。
    2. request HTTP(S) URL 上执行 HTTP POST 请求。这会调用远程 DID 解析器上的 DID 解析DID URL 解引用函数。
      POST https://resolver.example/1.0/identifiers/did:example:1234 HTTP/1.1
      Accept: application/did-resolution
      
      {
      "option1": "value1",
      "option2": "value2"
      }
      POST https://resolver.example/1.0/identifiers/did:example:1234?service=files&relativeRef=/resume.pdf HTTP/1.1
      Accept: application/did-url-dereferencing
      
      {
      "option1": "value1",
      "option2": "value2"
      }
  6. 如果 DID 解析DID URL 解引用函数在 didResolutionMetadatadereferencingMetadata 中返回 error 元数据属性,则 HTTP 响应状态码 MUST 根据下表 对应于 error objecttype 属性:
    error type URI HTTP 状态码
    https://www.w3.org/ns/did#INVALID_DID 400
    https://www.w3.org/ns/did#INVALID_DID_URL 400
    https://www.w3.org/ns/did#INVALID_OPTIONS 400
    https://www.w3.org/ns/did#NOT_FOUND 404
    https://www.w3.org/ns/did#REPRESENTATION_NOT_SUPPORTED 406
    https://www.w3.org/ns/did#INVALID_DID_DOCUMENT 500
    https://www.w3.org/ns/did#METHOD_NOT_SUPPORTED 501
    https://www.w3.org/ns/did#FEATURE_NOT_SUPPORTED 501
    https://www.w3.org/ns/did#INTERNAL_ERROR 500
    (任何其他错误 URI) 500
  7. 如果 DID 解析DID URL 解引用函数在 didDocumentMetadatacontentMetadata 中返回值为 truedeactivated 元数据属性:
    1. HTTP 响应状态码 MUST410
  8. 对于 DID 解析函数:
    1. 如果 Content-Type HTTP response header 的值是 application/did-resolution
      1. HTTP body MUST 包含一个 DID 解析结果(见 9. DID 解析结果),该结果是 DID 解析 函数的结果。
    2. 如果函数成功并返回 didDocument
      1. HTTP 响应状态码 MUST200
      2. HTTP 响应 MUST 包含一个 Content-Type HTTP response header。其值 MUSTdidResolutionMetadatacontentType 元数据属性的值(见 4.2 DID 解析元数据)。
      3. HTTP 响应正文 MUST 包含 DID 解析 函数结果中的 didDocument,并使用 与 Content-Type HTTP response header 对应的 表示。
  9. 对于 DID URL 解引用函数:
    1. 如果 Content-Type HTTP response header 的值 是 application/did-url-dereferencing
      1. HTTP body MUST 包含一个 DID URL 解引用结果 (见 10. DID URL 解引用结果),该结果是 DID URL 解引用函数的结果。
    2. 如果函数成功并返回 contentStream,并且 dereferencingMetadata 中的 contentType 元数据属性 值为 text/uri-list
      1. HTTP 响应状态码 MUST303
      2. HTTP 响应 MUST 包含一个 Location 标头。此标头的值 MUSTselected DID service endpoint URL
      3. HTTP 响应正文 MUST 为空。
    3. 如果函数成功并返回具有任何其他 contentTypecontentStream
      1. HTTP 响应状态码 MUST200
      2. HTTP 响应 MUST 包含一个 Content-Type HTTP response header。其值 MUSTdereferencingMetadatacontentType 元数据属性的值(见 5.2 DID URL 解引用元数据)。
      3. HTTP 响应正文 MUST 包含 DID URL 解引用函数结果中的 contentStream,并使用 与 Content-Type HTTP response header 对应的表示。

参见此处,了解与 HTTP(S) 绑定对应的 OpenAPI 定义。

12.2 DID 解析示例

给定以下 DID 解析器 HTTP(S) 端点

https://resolver.example/1.0/identifiers/

并给定以下 input DID

did:example:123

request HTTP(S) URL 为:

https://resolver.example/1.0/identifiers/did:example:123

12.2.1 示例: 返回 DID 解析结果

resolve() 函数可以通过 HTTP(S) 绑定按如下方式调用:

示例 30:通过 HTTP(S) 绑定向 DID 解析器发出的示例请求
GET https://resolver.example/1.0/identifiers/did:example:123 HTTP/1.1
Accept: application/did-resolution

响应如下:

示例 31:来自 DID 解析器并经由 HTTP(S) 绑定的示例响应
HTTP 200 OK
Content-Type: application/did-resolution

{
	"didDocument": {
		"@context": [ "https://www.w3.org/ns/did/v1.1" ],
		"id": "did:example:123",
		"verificationMethod": [{
			...
		}],
		"service": [{
			...
		}]
	},
	"didResolutionMetadata": {
		"contentType": "application/did"
	},
	"didDocumentMetadata": {
		...
	}
}

12.2.2 示例:返回 DID 文档

resolve() 函数可以通过 HTTP(S) 绑定按如下方式调用:

示例 32:通过 HTTP(S) 绑定向 DID 解析器发出的示例请求
GET https://resolver.example/1.0/identifiers/did:example:123 HTTP/1.1
Accept: application/did

响应如下:

示例 33:来自 DID 解析器并经由 HTTP(S) 绑定的示例响应
HTTP 200 OK
Content-Type: application/did

{
	"@context": [ "https://www.w3.org/ns/did/v1.1" ],
	"id": "did:example:123",
	"verificationMethod": [{
		...
	}],
	"service": [{
		...
	}]
}

12.3 DID URL 解引用 示例

12.3.1 示例:返回 DID URL 解引用结果

dereference() 函数可以通过 HTTP(S) 绑定按如下方式调用:

示例 34:通过 HTTP(S) 绑定向 DID URL 解引用器发出的示例请求
GET https://resolver.example/1.0/identifiers/did:example:123?versionId=2 HTTP/1.1
Accept: application/did-url-dereferencing

响应如下:

示例 35:来自 DID URL 解引用器 并经由 HTTP(S) 绑定的示例响应
HTTP 200 OK
Content-Type: application/did-url-dereferencing

{
	"content": {
		"@context": [ "https://www.w3.org/ns/did/v1.1" ],
		"id": "did:example:123",
		"verificationMethod": [{
			...
		}],
		"service": [{
			...
		}]
	},
	"dereferencingMetadata": {
		"contentType": "application/did"
	},
	"contentMetadata": {
		...
	}
}

12.3.2 示例:返回 资源

dereference() 函数可以通过 HTTP(S) 绑定按如下方式调用:

示例 36:通过 HTTP(S) 绑定向 DID URL 解引用器发出的示例请求
GET https://resolver.example/1.0/identifiers/did:example:123?versionId=2 HTTP/1.1
Accept: application/did

响应如下:

示例 37:来自 DID URL 解引用器 并经由 HTTP(S) 绑定的示例响应
HTTP 200 OK
Content-Type: application/did

{
	"@context": [ "https://www.w3.org/ns/did/v1.1" ],
	"id": "did:example:123",
	"verificationMethod": [{
		...
	}],
	"service": [{
		...
	}]
}

13. 安全考量

本节包含各种安全考量,建议在生产环境中使用 DID 解析的人予以考虑。建议读者在阅读本节之前,先 熟悉 去中心化标识符规范的安全考量章节 中提供的一般安全建议。

13.1 身份验证/授权

DID 解析DID URL 解引用不 涉及任何身份验证或授权功能。类似于 DNS 解析,任何人都可以执行该过程,而无需任何凭证 或非公开知识。

13.2 缓存

DID 解析器可以 维护一个通用的 DID 文档缓存。它 也可以维护特定于某些 DID 方法的缓存。

noCache 解析选项可用于请求 某种缓存行为。

resolution optionOPTIONAL

此属性的可能值为:

缓存行为可以通过 DID 解析器的配置、 noCache 解析选项、DID 文档的内容(例如 cacheMaxTtl 字段),或这些 属性的组合来控制。

实现 noCache 的解析器可能更容易受到拒绝 服务攻击,因为恶意客户端可以绕过缓存来强制 代价高昂的网络请求和资源消耗。使用 noCache 请求解析的客户端预期某些 解析器会拒绝绕过缓存的解析请求。 拒绝无缓存解析的解析器 MUSTFEATURE_NOT_SUPPORTED 错误响应,并明确说明 不允许绕过缓存,以便客户端可以尝试 不使用 noCache 进行解析。

13.3 JSON-LD 上下文完整性

如果从远程位置获取 JSON-LD Context 文件,攻击者可能会篡改该上下文 文件(例如,通过攻陷服务器 或通过中间人攻击拦截请求)。

因此,强烈建议任何执行远程检索 JSON-LD Context URL 的 DID 解析器使用上下文文件及其对应哈希的注册表 (或功能等效机制),以帮助确保 端到端安全。预期实现会在 资源的密码学哈希值与预期哈希值不匹配时抛出错误。

13.4 版本控制

如果提供了 versionIdversionTime DID 参数,则 DID 解析算法会返回 DID 文档的特定版本。

DID 参数 versionIdversionTime 互斥。

versionId DID 参数的使用是特定于 DID 方法的。其可能值可 包括顺序编号、随机 UUID、内容哈希等。

DID 文档元数据 MAY 包含一个 versionId 属性, 该属性会随着对 DID 文档执行的每次 Update 操作而变化。

虽然大多数 DID 方法支持 Update 操作,但并不要求 DID 方法保留所有以前的 DID 文档 版本,因此并非所有 DID 方法 都支持版本控制。

13.5 VDR 网络分叉

使用分布式系统(例如 分布式账本)作为 VDR(可验证数据注册表)的 DID 方法 需要管理 网络分叉可能发生的潜在情况。因此,使用 分布式系统作为 VDR 的 DID 方法规范 SHOULD 指定一种方式,以便将其使用的 VDR 与此类 分叉区分开来。

13.6 解引用循环

DID URL 解引用器客户端解引用 DID 文档中的标识符 和链接资源时——尤其是 verificationMethodcontrolleralsoKnownAs 等字段——可能会遇到 解引用循环。当 DID 文档 引用另一个 DID(或 URL),并且该引用最终 又指回先前已解引用的标识符,从而形成 循环时,可能会发生这种情况。DID URL 解引用器在解引用引用 DID 服务端点DID URL时, 也可能遇到此类情况。

did:example:alice
	└── verificationMethod.controller → did:example:bob
		└── verificationMethod.controller → did:example:alice

执行递归解引用的 DID URL 解引用器及其客户端应当预期、检测并处理 此类循环

安全和性能风险:如果未检测并缓解 循环,递归解引用可能导致:

缓解指导:鼓励递归跟随外部 DID 文档引用的组件 跟踪已经解引用过的标识符, 并检测循环何时发生,然后采取适当行动。 此外,开发者可能希望限制递归深度或广度, 以减少潜在攻击面。

13.7 查询字符串 规范化与注入风险

本节为非规范性内容。

DID URL 的查询组件用于传递影响解析和解引用行为的 DID 参数(见 3. DID 参数)。查询字符串处理的若干 方面具有安全含义,建议实现者仔细考虑。

13.7.1 通过 relativeRef 进行路径遍历

relativeRef DID 参数经百分号解码后的值,会使用 RFC3986 第 5 节中定义的引用解析算法,以 serviceEndpoint URL 作为基 URI 进行组合,从而构造最终 资源 URL(见 5.4.1 解引用资源)。如果 relativeRef 的值包含路径遍历序列,攻击者可能能够 使解引用器构造一个逃逸出服务端点预期 路径范围的资源 URL。

路径遍历可能使用多种编码方式尝试。以下是 攻击者可能使用的序列的非详尽示例:

  • 字面 dot-dot-slash:../
  • 百分号编码变体:%2E%2E%2F%2E%2E/、.%2E/%2E./
  • 双重编码变体:%252E%252E%252F
  • 平台特定变体(例如,Windows 衍生路径库中的 ..\

鼓励实现者:

  • 在应用 RFC3986 第 5 节 引用解析算法后,对已解析路径进行规范化,并验证生成路径不会 遍历到服务端点 URL 基路径之上。
  • 将经规范化后会产生路径不以 serviceEndpoint URL 基路径为前缀的 资源 URL 的 relativeRef 值视为 无效输入,例如通过返回 INVALID_DID_URL 错误(见 11. 错误)。
  • 在完全百分号解码后应用规范化和验证,以防范 编码后的遍历变体。表层字符串匹配(例如仅检查 字面字符串 ../)并不是可靠的遍历检测机制。
: relativeRef 解析循环

当服务端点 URL 本身是一个会被递归解引用的 DID URL 时,此问题尤为严重。在这种情况下, relativeRef 中的遍历序列可能会影响与预期不同的 DID 文档的解析。 另请参见 13.6 解引用循环

13.7.2 作为缓存绕过向量的规范化不一致

3.2 查询 规范化中所述,同一逻辑 DID URL 可以由多个语法上 不同的字符串表示。在代理或多组件解析架构中(见 8.2.2 代理 解析),不同组件可能应用不同的 规范化规则(或完全不规范化)。

了解组件之间规范化不一致的攻击者可能会:

  • 构造一个由某个组件从缓存提供、但由另一个 组件从 可验证数据 注册表重新解引用的 DID URL,从而可能绕过与缓存 响应相关的内容完整性检查。
  • 使两个逻辑上相同的 DID URL被缓存为 不同条目,膨胀缓存大小,并可能导致缓存 耗尽。
  • 利用缓存代理与 上游解析器之间不同的重复参数处理方式,向解析 请求中注入意外的参数值。

为缓解这些风险,鼓励实现者:

  1. 在解析流水线的最外层入口点应用查询字符串规范化(按照 3.2 查询规范化),并在任何缓存或 转发发生之前完成。
  2. 使用 DID URL 的规范化形式作为缓存键, 并记录所应用的规范化算法。
  3. 避免假定从上游 组件接收的 DID URL 已经规范化;在 处理前应用独立规范化是一种更安全的做法。

13.7.3 通过拼接进行参数 注入

通过字符串拼接以编程方式构造 DID URL 的实现 (例如,将调用者提供的值追加为 DID 参数)如果在拼接前未验证并编码输入, 可能容易受到参数注入攻击。

例如,调用者提供的 servicefiles&versionId=2 如果在未编码的情况下拼接,可能会向 DID URL 中注入额外的 versionId 参数, 从而以调用者可能并未预期或授权的方式 改变解析行为。这类似于基于 HTTP 的系统中的查询字符串 注入漏洞。

鼓励实现者在将所有调用者提供的参数 值拼接到 DID URL 查询字符串之前,按照 RFC3986 第 2.1 节对其进行百分号编码,并 验证参数值在 解码后符合本规范中 该参数的预期值格式(见 3. DID 参数)、适用 DID 方法规范或 DID Document Resolution Extensions [DID-EXTENSIONS-RESOLUTION] 中的定义。

14. 隐私考量

本节详细说明 DID 解析特有的隐私考量。 建议读者在阅读本节之前,先熟悉 去中心化标识符规范受控标识符规范 的隐私考量章节中提供的一般隐私建议。

14.1 DID 解析和解引用请求者的画像分析

DID 解析器DID URL 解引用器将能够 记录其服务收到的解析和解引用请求。随着时间推移, 这些日志可用于跟踪请求这些服务的客户端并为其画像。 为缓解此隐私风险,客户端应向其信任的服务发出此类请求, 例如,因为存在既有业务 关系,或因为该服务运行在其控制的基础设施上。

客户端还可以采取步骤混淆其向服务发出的请求,以降低 关联和画像分析的可能性。混淆技术 包括 Oblivious HTTP、使用可信代理执行解析 请求,以及使用可信缓存。

14.2 特定方法的 考量

不同 DID 方法会根据方法的设计决策和底层 VDR 具有不同的额外隐私影响和考量。 建议实现者审查其打算支持的 特定 DID 方法的隐私考量。鼓励 DID 方法设计者遵循 W3C 威胁建模指南 来生成威胁模型,以帮助实现者理解方法设计的 隐私影响。

A. 与其他技术的关系

在 Internet 上将标识符解析为地址时,最常用的机制之一是 [RFC1034] 中描述的全局域名系统(DNS)。 DNS 以及用于将域名映射到互联网 协议地址的过程和系统,是托管网站的常见要求。

去中心化标识符 (DID)v1.0 规范引入了一种新型标识符,它不依赖 全局域名系统,并引入了一个不要求架构中任何 部分中心化的标识符解析过程概念。这种新架构允许 以去中心化方式创建和管理可全局解析的标识符, 以对抗标识符寻租和审查。它使个人能够完全拥有并 控制自己的标识符,而不是从第三方租用标识符。

获得 DID URL 的个人,会在其软件中使用它们,方式与继续 使用基于 DNS 的 URL 十分相似。软件使用 DID 解析器接口 (在本规范中定义)来确定要检索资源的位置。 DID 解析过程与 DNS 解析过程非常相似,对个人而言是不透明的,并在软件内部发生, 不需要个人直接参与。

与 DNS 中心化以及相应发明 DIDDID 解析相关的研究, 由 去中心化标识符(DID)v1.0 规范中 与 DID 历史相关的章节记录。

B. DID 解析资源

  1. DID Core 规范中的 DID 解析器
  2. Universal Resolver
  3. did-client
  4. uPort DID 解析器

C. 参考文献

C.1 规范性参考文献

[CID]
受控标识符 v1.0。Michael Jones;Manu Sporny。W3C。2025 年 5 月 15 日。W3C 推荐标准。URL:https://www.w3.org/TR/cid-1.0/
[DID-CORE]
去中心化标识符(DID)v1.0。 Manu Sporny;Amy Guy;Markus Sabadello;Drummond Reed。W3C。2022 年 7 月 19 日。W3C 推荐标准。URL: https://www.w3.org/TR/did-core/
[INFRA]
Infra 标准。Anne van Kesteren;Domenic Denicola。WHATWG。现行标准。URL:https://infra.spec.whatwg.org/
[RFC2046]
多用途互联网邮件扩展 (MIME)第二部分:媒体类型。N. Freed;N. Borenstein。IETF。1996 年 11 月。标准 草案。URL:https://www.rfc-editor.org/info/rfc2046/
[RFC2119]
用于在 RFC 中指示 要求级别的关键词。S. Bradner。IETF。1997 年 3 月。最佳当前实践。URL:https://www.rfc-editor.org/info/rfc2119/
[RFC3986]
统一资源标识符(URI):通用 语法。T. Berners-Lee;R. Fielding;L. Masinter。IETF。2005 年 1 月。互联网 标准。URL:https://www.rfc-editor.org/info/rfc3986/
[RFC3987]
国际化资源标识符 (IRI)。M. Duerst;M. Suignard。IETF。2005 年 1 月。提议标准。URL:https://www.rfc-editor.org/info/rfc3987/
[RFC8174]
RFC 2119 关键词中大写与小写的 歧义。B. Leiba。IETF。2017 年 5 月。最佳当前实践。URL:https://www.rfc-editor.org/info/rfc8174/
[RFC9110]
HTTP 语义。R. Fielding,编辑; M. Nottingham,编辑;J. Reschke,编辑。IETF。2022 年 6 月。互联网标准。URL:https://httpwg.org/specs/rfc9110.html
[RFC9457]
HTTP API 的问题详情。 M. Nottingham;E. Wilde;S. Dalal。IETF。2023 年 7 月。提议标准。URL:https://www.rfc-editor.org/info/rfc9457/
[VC-DATA-MODEL]
可验证凭证数据模型 v2.0。Ivan Herman;Michael Jones;Manu Sporny;Ted Thibodeau Jr;Gabe Cohen。W3C。 2025 年 5 月 15 日。W3C 推荐标准。URL:https://www.w3.org/TR/vc-data-model-2.0/

C.2 资料性参考文献

[DID-EXTENSIONS-PROPERTIES]
DID 文档属性 扩展。Manu Sporny;Markus Sabadello。W3C。2025 年 12 月 11 日。W3C 工作 组说明。URL:https://www.w3.org/TR/did-extensions-properties/
[DID-EXTENSIONS-RESOLUTION]
DID 解析 扩展。Manu Sporny;Markus Sabadello。W3C。2024 年 11 月 19 日。W3C 工作 组说明。URL:https://www.w3.org/TR/did-extensions-resolution/
[DID-KEY]
did:key 方法。Manu Sporny; Dmitri Zagidulin;Dave Longley。2025 年 3 月 26 日。社区组草案。URL:https://w3c-ccg.github.io/did-key-spec/
[KERI]
密钥事件收据基础设施(KERI)。 Samuel M. Smith。2019 年 7 月。URL:https://arxiv.org/abs/1907.02143
[RFC1034]
域名——概念与 功能。P. Mockapetris。IETF。1987 年 11 月。互联网标准。URL:https://www.rfc-editor.org/info/rfc1034/
[RFC4122]
通用唯一标识符(UUID)URN 命名空间。P. Leach;M. Mealling;R. Salz。IETF。2005 年 7 月。提议标准。 URL:https://www.rfc-editor.org/info/rfc4122/
[RFC7231]
超文本传输协议(HTTP/1.1): 语义与内容。R. Fielding,编辑;J. Reschke,编辑。IETF。2014 年 6 月。 提议标准。URL:https://httpwg.org/specs/rfc7231.html