5. did-oan方法与资源身份
本章规定 did:oan 作为 OpenAgenet (OAN) 资源身份方法的稳定规则。方法层负责回答“标识符是否合法、标识了什么对象、如何得到对应的 DID文档、谁能够证明控制权”,不负责回答资源是否已经登记、根平台是否已经发布或发现服务节点是否已经索引。资源网络中的注册、发布、分发和发现状态应引用本规范其它章节的对象和证据。
did:oan 方法实现必须同时满足语法可解析、语义编码可解释、DID文档结构可验证和控制证明可验签四个条件。其 DID文档还通过 oanMetadata 将资源身份与能力语义放在同一个可解析对象中:能力标签提供受治理的分类键,能力描述说明资源能够完成的任务,用例给出典型使用情境,协议绑定和服务引用说明如何接入。这种设计使解析 DID 后即可取得语义发现所需的核心描述,并通过文档哈希、控制证明和资源包把语义声明与资源身份及版本绑定,是 did:oan 面向智能体资源发现的重要创新。
5.1 方法目的与标识符范围
did:oan 可以标识智能体服务、技能包、MCP 服务、工具 API,也可以标识主体、组织和基础设施节点等方法定义允许的对象。方法特定语义编码的前两位区分对象类别,后两位表示应用或语义域;资源 DID、主体 DID、注册服务节点 DID、发现服务节点 DID 和根平台 DID 的用途不同,不能因为都使用同一 DID 方法就混为一谈。
标识符的唯一性首先是方法命名空间内的字符串唯一性;随机生成依赖密码学随机数,确定性派生则由语义编码、控制材料和 nonce 共同决定。资源跨不同注册服务节点或发现服务节点传播时,资源 DID 不因入口变化而改变;同一 DID 的历史版本应通过版本、哈希、发布序列和历史 DID文档记录关联,而不是为每次更新随意生成新 DID。
在 OAN 的网络拓扑中,入口节点和身份对象是两条不同的关系:客户端可以通过一个注册服务节点提交资源,也可以从多个发现服务节点查询同一资源,但这些服务节点的 DID 只标识节点自身。资源 DID 仍由资源控制方生成或持有,解析器应根据资源 DID 取得对应 DID文档,而不是把提交入口拼接到 DID 中。
| 对象 | DID 的主体 | 主要用途 | 不应替代的对象 |
|---|---|---|---|
| 主体 DID | 组织、开发者或控制主体 | 表达控制关系和签名语境 | 具体资源 DID |
| 资源 DID | 智能体服务、技能包、MCP 服务或工具 API | 表达资源的注册、版本和控制边界 | 主体 DID 或节点 DID |
| 注册服务节点 DID | 注册基础设施节点 | 表达登记入口及其节点身份 | 资源控制权 |
| 发现服务节点 DID | 发现基础设施节点 | 表达索引和查询入口 | 资源发布事实 |
| 根平台 DID | 根平台基础设施身份 | 表达根平台相关证明和发布来源 | 资源所有权 |
5.2 DID 语法与方法特定标识符
方法特定标识符采用 did:oan:<semantic-code>:<suffix> 形式。semantic-code 必须是 4 个 ASCII 大写字母或数字,其中前两位为主体代码,后两位为应用域代码;suffix 必须是 32 个 Base58 字符,使用 OAN 定义的 Base58 字符表,不允许 0、O、I 和 l 等易混淆字符。方法实现对整体 DID、分段数量、语义编码和后缀分别校验。
例如,did:oan:SKFI:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu 是语法上可解析的技能包 DID,而大小写错误、后缀长度不为 32、包含非法 Base58 字符或缺少分隔段的字符串必须拒绝。SDK 的规范化只将语义编码按方法规则转换为大写并保持后缀不变;规范化不能修复错误字符,也不能改变 DID 的对象类别。
方法库把解析结果拆分为完整值、语义编码、主体代码、应用域代码和后缀,便于后续校验资源类型,而不是让调用方自行按字符串位置猜测含义:
{
"input": "did:oan:skfi:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu",
"normalized": "did:oan:SKFI:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu",
"semanticCode": "SKFI",
"subjectCode": "SK",
"appDomainCode": "FI",
"suffixLength": 32,
"parseResult": "valid"
}
这里的规范化只适用于语义编码大小写可以按实现规则转换的输入;分段数量错误、后缀长度错误或含非法字符时,解析应直接失败,不能以“尽量修复”的方式生成另一个 DID。
5.3 资源 DID 与主体/控制者关系
方法特定编码只能说明 DID 所属对象类别,不能单独证明主体、控制方、提供方或运营方之间的法律和业务关系。资源 DID 的控制关系应在 DID文档的验证方法、oanMetadata.controllerDid、publisherDid、issuerDid 及资源控制证明中表达,并由验证方检查这些字段与签名之间的对应关系。
主体可以控制多个资源 DID,资源提供方也可以与控制方不同;注册服务节点的 DID 代表基础设施资格,不能替代资源 DID。资源更新仍使用同一资源 DID 时,必须提交能够由当前控制关系验证的更新证明;DID 字符串本身不携带所有权,也不因被公开解析就转移控制权。
5.3.1 主体 DID
主体 DID 标识控制资源或代表组织、开发者的主体对象。它用于建立控制关系和签名主体的语境,不等同于某个具体资源的 DID,也不等同于用户登录账号。主体 DID 的 DID文档应公开验证所需的公钥和服务信息,私钥由主体在本地身份中保管。
5.3.2 资源 DID
资源 DID 为一个可独立注册、发布、发现、更新和撤销的资源建立身份边界。四类产品资源都可拥有独立资源 DID;资源类型必须与 DID 语义编码及 DID文档中的 oanMetadata.resourceType、subjectType 一致,否则注册服务节点和根平台应拒绝该材料。
5.3.3 控制关系与签名关系
控制关系由 DID文档中的验证方法和针对具体操作的可验证控制证明共同支撑。验证方应根据证明中的签名者、验证方法、目标 DID、用途、挑战、时间和 DID文档哈希检查签名,不能因为证明中的公钥与文档中某个公钥相同,就忽略用途、目标或新鲜度校验。
5.3.4 主体、资源与提供方分离
主体负责控制身份和资源操作,资源提供方负责能力、内容和服务端点,运营方负责运行环境和可用性。三者可以是同一主体,也可以分离;publisherDid 或 subjectDid 只是关系声明,关系真实性仍需由相应凭证、委托材料和控制证明支撑。
5.4 DID Document 结构
OAN 的 DID文档以 DID Core 数据模型为基础,至少包含 @context、id、verificationMethod、authentication、assertionMethod、service 以及面向 OAN 资源的 oanMetadata。id 必须是规范化后的 did:oan,验证方法的控制者、服务端点的引用和元数据中的资源身份必须能够相互校验。对于智能体服务、技能包、MCP 服务和工具 API,oanMetadata 是资源类型、能力语义、协议关系和发布引用的结构化承载位置。
oanMetadata.resourceDescription 和 oanMetadata.agentDescription 可以表达能力描述、能力标签和用例;资源描述还可携带输入输出模式、示例、受众、领域、语言和版本。顶层的 authorizedDomains、protocolBindings、implementationLinks、credentialRequirements 和 packageInfo 分别补充可见范围、交互协议、组合关系、调用凭证要求和发布材料。发现服务节点可以使用这些字段建立标签、词法和向量索引,把自然语言任务映射到候选资源;调用方则可以在取得候选后继续核对 DID 控制关系、资源版本和发布证明。
一个用于说明字段关系的最小 DID文档如下。示例中的公钥、服务地址和资源 DID 均为占位值;实际文档还应使用与控制方匹配的真实公钥和证明材料:
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/oan/v1"
],
"id": "did:oan:SKFI:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu",
"verificationMethod": [
{
"id": "did:oan:SKFI:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu#key-1",
"type": "Ed25519VerificationKey2020",
"controller": "did:oan:SKFI:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu",
"cryptoSuite": "Ed25519Sha256",
"publicKeyMultibase": "zExamplePublicKey"
}
],
"authentication": [
"did:oan:SKFI:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu#key-1"
],
"assertionMethod": [
"did:oan:SKFI:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu#key-1"
],
"service": [],
"oanMetadata": {
"subjectType": "skill",
"resourceType": "skill",
"controllerDid": "did:oan:DVFI:7YpQm9Kx2VnRb6Ts3WfHa4Cd5Ej8LgNz",
"capabilityTags": ["code-repository", "project-structure-summary"],
"resourceDescription": {
"name": "Repository structure analyzer",
"description": "Searches code repositories and summarizes project structure.",
"capabilityDescription": "Locate repository content, identify modules and summarize their relationships.",
"capabilityTags": ["code-repository", "project-structure-summary"],
"useCaseExamples": [
"Inspect an unfamiliar repository before development",
"Summarize modules, entry points and dependencies"
]
},
"lifecycleState": "active"
}
}
验证方至少应检查 id、验证方法的 controller、认证和断言引用是否属于同一文档,并检查资源类型是否与 SK 主体代码一致。能力标签、能力描述和用例应描述同一资源能力,发现服务节点可以分别用它们完成分类过滤、语义召回和结果解释。由于这些语义属性位于 DID文档中,资源控制方可以对包含语义声明的文档生成控制证明,资源包也可以通过 didDocumentHash 锁定该版本,避免发现索引把身份与来源不明的外部描述拼接在一起。
5.4.1 DID 标识与方法元数据
id 是 DID文档的主体标识,必须与请求或资源包中的资源 DID 完全一致;@context 应包含 DID Core 上下文和 OAN 方法上下文。方法特定语义编码可由解析器解释资源类别,但解析器不得仅据此替代 oanMetadata 和资源包的一致性校验。
5.4.2 verificationMethod
verificationMethod 描述可用于验证签名的公钥方法,每项至少需要方法 ID、类型、控制者和一种公开密钥表示。OAN 核心类型支持 publicKeyMultibase、publicKeyJwk 等表示,并可通过 cryptoSuite 和 publicKeyFormat 明确密码套件及编码;私钥绝不能出现在 DID文档中。
5.4.3 authentication 与 assertionMethod
authentication 指定可用于身份认证或请求证明的验证方法,assertionMethod 指定可用于签发或验证声明的验证方法。引用值必须能定位到同一 DID文档中的方法 ID,不能把仅用于断言的密钥无条件当作认证密钥,也不能把存在于 verificationMethod 中的公钥自动视为所有用途均有效。
5.4.4 service 端点
service 中的每个服务项应包含唯一服务 ID、服务类型和 serviceEndpoint,并可说明版本、协议、服务器类型和端口。端点可以指向资源业务服务、解析服务、资源包或其它协议描述,但端点可解析只证明地址存在,不能证明业务可用或调用方已获授权。
5.4.5 资源元数据与扩展字段
oanMetadata 用于承载 OAN 资源类型、主体类型、控制方、发布方、能力、授权域、协议绑定、实现链接、凭证要求、包信息和生命周期等语义。扩展字段不得覆盖 DID Core 的身份和验证含义;资源元数据与资源包、注册提交之间出现 DID、类型、版本、授权域或哈希冲突时,应按冲突处理规则拒绝或隔离。
oanMetadata 与 DID Core 核心字段的关系可以按以下方式理解:
| 字段区域 | 主要回答的问题 | 校验重点 |
|---|---|---|
id、verificationMethod |
这是哪个 DID,使用什么公钥验证 | DID 方法语法、方法 ID、控制者和公钥格式 |
authentication、assertionMethod |
哪些方法可以用于认证或断言 | 引用是否存在、用途是否匹配 |
service |
从哪里获取服务或协议入口 | 服务 ID、协议、版本和端点格式 |
oanMetadata |
资源是什么,具有什么能力和状态 | 资源类型、主体类型、授权域、版本和包绑定 |
因此,解析器可以保留未知的 OAN 扩展字段,但不能让扩展字段改变 id、验证方法和用途引用的含义;资源网络验证器则应在方法解析成功后继续检查元数据与资源包的一致性。
5.5 验证方法与公钥
验证方法的 id 应属于对应 DID,controller 应与控制关系一致,公钥表示和密码套件必须能被验证方解析。控制签名应明确 proofPurpose、verificationMethod、目标对象和签名覆盖范围;验证方先解析 DID文档取得公钥,再检查签名、用途、哈希和时间条件。
多个验证方法可以分别承担认证、断言、更新或恢复用途。密钥轮换必须通过当前有效控制关系授权,并保留旧密钥失效或历史验证所需的状态;旧密钥不能继续签发新的有效更新。仅把攻击者的公钥写入一份未被当前控制关系接受的 DID文档,不能取得该 DID 的控制权。
一个验证方法的可接受性不是“公钥存在”这一单一条件,而是多个字段共同成立:
{
"verificationMethod": "did:oan:SKFI:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu#key-1",
"expectedController": "did:oan:SKFI:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu",
"proofPurpose": "authentication",
"targetDid": "did:oan:SKFI:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu",
"documentHash": "sha256:example-did-document",
"signatureVerification": "required"
}
验证方应先确认 verificationMethod 能从目标 DID文档解析出来,再确认其控制者、用途、目标 DID 和签名覆盖的文档哈希相符。若公钥属于另一个 DID、方法未被相应用途引用或文档已被替换,验证失败;不能只比较公钥字节是否相同。
5.6 服务端点与发现引用
DID文档中的服务端点是资源或协议的定位信息,典型用途包括业务服务、注册服务、发现服务、DID 解析和资源包获取。服务项的 id 应可由资源 DID 关联,serviceEndpoint 应符合声明的地址或对象格式;发现响应可以引用端点,但调用方仍须验证根平台发布事实、端点新鲜度和业务认证要求。
注册服务节点、发现服务节点和解析器的接口属于网络组件行为,不因某个端点被写入 DID文档就改变其授权边界。端点缺失、协议不匹配、地址不可达或引用对象不兼容时,解析可以成功返回 DID文档,但资源发现或调用前验证应将相应问题明确标记。
解析结果应把“文档取得成功”和“端点可用”分开表达。一个面向客户端的结果摘要可以包含:
{
"did": "did:oan:SKFI:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu",
"resolution": {
"status": "resolved",
"documentRetrieved": true,
"methodSyntaxValid": true,
"documentIdMatchesRequest": true
},
"services": [
{
"id": "#resource",
"type": "OANResource",
"serviceEndpoint": "https://example.invalid/resource",
"availability": "not_checked"
}
],
"nextVerification": ["control-proof", "publication-proof", "endpoint-authentication"]
}
availability: not_checked 表示解析阶段没有对业务端点做可用性判断;解析器不应把 HTTP 地址存在或 DID文档返回成功改写为端点健康、资源已发布或调用已授权。
5.7 资源元数据绑定
资源 DID文档通过 oanMetadata 和包信息与资源元数据、ResourcePackage 建立关联。对于同一资源版本,资源 DID、资源类型、能力标签、能力描述、用例、授权域、协议绑定、版本和哈希应在 DID文档、注册提交和资源包之间保持可验证一致;资源包的 didDocumentHash 用于绑定具体文档内容,不能只绑定 DID 字符串。语义发现因此能够同时引用稳定 DID、受控语义声明和发布版本,而不是只对脱离身份的自由文本建立索引。
解析器返回 DID文档和 oanMetadata 后,发现服务节点可以提取能力标签、能力描述、用例、输入输出模式和协议绑定,结合共享能力词汇及本地语义搜索引擎建立索引。查询时,自然语言任务用于语义召回,能力标签和资源类型用于结构化过滤,用例与能力描述用于解释匹配原因;随后再叠加授权域、生命周期和发布状态检查。这一链路把 DID 方法中的身份语义扩展与 OAN 的语义治理、发现协议连接起来。
同一资源版本的绑定关系可以用如下摘要检查。三个哈希的用途不同,资源 DID 只能定位对象,不能替代对文档和内容的完整性检查:
{
"resourceDid": "did:oan:SKFI:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu",
"packageVersion": "1.0.0",
"didDocumentHash": "sha256:example-did-document",
"metadataHash": "sha256:example-metadata",
"packageHash": "sha256:example-package",
"checks": {
"didDocumentIdMatchesResourceDid": true,
"resourceTypeMatchesSemanticCode": true,
"metadataHashRecomputed": true,
"packageHashRecomputed": true
}
}
如果 DID文档内容变化,即使资源 DID 不变,didDocumentHash 也应变化并触发新的控制证明和资源网络验证;如果只查询 DID 字符串而不比较文档哈希,调用方无法判断拿到的是哪个版本的文档。
5.8 控制证明与 DID Document 证明
资源控制证明由控制方使用与 DID文档中验证方法对应的私钥生成,证明其对特定 DID、文档哈希、操作目的和挑战具有控制权。注册服务节点验证该证明,根平台在接受资源版本前再次验证;注册凭证证明登记处理事实,根平台可信发布证明证明网络发布事实,三者不能互相替代。
DID文档证明应覆盖规范化后的文档内容或规定的文档哈希,并包含可定位的验证方法、创建时间、证明用途和签名值。缺少证明、证明过期、目标 DID 不匹配、文档哈希不匹配、用途不匹配或签名无法验证时,验证必须失败且不得产生已发布状态。
OAN 控制挑战的验证输入应把请求上下文绑定到签名,而不是只验证一段脱离上下文的签名。安全库的检查重点可以抽象为:
{
"challenge": {
"challengeId": "challenge-example",
"draftId": "draft-example",
"subjectDid": "did:oan:SKFI:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu",
"registrarDid": "did:oan:INRG:7YpQm9Kx2VnRb6Ts3WfHa4Cd5Ej8LgNz",
"purpose": "register_resource",
"verificationMethod": "did:oan:SKFI:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu#key-1",
"didDocumentHash": "sha256:example-did-document",
"expiresAt": "2026-09-09T09:00:00Z"
},
"verification": {
"signatureValid": true,
"challengeMatchesRequest": true,
"notExpired": true,
"proofPurposeMatches": true
}
}
注册服务节点应把挑战中的主体 DID、目标注册节点、用途、文档哈希和有效期与当前请求逐项比较。挑战通过只说明控制方授权了这一次具有关联上下文的操作,不等于注册服务节点已经形成登记记录,也不等于根平台已经发布资源。
5.9 DID 生成与本地密钥处理
客户端是 DID 和控制密钥的首要生成与保管边界。随机 DID 由密码学随机数生成,确定性 DID 由语义编码、控制材料和 nonce 派生;无论采用哪种方式,生成结果都必须经过方法解析和资源类型一致性校验。注册服务节点只应接收公开 DID文档、签名和证明,不应取得主体或资源控制私钥。
本地身份备份是恢复控制关系的敏感材料,不是公开凭证。导入时应校验 DID、密钥、公钥、控制关系和文件结构的一致性;恢复后生成的控制证明必须重新绑定当前操作和文档哈希,不能把历史签名当作所有未来版本的无条件授权。
客户端处理本地身份时,可以按以下顺序减少密钥泄露和错误绑定风险:
- 在本地生成或导入主体及资源控制密钥,并检查公私钥是否匹配。
- 根据资源类型生成或解析
did:oan,检查语义编码与resourceType是否一致。 - 构造 DID文档,确认验证方法、用途引用和
oanMetadata指向同一资源 DID。 - 对当前文档和操作生成新的挑战控制证明,不复用与旧文档绑定的签名。
- 仅向注册服务节点提交公开 DID文档、证明和必要的资源元数据,不上传私钥。
浏览器下载的本地身份备份属于用户侧恢复材料,不能作为服务器端保存密钥的替代品。页面显示“已创建”或下载完成只表示客户端完成了文件操作,用户仍需确认文件内容完整并按本地安全要求保管。
5.9.1 DID 生成
客户端可调用方法库的随机生成或确定性派生接口创建 DID。生成参数中的语义编码必须合法;确定性派生只有在控制材料和 nonce 均相同且实现使用同一方法版本时才产生相同结果,不能把派生算法当作从 DID 反推出私钥的机制。
5.9.2 密钥生成与存储
控制密钥应在用户可控制的客户端环境生成或导入,私钥以本地安全存储或加密备份方式保存。DID文档、注册请求和发现响应只公开公钥及验证所需材料;服务器日志、请求体和错误响应不得包含私钥或可恢复私钥的明文材料。
5.9.3 本地身份备份
本地身份备份可以包含主体 DID、资源 DID、密钥材料、资源配置和必要凭证,应明确其敏感级别、创建时间和恢复用途。备份文件名、下载位置和页面展示文本不承担身份验证功能,用户必须独立保管备份并防止未经授权复制。
5.9.4 导入、恢复与密钥使用边界
导入或恢复后,客户端应确认公私钥对应、DID文档主体一致、资源类型一致,并在签名前重新生成当前挑战和哈希。注册服务节点、根平台和发现服务节点可以验证公开证明,但不应从导入流程获得私钥;节点运行私钥与用户资源控制私钥也必须分离。
5.10 DID 解析要求
解析请求首先验证 DID 方法和语法,再由解析服务取得当前可用的 DID文档或明确的历史版本。成功响应应包含文档及其可验证元数据;未找到、方法不支持、格式非法、资源已停用或历史版本不可用应使用可区分的错误或状态,而不能返回空文档并让调用方猜测原因。
解析成功只说明解析器能够返回一个 DID文档,不说明资源已登记、根平台已发布、凭证仍有效或业务端点可用。当前资源详情或 DID 文档 HTTP 接口的返回类型由具体节点决定:内容分发平台的 GET /cdn/documents/{did} 直接返回 DidDocument,而某些目录接口会把 DID 放在 did 字段并将文档放在 document 字段中;客户端必须按实际接口契约解析,不能把所有 DID 读取接口假定为同一种包装结构。调用方应根据资源网络证据、治理状态、版本和本地策略继续判断。
解析错误应使调用方能够区分输入错误、方法能力和网络状态。可采用如下结果分类表达,具体 HTTP 映射由解析服务接口决定:
| 结果类别 | 方法层判断 | 调用方处理 |
|---|---|---|
invalid_did |
DID 前缀、分段、语义编码或后缀不合法 | 修正输入,不发起业务调用 |
method_not_supported |
当前解析器不支持 did:oan |
更换支持该方法的解析器 |
not_found |
方法合法但没有可返回的 DID文档 | 区分未登记与暂时不可达 |
resolved |
已取得并通过基本结构检查 | 继续验证控制、发布和端点 |
status_restricted |
文档或资源状态限制当前使用 | 保留历史证据,停止敏感动作 |
解析器不应通过返回一个空对象来掩盖 not_found 或 method_not_supported,也不应把发现节点的旧快照直接当作当前 DID 方法解析结果。
与 A2A、MCP 等外部协议的互操作属于解析结果的消费和适配问题,不改变 did:oan 的标识符、DID文档或控制关系规则。解析器可以保留 oanMetadata、服务端点和协议绑定,供适配器映射为外部协议描述;调用方仍须独立验证 DID、资源包、控制证明和根平台发布证据。
5.11 DID 更新、版本管理、暂停、恢复与停用
同一资源的更新通常保持资源 DID 不变,通过新的 DID文档版本、资源包版本、哈希和控制证明表达变化。更新方必须使用当前有效控制关系签名,根平台和相关节点应检查版本顺序、上一版本引用、文档哈希及资源生命周期状态;方法库本身只提供 DID 解析和类型校验,不替代网络更新协议。
同 DID 更新的最小判断可以归纳为以下关系:
current DID + current control proof + new document hash
-> verify current control and version relation
-> accept a new resource version or reject the update
更新请求中的 DID 与旧记录不一致时,应按新资源或非法替换处理,不能由接收时间决定覆盖对象;DID 相同但控制证明无效时,也不能因为资源名称、端点或提交方相同而覆盖旧文档。
暂停、恢复和停用是资源网络状态动作,必须绑定明确的控制证明、治理事实或授权条件。历史文档可以为审计和历史验证保留,但解析当前状态时不得把旧文档或旧发布证明当作最新状态。
5.11.1 同 DID 更新
同 DID 更新要求新材料中的 id 与既有资源 DID 相同,并由当前控制密钥对新文档或规定的文档哈希签名。控制关系发生变化时,应先满足密钥轮换或恢复规则;仅提交相同 DID 和一把新公钥不能覆盖现有文档。
5.11.2 版本选择
当前版本应由资源版本、文档哈希、包哈希和发布序列共同确定。解析器或发现服务节点选择最新版本时,应依据可信发布事实和生命周期状态,而不是仅按接收时间或本地数据库自增编号选择;历史版本查询需要明确版本标识或发布引用。
5.11.3 暂停与恢复
暂停应使规定范围内的发现、发布或调用前验证停止把资源当作 active;恢复需要新的有效状态依据,并重新检查版本和发布证据。缓存的旧文档可以用于历史展示,但不能绕过当前暂停状态。
5.11.4 停用与历史状态
停用表示 DID 或资源在规定范围内不再接受新的有效使用,历史文档和证明仍可为审计保留。停用、资源撤销、注册凭证吊销和端点下线应分别记录,不能用一个页面状态字段代替全部事实。
同 DID 更新、暂停、恢复和停用的基本控制路径如下。图示只表达方法层与资源网络层之间的验证顺序,不表示方法库单独完成注册或发布:
flowchart LR
G[生成 DID 与控制密钥] --> DOC[构造 DID文档]
DOC --> PROOF[签署控制证明]
PROOF --> VERIFY[验证 DID、签名、挑战和哈希]
VERIFY -->|通过| UPDATE[接受注册或更新]
VERIFY -->|失败| REJECT[拒绝且不改变已发布状态]
5.12 DID 方法安全与隐私考量
安全性来自私钥保密、签名覆盖范围、DID文档公钥绑定、挑战和新鲜度检查,而不是来自 DID 字符串不可见或格式复杂。攻击者可以复制公开 DID文档和公钥,但在没有有效控制私钥、当前挑战和相应授权的情况下,不能产生可被接受的更新证明。随机 nonce、请求时间、文档哈希和用途字段应参与重放防护。
方法实现应避免将主体关系、资源内容和端点隐私无条件集中暴露。DID文档中只放置公开验证和发现所需的信息;敏感凭证、私钥和内部地址应通过受控端点或外部授权机制处理。失败校验不得写入已发布状态,错误日志应保留足够审计信息但不得泄露私密材料。
5.13 DID 方法符合性要求与测试向量
符合性测试至少应覆盖:合法 DID 解析;错误前缀、段数、语义编码、后缀长度和非法字符拒绝;四类资源代码映射;随机生成结果可重新解析;确定性派生在相同输入下稳定、在控制材料或 nonce 变化时改变;DID 与资源类型不一致时拒绝;规范化前后 DID 语义不变。
签名测试还应覆盖验证方法用途不匹配、目标 DID 不匹配、文档哈希不匹配、过期挑战、重复 nonce、错误公钥和旧密钥更新等情况。测试证据应记录固定输入、方法版本、预期错误和实际输出;方法层测试通过不等于注册、发布或发现链路已经通过。
方法实现可以使用下列最小测试向量作为输入分类的示例:
| 输入 | 预期结果 | 失败或通过依据 |
|---|---|---|
did:oan:SKFI:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu |
通过 | 四段结构、4位语义编码和32位 Base58 后缀成立 |
did:oan:skfi:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu |
规范化后再判断 | 仅语义编码大小写可按 SDK 规则规范化 |
did:oan:SKFI:0HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu |
拒绝 | 后缀含 Base58 禁止字符 0 |
did:oan:SK:5HkPq7Vm3RdT9Ya2WcX8Ns4Bf6GjLeZu |
拒绝 | 语义编码不是4位 |
合法 DID + resourceType: tool_api |
拒绝 | SK 与资源类型不一致 |
测试向量中的 DID 和后缀仅用于验证方法实现,不应直接作为生产资源身份。测试还应记录解析器版本、规范化前后输入、错误类型和是否产生任何持久化副作用;单纯返回错误字符串不足以证明发布状态没有被修改。
5.14 DID 方法互操作与解析器行为
did:oan 应遵守 DID Core 对 DID、DID文档、验证方法和服务的基本数据模型,同时由方法实现规定自己的方法特定标识符和解析行为。外部解析器至少应能识别方法名并拒绝不符合方法语法的标识符;支持 OAN 方法的解析器还应保留 oanMetadata 及其扩展字段,不能在转换过程中丢失资源类型、能力和发布引用。外部系统消费公开信息时,仍须按 OAN 规则验证控制关系、资源包和根平台发布证据。
did:oan 标识符由方法名和方法特定标识符组成。下例只用于说明结构和字段关联,示例值不代表真实网络对象,也不应被当作可直接发布的控制材料。
did:oan:<主体类型或资源类型编码>:<方法特定标识符>
{
"id": "did:oan:SKDM:example-resource-id",
"verificationMethod": [
{
"id": "did:oan:SKDM:example-resource-id#key-1",
"type": "JsonWebKey2020",
"controller": "did:oan:SKDM:example-resource-id",
"publicKeyJwk": { "kty": "OKP", "crv": "Ed25519", "x": "..." }
}
],
"authentication": ["did:oan:SKDM:example-resource-id#key-1"],
"service": [
{
"id": "#resource",
"type": "OANResource",
"serviceEndpoint": "https://example.invalid/resource"
}
]
}
| 检查对象 | 必须回答的问题 | 失败后果 |
|---|---|---|
| DID 字符串 | 方法名、编码、字符和类型是否符合规则 | 拒绝解析或进入无效状态 |
DID文档 id |
是否与请求中的资源 DID 完全一致 | 拒绝绑定 |
| 公钥与控制关系 | 验证方法是否由 DID 控制方声明并可验签 | 不接受控制证明或更新 |
| 签名覆盖范围 | 签名是否覆盖目标 DID、文档/包哈希、挑战和用途 | 拒绝签名事实 |
| service 与元数据 | 端点、协议和资源描述是否一致 | 不进入可信发现或调用流程 |
方法层符合性测试应把合法解析、非法输入拒绝、DID 类型映射、文档绑定、签名用途、挑战新鲜度和更新控制权分别记录。方法测试通过,只能证明 DID 方法行为符合测试向量,不能替代注册服务节点、根平台和发现服务节点的业务链路验证。具体生成、签署、验证和拒绝路径已经在 5.9、5.10、5.11 和 5.13 中说明,本节只规定跨解析器消费时不得丢失方法语义。
参考来源
| 来源 | 类型 | 链接 |
|---|---|---|
oan-protocol-common |
代码仓:did:oan 核心类型和方法实现 |
https://github.com/wolfbrother/oan-protocol-common |
oan-sdk-ts |
代码仓:TypeScript DID 解析、生成和验证 | https://github.com/OpenAgenet/oan-sdk-ts |
| OAN Yellow Paper | arXiv 黄皮书:身份、控制权和资源发布机制 | https://arxiv.org/abs/2606.03163 |
did:oan DID Method Specification |
标准/方法规范:did:oan 标识格式和解析规则 |
https://github.com/OpenAgenet/oan-public-docs/blob/main/did-oan-specs/doc/OAN DID Method Specification.md |
| OAN Resource Identity and Discovery | IETF 草案:资源身份和发现 | https://datatracker.ietf.org/doc/draft-xu-oan-resource-identity-discovery/ |