Copyright © 2026 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
去中心化标识符(DID)解析是为特定 DID 获取 DID 文档及随附元数据的过程。该过程以一个 DID 和一组选项作为输入,并返回一个 DID 文档以及 有关已解析文档和解析请求的相关元数据。已解析的 DID 文档 是一组信息,可支持与 DID 主体进行可通过密码学验证的 交互,包括密码学公钥等机制。本规范涵盖 DID 解析所使用的算法和指南,并依赖于核心 DID 规范 去中心化 标识符(DID)v1.0,该规范完整详细地描述了底层 DID 架构。
本节描述本文档在发布时的状态。当前 W3C 出版物列表以及本技术报告的最新修订版可在 W3C 标准和草案 索引中找到。
欢迎就本文档提出意见。请直接在 GitHub 上提交议题,或将 意见发送至 public-did-wg@w3.org (订阅, 归档)。
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 流程文档管辖。
DID 解析是为给定 DID 获取 DID 文档 的过程。这是可对任何 DID 执行的四项必需 操作之一(“读取”;其他操作为 “创建”、“更新”和“停用”)。这些操作的细节会因 DID 方法而异。在 DID 解析的基础上,DID URL 解引用是为给定 DID URL 检索资源 表示的过程。能够执行这些过程的软件 和/或硬件称为 DID 解析器。
本规范定义了一个标准接口,客户端可使用该接口来执行 DID 解析和 DID URL 解引用请求,而不依赖于 DID 解析器 所支持的任何特定 DID 方法的 “Resolve” 操作。此外,本规范还定义了实现 DID 解析器或 DID URL 解引用器时相关的要求、 算法(包括其输入和结果)、架构选项,以及 各种安全和隐私考量。
请注意,虽然本规范为 DID 解析定义了一些基础级功能,但与 DID 的 可验证数据 注册表通信所需的实际步骤由适用的 DID 方法规范定义。
本节为非规范性内容。
通过使用标准 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 方法上的正确解析行为。
除标记为非规范性的章节外,本规范中的所有编写指南、图表、示例和注释均为非规范性内容。除此之外,本规范中的所有内容均为规范性内容。
本文档中的关键词 MAY、MUST、MUST NOT、NOT REQUIRED、OPTIONAL、RECOMMENDED、REQUIRED 和 SHOULD 应按 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) 绑定中的规范性陈述。
本节为非规范性内容。
本规范有三类主要受众:一致性 DID 方法的实现者;一致性 DID 解析器的实现者;以及希望使用 DID 解析器 解析 DID 的系统和服务实现者。预期 受众包括但不限于软件架构师、数据建模人员、 应用开发人员、服务开发人员、测试人员、运维人员以及用户 体验(UX)专家。参与去中心化身份、可验证凭证和安全 存储相关广泛标准化工作的其他人员也可能有兴趣阅读本规范。
本节为非规范性内容。
DID 解析规范旨在通过定义标准化接口来支持广泛的用 例,该接口可独立于任何特定 DID 的 DID 方法来解析 DID 并解引用 DID URL。这些用例 包括:
本节定义了本规范以及整个 去中心化标识符 基础设施中使用的术语。每当这些术语在本规范中出现时, 都会包含指向这些术语的链接。
一组参数,可与某个过程一起使用,以独立 验证证明。例如,密码学公钥可作为 数字签名的验证方法;在这种用法中,它 验证签名者拥有相关联的密码学私钥。
此定义中的“验证”和“证明”旨在作广义理解。例如, 密码学公钥可在 Diffie-Hellman 密钥 交换期间用于协商用于加密的共享对称密钥。这保证了 密钥协商过程的完整性。因此,即使对该过程的描述可能不使用 “验证”或“证明”这些词,它也是另一类验证 方法。
DID URL 语法支持 一种简单的参数格式(见 [DID-CORE] 中的 Query 一节)。向 DID URL 添加 DID 参数,意味着该参数 成为 资源标识符的一部分。
did:example:123?versionTime=2021-05-10T17:00:00Z
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 文档的最新
版本。如果存在,关联值 MUST
以 3.1 日期时间
中定义的日期时间格式表示。
|
实现者以及 DID 方法规范作者 可以使用此处未列出的其他 DID 参数。为实现最大 互操作性,RECOMMENDED DID 参数使用 DID Document Properties Extensions 机制 [DID-EXTENSIONS-PROPERTIES],以避免 与同一 DID 参数在不同语义下的其他用法发生 冲突。
可以通过向 DID 解析器或DID URL 解引用器传递 DID 解析选项或 DID URL 解引用选项,来影响DID 解析和 DID URL 解引用函数。此类 选项不是DID或 DID URL的一部分。这与 HTTP 类似,在 HTTP 中, 某些参数既可以包含在 HTTP URL 中,也可以 在解引用过程中作为 HTTP 标头传递。
本规范中的所有日期时间值 MUST 是一个
ASCII
字符串,且是
[VC-DATA-MODEL] 在
可验证凭证数据模型
v2.0中定义的有效 XML 日期时间值。
此外,DID Resolution 中使用的时间戳 MUST 调整为
UTC,且不得具有亚秒十进制精度。例如:
2020-12-20T19:17:47Z
DID URL 查询字符串 通常会在解析流水线中的多个独立组件之间被构造、解析、 记录、缓存和比较——例如客户端、缓存代理、下游 解析器以及 DID 方法特定解析器(见 8.2 解析器 架构)。这些组件之间对 DID URL 查询字符串 的规范化不一致,可能会 悄然产生错误的解析结果、缓存污染或破坏 互操作性。本节列举了鼓励实现者和 DID 方法规范作者明确处理的边界情形。
本节中的指南涉及如何为 解析、比较和转发的目的规范化 DID URL 查询字符串。它不同于 哪些参数应作为解析选项传递、哪些应 嵌入到 DID URL 中这一问题;该问题已在 3. DID 参数末尾关于 DID 参数与解析选项区别的注释中处理。
本节为非规范性内容。
DID URL 查询 字符串中字符的百分号编码不会改变被标识资源的身份,但 同一逻辑值的不同编码可能会被执行朴素字符串比较的实现 视为不同字符串。
鼓励比较、缓存或转发 DID URL 的实现,在比较或存储之前 规范化百分号编码。以下规则 与 RFC3986 第 6.2.2 节:基于语法的规范化一致, 可作为基线:
%2F 而不是 %2f)。
%26 表示 &,%3D 表示
=),因为这样做会
改变查询字符串的已解析结构。
鼓励 DID 方法规范记录其 方法特定 DID 参数中哪些字符可在规范化期间安全解码。
relativeRef DID 参数值通常会包含百分号编码的
路径分隔符和查询字符(例如
relativeRef=%2Fresume.pdf%3Fversion%3D2)。避免将这些字符作为
查询级规范化的一部分进行解码,因为编码形式是有意的,并且对于
该值在解引用期间被正确解释为相对引用是必要的
(见解引用资源)。
DID URL 语法
并不禁止在单个 DID URL 中重复出现
同一个查询参数名(例如
did:example:123?service=files&service=agent)。当存在重复参数时,
解析和解引用函数的行为在其他方面未由本文档规定。
鼓励实现者定义并记录其实现
在 DID URL 包含重复查询
参数名时的行为。由于本规范中定义的所有 DID 参数都具有
标量值(见 3. DID
参数),因此这些参数的任何重复出现都表示
一个歧义输入,没有明确定义的
解析行为。一种合理做法是将这样的
DID URL 视为无效,
并返回 INVALID_DID_URL 错误
(见 11. 错误)。
鼓励定义方法特定查询参数的 DID 方法规范 明确说明这些参数是否允许重复出现, 若允许,则定义解析语义(例如第一个值 优先、最后一个值优先、集合并集)。
3. DID 参数中定义的查询参数集合并非 穷尽。DID 方法可以定义其他方法特定查询参数, 而这些参数的规范形式(包括其名称、值 格式和顺序)可能因方法而异。
鼓励 DID 方法规范为其定义的任何 方法特定查询参数指定规范形式,涵盖以下 考量:
需要测试两个 DID URL 逻辑等价性的实现(例如,用于 缓存查找)在应用 3.2.1 百分号编码规范化所述的百分号编码 规范化之后,鼓励采用与参数顺序无关的比较, 除非适用的 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 函数的输入变量如下:
resolve 函数的
输入选项组成,并且包含
did 本身之外的内容。此结构在
4.1 DID 解析
选项中进一步定义。此输入是 REQUIRED,但该
结构 MAY 为空。
此函数返回多个值,且不限制
这些值如何一起返回。
resolve 的返回值为 didResolutionMetadata、
didDocument 和 didDocumentMetadata。
这些值说明如下:
error 属性。参见第 11. 错误节。
id
值 MUST 与已解析的
DID
字符串相等。如果
解析不成功,此值 MUST 为空。
didDocument 属性中所含
DID 文档的元数据。
如果解析不成功,此输出 MUST 是一个
空的 元数据结构。
此结构在 4.3 DID 文档元数据中进一步定义。
这是一个 元数据结构,其中包含 DID 解析过程的输入选项。
此结构中的可能属性及其可能值 SHOULD 注册到 DID Resolution Extensions [DID-EXTENSIONS-RESOLUTION]。 本规范定义以下常见输入选项:
Accept 标头值来表示。DID 解析器
实现 SHOULD 使用此值来确定返回的 didDocument 的
表示,
前提是此类 表示
受支持且可用。此属性是 OPTIONAL。
这是一个 元数据结构,其中包含关于 DID 解析过程的元数据。
此元数据通常会在每次调用 DID 解析 函数时发生变化,因为它表示关于 解析过程本身的数据。
此元数据的来源是 DID 解析器。
DID 解析元数据的示例包括:
contentType)。error)(见第 11. 错误节)。
此结构中的可能属性及其可能值 SHOULD 注册到 DID Resolution Extensions [DID-EXTENSIONS-RESOLUTION]。 本规范定义以下常见元数据属性:
didDocument 的媒体类型。此
属性是 OPTIONAL。如果存在,此属性的值 MUST 是
一个 ASCII 字符串,并且是
一致性 表示的媒体类型。在这种情况下,
resolve 函数的调用者 MUST 在
确定如何解析和处理 didDocument 时使用此值。
一些 DID 解析器和 DID URL 解引用器 在执行 DID 解析或 DID URL 解引用 函数时使用证明。详情见 8.2 解析器架构。
DID
解析元数据 MAY 包含 proof 属性。
如果存在,该值 MUST 是一个
集合,其中每个
项都是表示证明的 映射。此属性的使用
和证明类型与 DID
方法无关。
这是一个 元数据结构,其中包含关于 DID 解析过程的元数据。
此元数据通常不会在每次调用 DID 解析 函数时发生变化,除非 DID 文档 发生变化,因为它表示关于 DID 文档的数据。
此元数据的来源是 DID 控制者和/或 DID 方法。由 DID 控制者证明的 DID 文档元数据本身并不天然保证准确性。建议客户端在依赖 DID 文档元数据来指导业务 逻辑时谨慎行事。
DID 文档元数据的示例包括:
created、
updated、nextUpdate)。
versionId、
nextVersionId)。
proof)。
此结构中的可能属性及其可能值 SHOULD 注册到 DID Document Properties Extensions [DID-EXTENSIONS-PROPERTIES]。本 规范定义以下常见 元数据属性。
created 属性,
用于指示
Create 操作的时间戳。该
属性的值 MUST 以
3.1 日期时间中定义的日期时间格式表示。
updated 属性,用于指示已解析文档版本的最后一次
Update 操作
的时间戳。该属性的值 MUST 以 3.1 日期时间中定义的日期时间格式表示。
如果从未对该 DID
文档执行过 Update 操作,则省略
updated 属性。如果存在
updated 属性,当两个时间戳之间的差异
小于一秒时,它可以与
created 属性具有相同值。
true。如果 DID 尚未被停用,
此属性是 OPTIONAL,但如果包含,则 MUST
具有布尔值
false。
nextUpdate 属性。它表示下一次
Update 操作的时间戳。
该属性的值 MUST 以
3.1 日期时间中定义的日期时间格式
表示。
versionId 属性,用于指示已解析文档
版本的最后一次
Update 操作的版本。该属性的值
MUST 是
ASCII 字符串。
nextVersionId 属性。它表示下一次
Update 操作的版本。
该属性的值 MUST 是
ASCII 字符串。
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 属性值在逻辑上
等价。
请求方预期保留
id 和
equivalentId
属性中的值,以确保
与它们包含的任何值的后续交互
都会被正确处理为逻辑等价(例如,在数据库中保留所有
变体,以便与其中任意一个的交互都映射到同一
底层账户)。
equivalentId
是一种比
alsoKnownAs
强得多的等价形式,因为
这种等价性 MUST 由管辖性的
DID
方法保证。使用
equivalentId
意味着同一个 DID
文档
同时描述
equivalentId
DID 和
id 属性的 DID。
如果请求方不保留 id 和
equivalentId
属性中的值,并确保
与它们包含的任何值的后续交互
都被正确处理为逻辑等价,则可能会
出现负面或意外问题。强烈建议实现者
遵守与此元数据属性相关的指令。
canonicalId
属性与
equivalentId
属性相同,但有以下区别:a)
它关联的是单个值而不是一个集合;b) 该
DID 被定义为
所含 DID
文档范围内该
DID
主体的规范 ID。
DID
文档元数据 MAY 包含 canonicalId
属性。
如果存在,该值 MUST 是一个
字符串,且
符合 去中心化标识符(DID)v1.0一节中的规则。
该关系是一项声明,表示
canonicalId
值与 id 属性值在逻辑上等价,并且
该
canonicalId
值由 DID 方法
定义为所含 DID
文档范围内
DID 主体的规范
ID。一个
canonicalId
值 MUST 由与 id
属性值相同的 DID
方法产生,并且是该方法的一种形式。
(例如 did:example:abc ==
did:example:ABC)。
一致性 DID
方法规范 MUST 保证
canonicalId
值与
id 属性值在逻辑上等价。
请求方预期将
canonicalId
值用作该
DID 主体的主要
ID 值,并将所有
其他等价值视为次要别名(例如,更新
其系统中的相应主要引用,以反映新的
规范 ID 指令)。
canonicalId
与
equivalentId
是相同的等价性声明,
只是它被限制为单个值,
且该值被定义为
DID 主体在
DID
文档范围内的规范值。与
equivalentId
一样,使用
canonicalId
意味着同一个 DID
文档
同时描述
canonicalId
DID 和
id 属性的 DID。
如果解析方不将
canonicalId
值用作 DID 主体的主要
ID 值,并将所有其他等价值
视为次要别名,则可能会出现与用户体验相关的负面或意外问题。
强烈建议实现者遵守与此元数据
属性相关的指令。
许多 DID 方法在执行 方法操作时使用证明。详情见 8.1 方法 架构。
DID
文档元数据 MAY 包含
proof 属性。如果存在,该值 MUST 是一个
集合,其中每一项都是表示证明的
映射。此属性的使用
以及证明类型是
DID
方法特定的。
did 规则。
如果不符合,DID
解析器 MUST 返回以下结果:
https://www.w3.org/ns/did#INVALID_DID
null«[ ]»https://www.w3.org/ns/did#METHOD_NOT_SUPPORTED
null«[ ]»https://www.w3.org/ns/did#FEATURE_NOT_SUPPORTED
null«[ ]»https://www.w3.org/ns/did#INVALID_OPTIONS
null«[ ]»https://www.w3.org/ns/did#NOT_FOUND
null«[ ]»«[ ... ]»null«[ "deactivated" → true, ... ]»
true 的 expandRelativeUrls 选项:
id 属性的值是
相对 DID URL,
或者如果某个
验证
关系是
相对 DID URL:
«[ ... ]»«[ "contentType" → output DID document media
type, ... ]»
如果 DID 解析器 在执行 DID 解析算法期间 遇到任何意外错误,它 MUST 返回以下 结果:
https://www.w3.org/ns/did#INTERNAL_ERROR
null«[ ]»整个章节当前存在风险,并且很可能会被大幅修改或 从本规范中移除。工作组正在征求实现者关于 本章节 价值的反馈。
DID URL 解引用函数将一个 DID URL 解引用为一个 资源, 其内容取决于 DID URL 的各个组成部分, 包括 DID 方法、 方法特定标识符、路径、 查询和片段。此过程依赖于对 DID URL 中所含 DID 的 DID 解析。DID URL 解引用可能涉及 多个步骤(例如,当被解引用的 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 解引用器,但预期实现者参考
5. DID URL 解引用
以进一步理解关于
DID URL 预期如何被
解引用的常见模式。
dereference 函数的输入选项组成,并且包含
didUrl 本身之外的内容。此结构在
5.1 DID URL
解引用选项中进一步定义。此输入是 REQUIRED,但该
结构 MAY 为空。
此函数返回多个值,且不限制
这些值如何一起返回。
dereference 的返回值为 dereferencingMetadata、
contentStream 和 contentMetadata。
这些值说明如下:
error 属性。参见第 11. 错误节。
dereferencing 函数且成功,
此值 MUST 包含与
DID URL 对应的
资源。
contentStream MAY 是一个
资源,
例如可序列化为一种一致性
表示的
DID
文档、
验证方法、
服务,或
任何其他可通过媒体类型标识并可通过
解析过程获得的资源格式。如果解引用
不成功,此值 MUST 为空。
contentStream 的元数据。如果
contentStream
是一个 DID 文档,
则此值 MUST 是一个
didDocumentMetadata 结构,如
DID 解析中所述。如果
解引用不成功,
此输出 MUST 是一个空的 元数据
结构。此
结构在 5.3 DID URL
内容元数据中进一步定义。
一致性 DID URL
解引用实现不得以任何方式更改
这些函数的签名。
DID URL
解引用实现可以将
dereference 函数映射到特定方法的内部函数,
以执行实际的 DID URL
解引用过程。
DID URL
解引用实现除了此处指定的
dereference 函数外,还可以实现并
暴露具有不同签名的其他函数。
这是一个 元数据结构,其中包含 DID URL 解引用过程的输入选项。
此结构中的可能属性及其可能值 SHOULD 注册到 DID Resolution Extensions [DID-EXTENSIONS-RESOLUTION]。 本规范定义以下常见输入选项:
contentStream 的媒体类型。该值 MUST 按
HTTP
语义
第 12.5.1 节中定义的
Accept 标头值来表示。DID URL
解引用器
实现 SHOULD 使用此值来确定返回值中所含
表示
的
contentType,前提是此类
表示受支持且可用。
这是一个 元数据结构,其中包含关于 DID URL 解引用过程的元数据。
此元数据通常会在每次调用 DID URL 解引用函数时发生变化,因为它表示关于 解引用过程本身的数据。
此元数据的来源是 DID URL 解引用器。
此结构中的可能属性及其可能值 SHOULD 注册到 DID Resolution Extensions [DID-EXTENSIONS-RESOLUTION]。 本规范定义以下常见元数据属性:
contentStream 的媒体类型在解引用成功时 SHOULD
使用此属性来表示。该
媒体类型值 MUST 表示为
ASCII 字符串。
一些 DID 解析器和 DID URL 解引用器在执行 DID 解析或 DID URL 解引用 函数时使用证明。详情见 8.2 解析器架构。
DID URL
解引用元数据 MAY 包含
proof 属性。如果存在,该值 MUST 是一个
集合,其中每一项都是表示证明的
映射。此属性的使用
和证明类型与
DID
方法无关。
这是一个 元数据结构,其中包含关于 DID URL 解引用过程的元数据。
此元数据通常不会在每次调用 DID URL 解引用函数时发生变化,除非内容发生变化,因为它 表示关于内容的数据。
此结构中的可能属性及其可能值 SHOULD 注册到 DID Resolution Extensions [DID-EXTENSIONS-RESOLUTION]。 本规范未定义任何通用属性。
DID URL 解引用器实现以下 DID URL 解引用算法。按照 [RFC3986],它包括 以下三个步骤:解析 DID;解引用资源;以及解引用片段(仅当 input DID URL 包含 DID 片段时):
did-url
规则。
如果不符合,DID URL 解引用器
MUST 返回以下结果:
https://www.w3.org/ns/did#INVALID_DID_URL
null«[ ]»https://www.w3.org/ns/did#NOT_FOUND
null«[ ]»did:example:1234
«[ ... ]»resolved DID document
«[ resolved DID document metadata ]»
service 和/或
DID 参数 serviceType,以及
可选的 DID 参数
relativeRef:
did:example:1234?service=files&relativeRef=%2Fmyresume%2Fdoc%3Fversion%3Dlatest
service:
当 service 的
id 属性与
service DID 参数的值匹配时,选择该服务。如果
id 属性或 service DID
参数,或两者都包含相对引用,则
MUST 解析相应的绝对 URI 并使用它们来
确定匹配,使用
RFC3986 第 5 节:
引用解析以及 去中心化标识符(DID)
v1.0 中
相对 DID
URL一节所指定的规则。
serviceType:当
service 的
type 属性与
serviceType DID 参数的值匹配时,选择该服务。
relativeRef:
serviceEndpoint 属性值是
一个 映射,则跳过此
selected service。
serviceEndpoint 属性值
是一个 字符串,则将
此值添加
到
selected DID
service endpoint URLs 列表。
serviceEndpoint 属性值是
一个 集合,则将其中所有
为 字符串的项添加到
selected DID
service endpoint URLs 列表。
relativeRef 的值。
解引用一个 DID 服务端点—— 尤其是本身为 DID 的服务端点——可能导致 解引用 循环,即一组 导致无限循环的步骤。例如,一个 DID 服务端点可能通过一系列解引用过程 间接指回 先前已解引用的标识符。建议 DID URL 解引用器在递归 解引用 DID 服务端点时 检测并处理此类循环,以防止无限 循环或解引用失败。更多指导, 见 解引用 循环一节。
«[ ... ]»
resolved DID document with selected services
«[ resolved DID document metadata ]»
«[ ... ]»
« selected service endpoint URLs »
«[ "contentType" → "text/uri-list", ... ]»
https://www.w3.org/ns/did#REPRESENTATION_NOT_SUPPORTED
null«[ ]»did:example:1234/custom/path?customquery
https://www.w3.org/ns/did#NOT_FOUND
null«[ ]»如果 input DID URL 包含 DID 片段, 则片段的解引用 取决于资源的媒体类型([RFC2046]),也就是 5.4.1 解引用资源的结果。
verificationRelationship 选项:
verificationRelationship
选项的值。
did:example:1234?service=files&relativeRef=%2Fmyresume%2Fdoc%3Fversion%3Dlatest#intro
fragment 组件,则引发错误。
application/did 的 DID 文档表示,
则该片段按照
JSON-LD 1.1:application/ld+json
媒体类型 [JSON-LD11] 关联规则处理。
给定以下 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"
}
给定以下 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 解引用算法,它采用比先前算法更模块化的 方法,基于“检索 策略”或“处理策略”。
解引用 DID URL 的第一步是准备 DID 以进行 解析。这涉及验证 DID URL 语法、选择适当的 DID 解析器,并为解析请求准备 DID 及任何随附的 DID 解析选项。
下一步是选择一个 DID 解析器,并使用它以准备好的输入执行 解析 请求。这可能涉及向外部服务发出网络请求, 也可能涉及本地解析过程, 具体取决于 DID 解析器的特定实现。其 结果是一个 DID 解析结果,其中 包含已解析的 DID 文档及相关元数据,或错误信息。
成功解析 DID 文档及随附元数据之后, 下一步是确定用于检索 DID URL 所标识资源的适当策略。这涉及分析 DID 解析结果的 内容,包括 DID 文档及 其元数据,以及 DID URL 的路径和查询组件, 以确定检索该资源的方法。
下一步是使用已确定的检索策略,检索 DID URL 所标识的资源。 检索策略可以在外部 规范中定义。客户端需要自行判断其是否能够 使用指定策略检索该资源。
最后一步是在调用解引用的上下文中,使用检索到的资源来完成 DID URL 解引用过程。 这可能涉及将片段标识符应用于检索到的资源, 将生成的资源提供给调用方应用程序进程, 或者在无法完成解引用时产生错误。
输入和输出元数据通常会参与 DID 解析、DID URL 解引用以及其他 DID 相关过程。用于传达此元数据的结构 MUST 是一个 属性 映射。每个属性名 MUST 是一个 字符串。每个属性值,以及任何 复杂数据结构(例如映射或列表)中的每个值,MUST 是 字符串、数字、 映射、列表、 集合、布尔值,或 null。整个元数据结构 MUST 能够按照 [INFRA] 规范中的 JSON 序列化 规则 进行序列化。实现 MAY 将元数据结构序列化为其他数据格式。
所有使用元数据结构作为输入或输出的函数实现, 都能够以确定性的方式完整表示此处描述的所有数据类型。 由于使用元数据结构的输入和输出是根据数据类型而非其序列化来 定义的,因此 表示方法属于该函数实现的内部事项, 不在本规范范围内。
以下示例展示了一个 JSON 编码的元数据结构,它可能 用作 DID 解析选项。
{
"accept": "application/did"
}
此示例对应于以下格式的元数据结构:
«[
"accept" → "application/did"
]»
下一个示例展示了一个 JSON 编码的元数据结构,如果 未找到某个 DID, 它可能用作 DID 解析元数据。
{
"error": "notFound"
}
此示例对应于以下格式的元数据结构:
«[
"error" → "notFound"
]»
下一个示例展示了一个 JSON 编码的元数据结构,它可能 用作 DID 文档元数据,以描述 与 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"
]»
本节当前被标记为存在风险,并且很可能会被 DID 解析威胁模型中的内容取代。
DID 解析 算法涉及根据某个 DID 的 DID 方法执行其上的 Resolve 操作(见 4. DID 解析)。
每种 DID 方法都会定义此方法操作,即 DID 解析器如何 从 DID 获得 DID 文档。底层数据格式、协议、技术基础设施和过程在 各种 DID 方法之间可能 差异很大。
DID 方法考量示例包括以下内容:
基于上述考量,并结合 DID 方法的 “Resolve” 操作的性质, 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 解析器 架构。
DID 解析和 DID URL 解引用算法被定义为抽象函数(见 4. DID 解析和 5. DID URL 解引用)。
这些算法由 DID 解析器和 DID URL 解引用器实现,并由 客户端通过 绑定调用。绑定 定义了如何使用具体的编程或 通信接口访问抽象函数。
绑定示例包括以下内容:
基于上述考量,并结合绑定的性质, 客户端与 DID 解析器或 DID URL 解引用器之间的交互 可以被视为 本地绑定或 远程绑定:
在可能的情况下,优先使用 本地绑定,因为它们 最大限度减少对第三方和中介的依赖,降低安全 风险,并最大化对 DID 解析和 DID URL 解引用 函数结果完整性和正确性的信心。
在某些情况下,可能无法使用 本地绑定;例如,在受限的 IoT(物联网) 环境中,或当 DID 方法需要复杂 基础设施时,或当需要支持许多不同 DID 方法时。
DID 解析器 MAY 也可以在
DID 解析元数据的
proof 属性中包含证明。
请注意,源自 DID 解析器的证明 与 DID 方法无关,并且可由 DID 解析器 跨所有 DID 方法统一应用。这些证明有助于 在 DID 解析器本身 所关涉的范围内,验证 DID 解析 过程结果的完整性和真实性。然而,它们并不 保证适用 DID 方法的 “Resolve” 操作结果本身是 正确的。另请参见 8.1 方法架构。
DID 解析器 可能支持用于多种 DID 方法的 DID 解析 算法:
在这种情况下,8.1 方法架构中关于 可验证解析和 不可验证解析 实现的上述考量,分别适用于每个受支持的 DID 方法。
DID 解析器 MAY 调用另一个 DID 解析器, 后者作为代理执行 DID 解析 算法,如 4. DID 解析中所定义。
第一个 DID 解析器随后充当 客户端, 并选择适合的 绑定来调用第二个 DID 解析器。 例如,DID 解析器 可以通过 本地绑定(例如命令行 工具)调用,而该工具又通过 远程绑定(例如 HTTP(S) 绑定)调用另一个 DID 解析器。
使用代理解析时,“下游”解析器 SHOULD 以透明方式保留来自 “上游”解析器的所有 DID 解析元数据和 DID 文档元数据, 包括可能存在的任何证明。在此过程中,“下游”解析器 MAY 添加其自己的 DID 解析元数据, 包括关于代理解析过程本身的任何元数据。
DID URL 解引用算法的不同部分 可以由 解析器架构中的不同组件执行。
具体而言,当解引用带有 DID 片段的 DID URL 时, 解引用资源 由 DID 解析器完成,而 解引用片段 由 客户端完成。
给定 DID URL
did:xyz:1234#keys-1,可以通过
本地绑定调用
DID 解析器来
解引用资源
(即 DID
文档),而 客户端可以通过
解引用片段
(即 DID 文档的一部分)
完成
DID URL
解引用算法。
给定 DID URL
did:xyz:1234?service=agent&relativeRef=%2Fsome%2Fpath%3Fquery#frag,
可以调用 DID 解析器
来
解引用资源
(即 DID
服务端点 URL),而 客户端可以通过
解引用片段
(即带有片段的 DID
服务端点 URL)
完成
DID URL
解引用算法。
给定 DID URL
did:xyz:1234#keys-1,可以通过
本地绑定调用
DID 解析器,该解析器又通过
远程绑定调用另一个
DID
解析器来
解引用资源
(即 DID
文档),而 客户端可以通过
解引用片段
(即 DID 文档的一部分)
完成
DID URL
解引用算法。
本节定义了一个 JSON 数据结构,用于表示 4. DID 解析中所述算法的结果。 DID 解析结果包含 DID 文档,以及 DID 解析元数据和 DID 文档元数据。
此数据结构的媒体类型定义为
application/did-resolution。
{
"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"
}
}
}
}
本节当前被标记为存在风险,并且可能会在候选推荐阶段 被大幅修改或从本规范中移除。
本节定义了一个 JSON 数据结构,用于表示 5. DID URL 解引用中所述算法的结果。 DID URL 解引用结果包含内容,以及 DID URL 解引用元数据 和 DID URL 内容元数据。
此数据结构的媒体类型定义为
application/did-url-dereferencing。
{
"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"
}
}
}
}
本规范中描述的算法会抛出特定类型的错误。 实现者可能会发现,将这些错误传达给其他库或 软件系统很有用。本节为这些错误提供特定 URL 和描述, 以便实现本规范所述技术的生态系统 在发生错误时可以更有效地互操作。 此外,本规范还使用 [CID] 规范的 第 3.5 节 处理错误 中定义的一些错误。
实现者 SHOULD 使用 [RFC9457] 来编码错误 数据结构。如果使用 [RFC9457]:
type 值 MUST 是一个 URL。若下方章节
中列出的值未定义 URL,则这些值 MUST 以前缀
URL
https://www.w3.org/ns/did# 开头。
title 值 SHOULD 提供一个简短但具体的人类可读
错误字符串。
detail 值 SHOULD 为错误提供一个更长的人类可读字符串。
https://www.w3.org/ns/did#INVALID_DIDhttps://www.w3.org/ns/did#INVALID_DID_DOCUMENThttps://www.w3.org/ns/did#NOT_FOUNDaccept DID URL 解引用选项请求的
表示不受
DID 方法和/或
DID URL
解引用器实现支持。参见
5.4 DID URL 解引用
算法。
https://www.w3.org/ns/did#REPRESENTATION_NOT_SUPPORTED
https://www.w3.org/ns/did#INVALID_DID_URLhttps://www.w3.org/ns/did#METHOD_NOT_SUPPORTEDhttps://www.w3.org/ns/did#INVALID_OPTIONShttps://www.w3.org/ns/did#INTERNAL_ERRORdetail 字段的值 SHOULD 提供关于解析器不支持的
特性的更长描述。
https://www.w3.org/ns/did#FEATURE_NOT_SUPPORTED
本节为 4. DID 解析和 5. DID URL 解引用章节中的 抽象算法定义绑定。
本节定义了一个 DID 解析器 绑定, 该绑定通过 HTTP(S) 端点暴露 DID 解析 和/或 DID URL 解引用函数 (包括所有解析/解引用选项和元数据)。参见 8.2 解析器 架构。
使用 HTTP(S) 解析器会产生对远程方的依赖,请求者的隐私
可能会因包含各种 HTTP 标头而降低,例如
Referer、Origin、Cookies 和
Authorization。此外,
客户端与
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 解引用)可以 按如下方式执行:
https://resolver.example/1.0/identifiers/
https://resolver.example/1.0/identifiers/did:example:1234
Accept HTTP request header 设为
application/did-resolution,以请求完整的
9. DID 解析
结果,或者
Accept HTTP request header 设为
accept resolution option 的值,以
仅请求结果中的 didDocument 值。
https://resolver.example/1.0/identifiers/did:example:1234?service=files&relativeRef=/resume.pdf
Accept HTTP request header 设为
application/did-url-dereferencing,以请求完整的
10. DID URL
解引用结果,或者
Accept HTTP request header 设为
accept
dereferencing option 的值,以仅请求结果中的
contentStream 值。
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
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"
}
type 属性:
true 的
deactivated 元数据属性:
410。Content-Type
HTTP response header 的值是 application/did-resolution:
200。
Content-Type
HTTP response header。其值 MUST 是
didResolutionMetadata 中
contentType 元数据属性的值(见
4.2 DID
解析元数据)。
Content-Type HTTP response header 对应的
表示。
Content-Type HTTP response header 的值
是 application/did-url-dereferencing:
text/uri-list:
303。
Location 标头。此标头的值 MUST
是 selected DID service
endpoint URL。
200。
Content-Type
HTTP response header。其值 MUST 是
dereferencingMetadata 中
contentType 元数据属性的值(见
5.2
DID URL 解引用元数据)。
Content-Type HTTP response header 对应的表示。
参见此处,了解与 HTTP(S) 绑定对应的 OpenAPI 定义。
给定以下 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
resolve() 函数可以通过 HTTP(S)
绑定按如下方式调用:
GET https://resolver.example/1.0/identifiers/did:example:123 HTTP/1.1 Accept: application/did-resolution
响应如下:
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": {
...
}
}
resolve() 函数可以通过 HTTP(S)
绑定按如下方式调用:
GET https://resolver.example/1.0/identifiers/did:example:123 HTTP/1.1 Accept: application/did
响应如下:
HTTP 200 OK
Content-Type: application/did
{
"@context": [ "https://www.w3.org/ns/did/v1.1" ],
"id": "did:example:123",
"verificationMethod": [{
...
}],
"service": [{
...
}]
}
dereference() 函数可以通过
HTTP(S) 绑定按如下方式调用:
GET https://resolver.example/1.0/identifiers/did:example:123?versionId=2 HTTP/1.1 Accept: application/did-url-dereferencing
响应如下:
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": {
...
}
}
dereference() 函数可以通过
HTTP(S) 绑定按如下方式调用:
GET https://resolver.example/1.0/identifiers/did:example:123?versionId=2 HTTP/1.1 Accept: application/did
响应如下:
HTTP 200 OK
Content-Type: application/did
{
"@context": [ "https://www.w3.org/ns/did/v1.1" ],
"id": "did:example:123",
"verificationMethod": [{
...
}],
"service": [{
...
}]
}
本节包含各种安全考量,建议在生产环境中使用 DID 解析的人予以考虑。建议读者在阅读本节之前,先 熟悉 去中心化标识符规范的安全考量章节 中提供的一般安全建议。
DID 解析和 DID URL 解引用不 涉及任何身份验证或授权功能。类似于 DNS 解析,任何人都可以执行该过程,而无需任何凭证 或非公开知识。
DID 解析器可以 维护一个通用的 DID 文档缓存。它 也可以维护特定于某些 DID 方法的缓存。
noCache 解析选项可用于请求
某种缓存行为。
此 resolution option 是 OPTIONAL。
此属性的可能值为:
缓存行为可以通过
DID 解析器的配置、
noCache 解析选项、DID
文档的内容(例如 cacheMaxTtl 字段),或这些
属性的组合来控制。
实现 noCache 的解析器可能更容易受到拒绝
服务攻击,因为恶意客户端可以绕过缓存来强制
代价高昂的网络请求和资源消耗。使用 noCache
请求解析的客户端预期某些
解析器会拒绝绕过缓存的解析请求。
拒绝无缓存解析的解析器 MUST 以
FEATURE_NOT_SUPPORTED 错误响应,并明确说明
不允许绕过缓存,以便客户端可以尝试
不使用 noCache 进行解析。
如果从远程位置获取 JSON-LD Context 文件,攻击者可能会篡改该上下文 文件(例如,通过攻陷服务器 或通过中间人攻击拦截请求)。
因此,强烈建议任何执行远程检索 JSON-LD Context URL 的 DID 解析器使用上下文文件及其对应哈希的注册表 (或功能等效机制),以帮助确保 端到端安全。预期实现会在 资源的密码学哈希值与预期哈希值不匹配时抛出错误。
如果提供了 versionId 或
versionTime DID
参数,则 DID 解析算法会返回
DID 文档的特定版本。
DID 参数 versionId 和
versionTime 互斥。
versionId
DID 参数的使用是特定于
DID 方法的。其可能值可
包括顺序编号、随机 UUID、内容哈希等。
DID 文档元数据 MAY 包含一个
versionId 属性,
该属性会随着对 DID 文档执行的每次
Update
操作而变化。
使用分布式系统(例如 分布式账本)作为 VDR(可验证数据注册表)的 DID 方法 需要管理 网络分叉可能发生的潜在情况。因此,使用 分布式系统作为 VDR 的 DID 方法规范 SHOULD 指定一种方式,以便将其使用的 VDR 与此类 分叉区分开来。
当 DID URL
解引用器客户端解引用
DID 文档中的标识符
和链接资源时——尤其是
verificationMethod、controller 或
alsoKnownAs 等字段——可能会遇到
解引用循环。当
DID 文档
引用另一个 DID(或 URL),并且该引用最终
又指回先前已解引用的标识符,从而形成
循环时,可能会发生这种情况。DID
URL 解引用器在解引用引用
DID 服务端点的
DID URL时,
也可能遇到此类情况。
did:example:alice
└── verificationMethod.controller → did:example:bob
└── verificationMethod.controller → did:example:alice
执行递归解引用的 DID URL 解引用器及其客户端应当预期、检测并处理 此类循环。
安全和性能风险:如果未检测并缓解 循环,递归解引用可能导致:
缓解指导:鼓励递归跟随外部 DID 文档引用的组件 跟踪已经解引用过的标识符, 并检测循环何时发生,然后采取适当行动。 此外,开发者可能希望限制递归深度或广度, 以减少潜在攻击面。
本节为非规范性内容。
DID URL 的查询组件用于传递影响解析和解引用行为的 DID 参数(见 3. DID 参数)。查询字符串处理的若干 方面具有安全含义,建议实现者仔细考虑。
relativeRef DID 参数经百分号解码后的值,会使用
RFC3986 第
5 节中定义的引用解析算法,以
serviceEndpoint URL 作为基 URI 进行组合,从而构造最终
资源 URL(见 5.4.1
解引用资源)。如果
relativeRef 的值包含路径遍历序列,攻击者可能能够
使解引用器构造一个逃逸出服务端点预期
路径范围的资源 URL。
路径遍历可能使用多种编码方式尝试。以下是 攻击者可能使用的序列的非详尽示例:
../%2E%2E%2F、%2E%2E/、.%2E/、
%2E./
%252E%252E%252F..\)
鼓励实现者:
serviceEndpoint URL 基路径为前缀的
资源 URL 的 relativeRef 值视为
无效输入,例如通过返回 INVALID_DID_URL 错误(见
11. 错误)。
../)并不是可靠的遍历检测机制。
当服务端点 URL 本身是一个会被递归解引用的 DID
URL 时,此问题尤为严重。在这种情况下,
relativeRef 中的遍历序列可能会影响与预期不同的 DID 文档的解析。
另请参见 13.6
解引用循环。
如 3.2 查询 规范化中所述,同一逻辑 DID URL 可以由多个语法上 不同的字符串表示。在代理或多组件解析架构中(见 8.2.2 代理 解析),不同组件可能应用不同的 规范化规则(或完全不规范化)。
了解组件之间规范化不一致的攻击者可能会:
为缓解这些风险,鼓励实现者:
通过字符串拼接以编程方式构造 DID URL 的实现 (例如,将调用者提供的值追加为 DID 参数)如果在拼接前未验证并编码输入, 可能容易受到参数注入攻击。
例如,调用者提供的 service 值 files&versionId=2
如果在未编码的情况下拼接,可能会向
DID URL
中注入额外的 versionId 参数,
从而以调用者可能并未预期或授权的方式
改变解析行为。这类似于基于 HTTP 的系统中的查询字符串
注入漏洞。
鼓励实现者在将所有调用者提供的参数 值拼接到 DID URL 查询字符串之前,按照 RFC3986 第 2.1 节对其进行百分号编码,并 验证参数值在 解码后符合本规范中 该参数的预期值格式(见 3. DID 参数)、适用 DID 方法规范或 DID Document Resolution Extensions [DID-EXTENSIONS-RESOLUTION] 中的定义。
本节详细说明 DID 解析特有的隐私考量。 建议读者在阅读本节之前,先熟悉 去中心化标识符规范 和 受控标识符规范 的隐私考量章节中提供的一般隐私建议。
DID 解析器和 DID URL 解引用器将能够 记录其服务收到的解析和解引用请求。随着时间推移, 这些日志可用于跟踪请求这些服务的客户端并为其画像。 为缓解此隐私风险,客户端应向其信任的服务发出此类请求, 例如,因为存在既有业务 关系,或因为该服务运行在其控制的基础设施上。
客户端还可以采取步骤混淆其向服务发出的请求,以降低 关联和画像分析的可能性。混淆技术 包括 Oblivious HTTP、使用可信代理执行解析 请求,以及使用可信缓存。
不同 DID 方法会根据方法的设计决策和底层 VDR 具有不同的额外隐私影响和考量。 建议实现者审查其打算支持的 特定 DID 方法的隐私考量。鼓励 DID 方法设计者遵循 W3C 威胁建模指南 来生成威胁模型,以帮助实现者理解方法设计的 隐私影响。
在 Internet 上将标识符解析为地址时,最常用的机制之一是 [RFC1034] 中描述的全局域名系统(DNS)。 DNS 以及用于将域名映射到互联网 协议地址的过程和系统,是托管网站的常见要求。
去中心化标识符 (DID)v1.0 规范引入了一种新型标识符,它不依赖 全局域名系统,并引入了一个不要求架构中任何 部分中心化的标识符解析过程概念。这种新架构允许 以去中心化方式创建和管理可全局解析的标识符, 以对抗标识符寻租和审查。它使个人能够完全拥有并 控制自己的标识符,而不是从第三方租用标识符。
获得 DID URL 的个人,会在其软件中使用它们,方式与继续 使用基于 DNS 的 URL 十分相似。软件使用 DID 解析器接口 (在本规范中定义)来确定要检索资源的位置。 DID 解析过程与 DNS 解析过程非常相似,对个人而言是不透明的,并在软件内部发生, 不需要个人直接参与。
与 DNS 中心化以及相应发明 DID 和 DID 解析相关的研究, 由 去中心化标识符(DID)v1.0 规范中 与 DID 历史相关的章节记录。
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: