另请参阅 翻译。
Copyright © 2025 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
本规范描述了一种通过使用位串来发布状态信息(例如 可验证凭证的暂停或撤销)的保护隐私、空间高效且 高性能的机制。
本节描述了本文档在 发布时的状态。当前 W3C 出版物列表以及本技术报告的最新修订版可在 W3C 标准和草案 索引中找到,地址为 https://www.w3.org/TR/。
随时欢迎对本规范提出意见。 请直接在 GitHub 上提交议题, 如果无法这样做,也可以发送到 public-vc-comments@w3.org。 (订阅, 归档)。
本文档由可验证凭证工作组作为 推荐标准发布,并使用 推荐标准轨道。
W3C 建议将本规范作为 Web 标准广泛部署。
W3C 推荐标准是一种规范,它在经过广泛 共识建立后,由 W3C 及其成员认可,并且 工作组成员已承诺为实现提供 免版税许可。
本文档由一个根据 W3C 专利 政策运作的小组制作。 W3C 维护一个 与该小组交付物相关的任何专利披露的公开列表; 该页面还包括 披露专利的说明。任何实际知悉某项专利且认为该专利包含 必要权利要求的个人, 必须按照 W3C 专利政策第 6 节披露该信息。
本文档受 2023年11月3日 W3C 流程文档约束。
本节是非规范性的。
对发行者而言,通常有必要为可验证凭证 [VC-DATA-MODEL-2.0] 链接到一个位置, 使验证者 能检查 凭证是否已被暂停或撤销。在设计、发布和 处理状态列表时,需要考虑各种隐私 和性能因素。
当可验证凭证与 发布状态的 URL 之间存在一对一映射时, 就会出现这样一种隐私考量。这种映射使发布该 URL 的网站能够在 状态被检查时关联持有者、时间和验证者。 这可能使发行者发现 持有者正在与 验证者进行的交互类型, 例如进入酒吧时提供年龄 验证凭证。在进入场所时被驾驶执照的发行者 跟踪,违反了如今许多人所具有的隐私 期望。
类似地,在设计状态列表时也会探索性能方面的考量。 其中一个考量是列表发布的位置,以及从带宽和处理角度看, 它给服务器和获取信息的客户端都带来的负担。 为了满足隐私期望, 将大量凭证的状态打包到一个单一 列表中有助于群体隐私。然而,如果每个凭证的状态信息多达 数百字节,并且覆盖数亿 持有者, 这样做可能会给服务器和客户端都带来不可能承受的 负担。
本文档其余部分提出了一种高度可压缩、基于位串的 状态列表机制,它具有强大的隐私保护特性, 与 Web 架构兼容,具有很高的空间效率, 并且非常适合内容分发网络。作为使用本规范实现一系列有益隐私和 性能目标的示例,可以创建一个 可为 100,000 个可验证凭证 构造的状态列表,在最坏情况下大小约为 12,500 字节。在只有数百个 凭证被撤销的情况下,该列表的大小小于 数百字节,同时在 100,000 人的群体中提供隐私。
本节是非规范性的。
本节概述了本规范描述的状态列表
机制所使用的核心概念。在最基本层面,由发行者
签发的所有可验证凭证
的状态信息会表示为列表中的项。每个发行者管理一个
其已签发的所有可验证凭证的列表。每个
可验证凭证
都与其列表中的一个项相关联。
当单个位指定一个状态,例如“已撤销”或“已暂停”时,
则当该位被设置(1)时,该状态预期为 true,
未设置(0)时为 false。
使用位串的好处之一是,它是一种高度可压缩的 数据格式,因为在平均情况下,大量凭证将 保持未撤销状态。这将确保有很长一段位具有相同 值,因此可使用游程长度压缩技术(例如 GZIP [RFC1952])高度压缩。默认状态列表 大小为 131,072 个条目, 相当于 16 KB 的单个位值。当只有少数 可验证凭证 被撤销时,GZIP 会将该位串压缩 到数百字节。
使用位串的另一个好处是,它使大量 可验证凭证 状态能够放在同一个列表中。 本规范使用的最小列表长度为 131,072。这一 大小确保在平均情况下具有足够的群体隐私。 如果需要更好的群体隐私,可以使位串更大。
本节是非规范性的。
本文档中使用的术语定义于 可验证凭证数据模型 v2.0规范的 术语章节中。
除标记为非规范性的章节外,本规范中的所有编写指南、图表、示例和注释均为非规范性。本规范中的其他所有内容均为规范性。
本文档中的关键词 MAY、MUST、MUST NOT、OPTIONAL、SHOULD 和 SHOULD NOT 应按 BCP 14 [RFC2119] [RFC8174] 中所述来解释,但仅当它们如这里所示以全 大写形式出现时才如此。
一致的 文档是数据模型的任何具体表达, 它遵循第 2. 数据模型中的相关规范性要求。
一致的 处理器是任何以软件和/或硬件实现的算法, 它根据第 3. 算法中的相关规范性 声明,生成和/或消费 一致的文档。一致的 处理器 MAY 选择仅 支持大小为 1 的位串条目。一致的处理器在消费非一致文档时 MUST 产生错误。
有许多方式可以表达与数字 凭证关联的状态信息。其中一些机制包括证书撤销列表(CRL) [RFC5280]、 在线证书状态协议(OCSP)[RFC2560]、 Bloom 过滤器 [RFC8932],以及密码学 累加器 [ALLOSAUR]。 本 规范针对一组不同于其他机制的需求进行优化。 这些需求包括:
| 状态技术比较 | |||||
|---|---|---|---|---|---|
| 特性 | CRL | OCSP | Bloom | 累加器 | 位串 |
| 提供可调的群体隐私 | ✓ | ✗ | ✓ | ✓ | ✓ |
| 不需要为每个凭证提供已签名断言 | ✓ | ✗ | ✓ | ✓ | ✓ |
| 当由验证者获取时, 抵抗发行者跟踪 | ✓ | ✓ | ✓ | ✓ | ✓ |
| 在撤销很多时,缓存具有空间效率 | ✗ | ✗ | ✓ | ✓ | ✓ |
| 高度可压缩(平均压缩率 >90%) | ✗ | ✗ | ✓ | ✓ | ✓ |
| 更新高效(快速,并且整个人群不需要更新) | ✓ | ✗ | ✓ | ✗ | ✓ |
| 使用 IETF 批准的密码学基元 | ✓ | ✓ | ✓ | ✗ | ✓ |
| 无误报 | ✓ | ✓ | ✗ | ✓ | ✓ |
| 可由持有者交付(装订) | ✗ | ✓ | ✗ | ✓ | ✓ |
| 易于为与可验证 凭证一起使用而配置配置文件 | ✗ | ✗ | ✗ | ✗ | ✓ |
当发行者
希望为
可验证凭证
启用状态信息时,他们 MAY 添加一个
credentialStatus 属性,该属性使用本节描述的数据模型。
本节中数据模型的任何表达 MUST 表达在
符合 [VC-DATA-MODEL-2.0] 定义的
一致可验证凭证中。
| 属性 | 描述 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| id |
状态列表条目的可选标识符。id
属性的约束列在可验证凭证数据模型规范
[VC-DATA-MODEL-2.0] 中。如果
存在,其值预期为一个 URL,用于
标识与可验证
凭证关联的状态信息。它 MUST NOT 是状态列表的 URL。
该值在验证或校验过程中不使用,并且不需要
与 statusListCredential 值相关。如有必要,该值可用于
唯一标识 BitstringStatusListEntry 对象,例如当它
存储在数据库中时。
|
||||||||||
| type |
type 属性 MUST 为
BitstringStatusListEntry。
|
||||||||||
| statusPurpose |
状态条目的目的 MUST 是字符串。虽然
字符串的值是任意的,但以下值 MUST 用于其
预期
目的:
|
||||||||||
| statusListIndex |
statusListIndex 属性 MUST 是任意大小的
大于或等于 0 的整数,
以十进制字符串表示。该值标识可验证
凭证状态的位置。实现
SHOULD 随机分配索引,使得诸如
分配的新近程度或群体大小等推断不能轻易从
该位置得出。
|
||||||||||
| statusListCredential |
statusListCredential 属性 MUST 是指向
可验证
凭证的 URL。当该 URL 被解除引用时,得到的
可验证
凭证 MUST 具有包含
BitstringStatusListCredential 值的 type 属性。
|
||||||||||
| statusSize |
statusSize 表示状态条目的位数大小。
statusSize
MAY 被提供。如果 statusSize 未作为
credentialStatus 的属性出现,则 statusSize MUST
按 1 处理。如果存在,
statusSize MUST 是大于零的整数。如果
提供了 statusSize
且其大于 1,则属性
credentialStatus.statusMessage
MUST 存在,并且状态消息的数量 MUST 等于
可能值的数量。
|
||||||||||
| statusMessage |
如果存在,statusMessage 属性 MUST 是一个
数组,其长度
MUST 等于 statusSize 指示的可能状态消息数量
(例如,如果
statusSize 为 1 位,则 statusMessage 数组 MUST
有 2 个元素;如果 statusSize 为 2 位,则有 4 个元素;
如果 statusSize 为 3 位,则有 8 个元素,依此类推)。如果
statusSize 为 1,statusMessage MAY 存在;如果 statusSize
大于 1,则 MUST
存在。如果 statusMessage 数组不存在,
与 status 位值 1 和
0 关联的消息值分别为 "set" 和 "unset"。如果
statusMessage 数组
存在,则每个元素 MUST 包含下面描述的两个属性,
并且 MAY 包含额外属性。
statusMessage 数组中的对象添加额外值。
实现者 MAY 在值中使用 undefined 的字符串值,以表示
对应状态尚未为关联状态值定义,但
将来可能会定义。如何处理各种状态
消息的规则不属于本文档规范性要求的范围,但
假定实现者会记录处理各种
状态代码的规则。
|
||||||||||
| statusReference |
实现者 MAY 包含 statusReference
属性。如果存在,其
值 MUST 是 URL 或 URL 数组 [URL],解除引用后指向
与状态相关的材料。强烈鼓励使用
statusPurpose 为
message 的实现者提供 statusReference。
注:关于引用的详细信息
当解释凭证的状态可能涉及对相关业务案例的某种理解时,
|
状态列表条目可通过使用
statusPurpose 属性,表达与可验证凭证
关联的状态目的。
使用 revocation 或 suspension 作为状态目的
包含了该状态的语义,其中 revocation
表示状态位表达某个
可验证凭证
是否已被撤销,而 suspension
表示状态位表达某个
可验证凭证
是否已被暂停。下面的示例
演示了这些状态目的的用法:
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"id": "https://example.com/credentials/23894672394",
"type": ["VerifiableCredential", "EmployeeIdCredential"],
"issuer": "did:example:12345",
"validFrom": "2024-04-05T14:27:42Z",
"credentialStatus": [{
"id": "https://example.com/credentials/status/3#94567",
"type": "BitstringStatusListEntry",
"statusPurpose": "revocation",
"statusListIndex": "94567",
"statusListCredential": "https://example.com/credentials/status/3"
}, {
"id": "https://example.com/credentials/status/4#23452",
"type": "BitstringStatusListEntry",
"statusPurpose": "suspension",
"statusListIndex": "23452",
"statusListCredential": "https://example.com/credentials/status/4"
}],
"credentialSubject": {
"id": "did:example:6789",
"type": "Person",
"employeeId": "A-123456"
}
}
使用 message 作为状态目的,使发行者能够
定义任意数量的自定义描述性消息,用于说明
可验证凭证的状态。
发行者
在
可验证凭证
签发时,通过
statusSize、statusMessage 和可选的 statusReference
属性,
承诺可能与特定条目
(即与特定可验证凭证)
关联的消息集合。这样做是为了确保
持有者知道
他们持有的特定可验证凭证
可能关联什么类型的信息,
而这些信息随后可能被收到该凭证的验证者发现。
需要注意,statusListIndex 是
可验证
凭证与其在列表中的状态之间唯一的链接。其他
属性(例如 credentialSubject.id)不用于
此目的。
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"id": "https://example.com/credentials/2947478373",
"type": ["VerifiableCredential", "BillOfLadingExampleCredential"],
"issuer": "did:example:12345",
"validFrom": "2024-04-05T03:52:31Z",
"credentialStatus": {
"id": "https://example.com/credentials/status/8#492847",
"type": "BitstringStatusListEntry",
"statusPurpose": "message",
"statusListIndex": "492847",
"statusSize": 2,
"statusListCredential": "https://example.com/credentials/status/8",
"statusMessage": [
{"status":"0x0", "message":"pending_review"},
{"status":"0x1", "message":"accepted"},
{"status":"0x2", "message":"rejected"},
...
],
"statusReference": "https://example.org/status-dictionary/"
},
"credentialSubject": {
"id": "did:example:6789",
"type": "BillOfLading",
...
}
}
当状态列表可验证凭证 被发布时,它 MUST 是一个 一致的文档,如 [VC-DATA-MODEL-2.0] 中定义,并表达 本节中的数据模型。以下章节描述了封装状态列表的 可验证凭证 格式。
状态列表表达在可验证凭证 内部,以便使 持有者 能够将其直接提供给验证者。这种机制 有时称为“证书装订”,它通过确保验证者无需联系 发行者来 检索状态列表,从而提高持有者的隐私。 不过,如果验证者例如希望获得状态列表的更新版本, 即使由持有者提供的 状态列表的真实性可验证,也可能选择忽略它。
建议发行者和验证者注意,
可验证凭证的发行者
与关联
BitstringStatusListCredential 的发行者
可能并不相同。可能存在技术、法律、制度、政治以及其他原因,
使得将原始凭证的权限与撤销或以其他方式更改
此类凭证状态的权限分离是适当的。
因此,包含
BitstringStatusListEntry 的可验证凭证
的 issuer 值
MAY 不同于
BitstringStatusListCredential 的
issuer 值。
| 属性 | 描述 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| id |
包含状态列表的可验证
凭证 MAY
表达一个 id 属性,该属性与相应
BitstringStatusListEntry 的
statusListCredential 中指定的值匹配(见 2.1 BitstringStatusListEntry)。
|
||||||||||
| type |
包含状态列表的可验证
凭证 MUST
表达一个包含
BitstringStatusListCredential 值的 type 属性。
|
||||||||||
| validFrom | 状态列表有效的最早时间点。此属性在 可验证凭证数据模型规范的 第 4.6 节:有效期中定义。 | ||||||||||
| validUntil | 状态列表有效的最晚时间点。此属性在 可验证凭证数据模型规范的 第 4.6 节:有效期中定义。 | ||||||||||
| credentialSubject.type |
凭证主体(即状态列表)的
type MUST 为 BitstringStatusList。
|
||||||||||
| credentialSubject.statusPurpose |
状态条目的目的属性 statusPurpose 的值 MUST 是
一个或多个字符串。虽然每个字符串的值是任意的,但以下
值 MUST 用于其预期目的:
|
||||||||||
| credentialSubject.encodedList |
凭证主体的
encodedList 属性 MUST 是
Multibase 编码的 base64url
(无
填充) [RFC4648]
表示,用于表示经 GZIP 压缩的 [RFC1952]
位串值,这些位串值对应于相关范围的可验证
凭证
状态值。未压缩的位串 MUST 至少为 16KB
大小。
位串 MUST 以如下方式编码:第一个索引,值
为零(0),
位于位串最左侧的位;最后一个索引,值为位串长度减一
(bitstring_length - 1),位于
位串最右侧的位。有关位串
编码的更多信息见第 7.1
位串编码。
|
||||||||||
| credentialSubject.ttl |
ttl 是一个 OPTIONAL 属性,表示在尝试刷新之前
的“生存时间”,单位为
毫秒。如果不存在,则不假定
默认值。该值不会覆盖或替代
BitstringStatusList 的
有效期。
发布状态列表的实现
SHOULD 将任何特定于协议的缓存信息,例如 HTTP
Cache-Control 头,与此字段中的值保持一致。
|
下面的示例演示了如何将 BitstringStatusListEntry
与 BitstringStatusListCredential 一起使用,以向验证者提供
确定特定
可验证凭证状态所需的信息。
{
"@context": [
"https://www.w3.org/ns/credentials/v2"
],
"id": "https://example.com/credentials/status/3",
"type": ["VerifiableCredential", "BitstringStatusListCredential"],
"issuer": "did:example:12345",
"validFrom": "2021-04-05T14:27:40Z",
"credentialSubject": {
"id": "https://example.com/status/3#list",
"type": "BitstringStatusList",
"statusPurpose": "revocation",
"encodedList": "uH4sIAAAAAAAAA-3BMQEAAADCoPVPbQwfoAAAAAAAAAAAAAAAAAAAAIC3AYbSVKsAQAAA"
}
}
以下章节概述了本文档所描述的用于生成 和验证状态列表的算法。
如果本节中任何算法的实现处理第 2. 数据模型中定义的属性, 而其值由于 不符合相关“MUST”语句而格式错误,则 MUST 引发 MALFORMED_VALUE_ERROR。
在生成 BitstringStatusListCredential 时,MUST 遵循 以下过程,或遵循能生成完全相同输出的过程。 该算法以已签发凭证列表作为输入,并且要么抛出 错误,要么返回状态列表凭证作为输出。
encodedList 属性。
encodedList 设置为压缩位串。
发行者 SHOULD 以可缓存且不跟踪谁检索了状态列表凭证的方式发布状态列表凭证, 例如通过 Oblivious HTTP、不由 发行者运营的内容分发 网络,或访问日志无法由数据分析人员或系统管理员 访问的业务流程。
在验证包含在 BitstringStatusListCredential 中的 可验证凭证 时,MUST 遵循以下过程,或遵循能生成完全相同输出的过程。 该算法以状态列表可验证凭证 作为输入,并且要么抛出错误,要么返回状态列表凭证作为输出。
credentialStatus 条目的可验证
凭证。
credentialStatus 条目里的
statusPurpose 值。
statusListCredential URL,并确保所有
证明都成功通过验证。如果解除引用失败,则引发
STATUS_RETRIEVAL_ERROR。如果任何
证明验证失败,则引发
STATUS_VERIFICATION_ERROR。
statusPurpose 值。注:
statusListCredential 可能在单个列表中包含多个
状态目的。如果这些值不
相等,则引发
STATUS_VERIFICATION_ERROR。
encodedList 属性值。
statusListIndex 属性值。
statusSize 小于 minimumNumberOfEntries,
则引发 STATUS_LIST_LENGTH_ERROR。
status 键设置为 status,并将
result 中的 purpose 键
设置为 statusPurpose 的值。
0,则将 result 中的 valid 键设置为
true;否则将其设置
为 false。
statusPurpose 为 message,则将
result 中的 message 键设置为
statusMessages
数组中指示的 value 对应的 message。
当 statusListCredential URL 被解除引用时,服务器实现 MAY
提供一种机制,用于解除引用某个特定时间点的状态列表。当发行者提供这种机制时,它使
验证者能够以发行者选择的精度
确定状态变化,例如每小时、每天或每周。如果支持这种特性,并且如果
URL 方案支持查询参数,则查询
参数的名称 MUST 为 timestamp,且其值 MUST 是有效的 URL
编码
[XMLSCHEMA11-2]
dateTimeStamp 字符串值。解除引用这种
带 timestamp 参数的 URL 的结果 MUST 要么是包含
给定时间点存在的状态列表的状态列表凭证,要么是
STATUS_RETRIEVAL_ERROR。如果结果为
错误,则只要验证者的
验证规则允许此类操作,实现 MAY 使用不同的
timestamp 值或不使用 timestamp 值再次尝试检索。
验证者 SHOULD 缓存已检索的状态列表,并且 SHOULD 使用代理 或其他机制,例如 Oblivious HTTP,以向 发行者隐藏检索 行为。
预期验证者在使用任一凭证中包含的信息 进行进一步决策之前,会确保其信任 可验证 凭证的发行者,以及相关 BitstringStatusListCredential 的发行者。 建议实现者注意,这些 凭证的发行者可能不同,例如当原始 可验证 凭证的发行者并不维护其有效性记录时。
在生成状态列表位串时,MUST 遵循以下过程, 或遵循能生成完全相同输出的过程。该算法以 issuedCredentials 列表作为输入,并且要么抛出错误,要么返回 压缩位串作为输出。
bitstring 中的每个值,如果
issuedCredentials 中某个凭证具有对应的 statusListIndex 值,
则将该值设置为适当状态。该值的位置计算为
statusListIndex 乘以 statusSize。
在展开压缩状态列表位串时,MUST 遵循以下过程, 或遵循能生成完全相同输出的过程。该算法以 压缩位串作为输入,并且要么抛出错误,要么返回 未压缩位串作为输出。
本规范中描述的算法会抛出特定类型的错误。 实现者可能会发现将这些错误传达给其他库或 软件系统是有用的。本节为这些错误提供特定 URL、描述和错误 代码,以便实现本规范所述技术的生态系统在错误发生时 能够更有效地互操作。
在通过 HTTP 接口暴露这些错误时,实现者 SHOULD 使用 HTTP API 的问题详情 [RFC9457] 来编码错误数据结构。如果 使用 [RFC9457]:
type 值 MUST 是一个 URL,其开头
为值
https://www.w3.org/ns/credentials/status-list#,并以
下面列出的章节中的值结尾。
title 值 SHOULD 为
错误提供一个简短但具体的人类可读字符串。
detail 值 SHOULD 为错误提供一个更长的人类可读字符串。
Accept-Language
HTTP 头字段来选择最合适的资源。
第 2. 数据模型中的信息可以通过多种方式进行保护。这些 机制在 可验证凭证数据模型 v2.0的 保护机制 章节中进行了详细说明。
在保护包含对 BitstringStatusListCredential 的引用的 可验证凭证 时,实现者 SHOULD 对两个 可验证 凭证使用相同的保护机制、相同的 密码学参数和相同的媒体类型。
在解除引用 statusListCredential 时,返回的
statusListCredential 内容可能是为表达带有一个或多个证明的
可验证凭证这一目的而注册的任何媒体类型。
例如,使用数据完整性证明保护的可验证凭证可能
具有媒体类型 application/vc,而使用 SD-JWT 保护的可验证凭证
可能具有媒体类型 application/sd-jwt。
某些实现可能选择支持不那么具体的媒体类型,例如
application/ld+json 或 application/json。
在通过 HTTP 解除引用时,使用
accept 和
content-type 头,可能
允许某些实现协商用于保护
statusListCredential 的证明格式。
某些实现可能使用 415 不支持的媒体类型状态 代码来表示它们不支持所请求的媒体类型。
本规范中定义的术语也是 RDF 词汇表命名空间
https://www.w3.org/ns/credentials/status# 的一部分。对于
任何
TERM,相关 URL 的形式为
https://www.w3.org/ns/credentials/status#TERM。
使用 RDF 处理并依赖本规范的实现 MUST 使用
这些 URL。
在解除引用 https://www.w3.org/ns/credentials/status# URL 时, 返回数据的 媒体类型取决于 HTTP 内容协商。 如下所示:
| 媒体类型 | 描述和哈希 |
|---|---|
| application/ld+json |
JSON-LD 格式的词汇表 [JSON-LD11]。 SHA2-256 摘要: 98b555e914aed27fe6b73dbd655a3d1103d1a26ce1ad709a38435dcbb3451a68
|
| text/turtle |
Turtle 格式的词汇表 [TURTLE]。 SHA2-256 摘要: ad4b2142eaa57cf771d91c2b061ebeb4cd17d74c8e87899ea14368df14168844
|
| text/html |
HTML+RDFa 格式的词汇表 [HTML-RDFA]。 SHA2-256 摘要: fa3b8be58441dfdf11f5314330d612e0a9b9e94993076f3702418c511de71174
|
可以通过现代类 UNIX 操作系统命令行界面运行如下命令
来确认上述密码学摘要(将 <MEDIA_TYPE> 和 <DOCUMENT_URL> 替换为
相应值):
curl -sL -H "Accept: <MEDIA_TYPE>" <DOCUMENT_URL> | openssl dgst -sha256
执行 JSON-LD 处理的实现 MUST 将以下 JSON-LD 上下文 URL 视为已解析,其中已解析文档与 下方相应的哈希值匹配:
| 上下文 URL 和哈希 |
|---|
|
URL: https://www.w3.org/ns/credentials/status/v1 SHA2-256 摘要: fda5add353231e6a6884a46b12e6c75464281900cb348284d9c360f62381d9f7
|
可以通过现代类 UNIX 操作系统命令行界面运行如下
命令来确认上面列出的密码学摘要:
curl -sL -H "Accept: application/ld+json" https://www.w3.org/ns/credentials/status/v1 | openssl dgst -sha256
JSON-LD 上下文解析到的词汇表术语 位于 https://www.w3.org/ns/credentials/status# 命名空间中。更多详情见第 5.1 词汇表。
应用程序或规范可以使用其自己的 JSON-LD 上下文定义
到词汇表 URL 的映射。例如,本节提到的 JSON-LD 上下文定义
也是
https://www.w3.org/ns/credentials/v2 上下文的一部分,该上下文由
可验证凭证数据模型
v2.0规范定义。
本节是非规范性的。
本节详细说明将本规范部署到生产环境中的一般隐私考量和具体隐私 影响。
敦促读者在阅读本节之前,先熟悉 可验证凭证规范的 隐私考量章节中提供的一般 隐私建议。
本节是非规范性的。
本文档规定的最小撤销位串长度为 131,072,或 未压缩 16KB。如果已签发的可验证凭证数量足够大, 这足以为持有者提供足够的 群体隐私。然而,如果已签发可验证凭证的数量很小, 则由于位串中分配的 槽位数量较少,关联个人的能力会增加。将这些信息与例如 地理请求来源进行关联,也可能有助于关联来自同一地理区域 收到凭证的个人。
本节是非规范性的。
第 2.1 BitstringStatusListEntry 中定义的状态列表条目使用了若干全局标识符,
这些标识符可跨
验证者
用于关联主体。可以
表达这些值的一些属性包括 id、statusListIndex 和
statusListCredential。
在某些情况下,例如当展示包含全局标识符 (例如驾驶执照识别号码)的可验证凭证时, 为状态列表信息添加一个或多个全局标识符不会增加关联危害, 因为单个全局唯一 标识符已足以进行关联。
当全局标识符用于使用 选择性披露或 不可关联披露的 表示中时, 它们可能违反隐私 期望。当某个特定可验证凭证 预期以不需要关联的方式披露时,例如在 证明某个人超过某个年龄时,敦促发行者使状态信息能够被 选择性披露/隐藏。验证者可以要求 在需要了解凭证当前状态的情形下揭示状态信息,而持有者随后可以同意或拒绝 为给定交易揭示该信息。在所有情况下,都敦促发行者 和验证者 避免使用全局标识符,以防止 关联,除非某个特定交换要求或需要这样做。
有关其他类型潜在关联的信息, 敦促读者研究 可验证凭证数据模型 v2.0规范的隐私考量章节,尤其是关于 基于标识符的关联、 基于签名的关联、 基于长期标识符的关联,以及 基于元数据的关联的小节。
本节是非规范性的。
验证者可以通过缓存 从远程服务器获取的状态列表,来增强正在被检查的 持有者 及其可验证凭证的隐私。 通过在本地缓存内容,可以从基于 验证者的 状态列表访问模式中推断出更少可关联信息。
本节是非规范性的。
发行者使用内容分发网络,可以通过减少或消除 对来自发行者的 状态列表请求,来增强持有者的 隐私。通常,对撤销 列表的请求将由边缘设备提供服务,因此速度更快,并能减少 服务器负载,同时也使验证者和持有者 对发行者不可见。
本节是非规范性的。
已经探索了发行者在状态列表中使用 诱饵值作为一种机制,以增强主体的隐私。虽然采用诱饵 值的算法不在本规范范围内,但建议实现者注意: 如果诱饵值不能准确模拟与状态列表相关的人群, 使用诱饵值可能会损害隐私。如果诱饵值能够 与真实值区分开来,则集合中提供的匿名性将会因可检测到的 诱饵值数量而降低。最 保护隐私的状态列表是从不改变的状态列表,因为如果没有可观察事件发生, 就无法确定人群的行为。
鉴于对某个人群的状态条目进行统计模拟是非常困难的, 并且由于 可验证凭证 服务于广泛的用例,无法给出一般建议,因此建议实现者 随机分配状态列表条目索引,并最小化——最佳情况下是永不发生—— 状态条目被改变的频率。状态列表条目的分配在不触发 状态列表任何可观察变化时,最能保护隐私。
本节是非规范性的。
一般而言,本规范提供的群体隐私保护可以被恶意的 发行者和验证者绕过。只有当发行者和验证者意图避免 跟踪或共享特定凭证的展示时,其隐私 好处才能实现。
恶意验证者可能会通过与恶意发行者共享 已展示凭证中的信息,故意攻击 群体隐私。这种 串通很难检测,因为它通常通过发行者与验证者之间的 安全通信信道执行。
恶意发行者可能会通过为每个已签发凭证创建 唯一状态列表来故意攻击 群体隐私,以建立一对一映射来跟踪验证者何时处理每个映射的 凭证。类似地, 它们可以通过为给定状态列表跟踪的每个已签发凭证使用不同的 密码学密钥来建立一对一映射。
这种串通可以由服务于 多个持有者的 持有者软件检测到 (例如,运行在服务器上的持有者 应用),如果它 例如具有一个选择加入流程,该流程发现 可验证凭证中使用的一些全局标识符 并未被其他凭证充分共享。 然后,当持有者展示包含某些对该凭证唯一的全局标识符的 可验证凭证时,可以 向其发出警告。 这种选择加入服务可能带来一些额外的隐私问题; 通过持有者软件产生的这种潜在暴露 是否因意识到可能的全局标识符关联而合理,只能由此类系统的用户 评估。
本节是非规范性的。
一旦验证者 知道与特定持有者或主体相关联的状态列表和条目索引, 只要状态列表继续更新,该 验证者就可能看到该状态条目的 更新。这对于需要了解某个特定 可验证凭证何时 改变状态的验证者是有用的, 因为其无需直接向发行者请求关于 特定可验证凭证的状态 信息,或者在无法与持有者交互以获取 最新状态信息时。该特性也可能导致 持有者和/或主体的 隐私受到侵犯,如果 验证者能够对 可验证凭证的状态执行近实时检查。
发行者可以通过在相对较短的时间线内 撤销并重新签发实际上相同的 可验证凭证,为 持有者提供一定程度的 隐私顾虑缓解。 例如,发行者可以每三个月自动重新签发一个 可验证凭证, 并在重新签发发生时分配新的状态条目 索引,以打破随着 可验证凭证状态改变而产生的任何长期监控。
本节是非规范性的。
本规范提供了一种手段,使多个状态消息可以 为状态列表中的某个特定条目提供。虽然这种机制可以 为状态列表中的特定条目提供更详细的信息, 但这些信息可能提供进一步的关联数据。
例如,如果每条状态消息都与某个特定流程中的一个步骤相关联, 或者与凭证被撤销或暂停原因的更详细信息相关联, 那么观察列表变化的攻击者可能能够 关联有关列表中实体群体的信息, 从而导致隐私侵犯。了解一个人群如何 推进业务流程,或该人群中可能与某种状态相关联的百分比, 会向攻击者提供额外 信息。基于此类信息,网络钓鱼行动可以 预测业务流程的下一步是什么,然后预先 联系当前状态已知的实体。然后,基于这些 信息,他们可以尝试使用随时间从状态列表中收集的数据, 从目标处钓取更有价值的信息。
基于这些原因,敦促发行者评估以公开方式 发布关于特定实体或某个人群的详细状态信息的潜在影响。
本节是非规范性的。
当状态列表使用状态消息特性时, 发行者可以 随时间增加与其签发的 可验证凭证 相关联的消息类型。
这一特性会造成一种潜在的隐私侵犯,即 主体或持有者的 可验证凭证 可能与原始 可验证凭证 签发时不存在的额外状态信息 相关联。例如,初始状态 消息可能传达“延迟”和“取消”,但 发行者可能会添加额外状态消息,以传达“因未付款而延迟”和 “因非法活动而取消”。除非有代表 主体或持有者运行的监控软件 警告他们发行者打算暴露 关于其活动的额外信息,否则这种变化对他们并不明显。
持有者软件可以向持有者提供特性,以在使用 与状态消息相关联的 可验证凭证时, 警告他们持有者 和/或主体 信息暴露的程度,并在信息暴露程度发生变化时警告 他们。
本节是非规范性的。
实现者在处理本规范所描述的数据时,应当了解 若干安全考量。忽略或 不理解本节的影响,可能导致 安全漏洞。
敦促读者在阅读本节之前,先熟悉 可验证凭证规范的 安全考量章节中提供的一般 安全建议。
虽然本节试图突出一系列广泛的安全 考量,但它并不是完整列表。敦促实现者在使用本规范概述的技术 实现任务关键型系统时,寻求安全和密码学专业人士的 建议。
本节是非规范性的。
实现者特别注意其编码和解码位串的方式至关重要。 未能做到这一点可能导致针对给定凭证检查 错误的位串索引,从而错误解释 其当前状态(例如,将已撤销状态误认为未撤销 状态)。如第 2.2 BitstringStatusListCredential 所述, 位串的编码方式使第一个(第零个)索引引用 位串数组中最左侧的位。下图展示了 未压缩位串的正确布局。
例如,如果位串大小为 131,072 位(16KB),第一个索引将 是 0,最后一个索引将是 131,071。
本节是非规范性的。
发行者可能选择在状态列表中表达的有效期 取决于多种 因素,包括:
由于这些因素会随生态系统和凭证类型而变化,因此不存在 建议适用于所有状态列表的最小或最大有效期。 发行者需要 考虑各种特定于其 可验证凭证 类型的因素,并选择能够在其生态系统中取得 适当平衡的有效期。
本节是非规范性的。
敦促读者熟悉 可验证凭证规范的 无障碍考量章节中提供的一般 无障碍建议。除面向所有可验证凭证的一般建议外, 本规范不再提供进一步建议。
本节是非规范性的。
敦促读者熟悉 可验证凭证规范的 国际化考量章节中提供的一般 国际化建议。除面向所有可验证凭证的一般建议外, 本规范不再提供进一步建议。
本节是非规范性的。
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"id": "https://example.com/credentials/23894672394",
"type": ["VerifiableCredential"],
"issuer": "did:example:12345",
"validFrom": "2021-04-05T14:27:42Z",
"credentialStatus": {
"id": "https://example.com/credentials/status/3#94567",
"type": "BitstringStatusListEntry",
"statusPurpose": "revocation",
"statusListIndex": "94567",
"statusListCredential": "https://example.com/credentials/status/3"
},
"credentialSubject": {
"id": "did:example:6789",
"type": "Person"
}
}
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"id": "https://example.com/credentials/23894672394",
"type": [
"VerifiableCredential"
],
"issuer": "did:example:12345",
"validFrom": "2021-04-05T14:27:42Z",
"credentialStatus": {
"id": "https://example.com/credentials/status/3#94567",
"type": "BitstringStatusListEntry",
"statusPurpose": "revocation",
"statusListIndex": "94567",
"statusListCredential": "https://example.com/credentials/status/3"
},
"credentialSubject": {
"id": "did:example:6789",
"type": "Person"
},
"proof": {
"type": "DataIntegrityProof",
"created": "2025-04-27T20:53:40Z",
"verificationMethod": "did:key:zDnaewCdcZ4ERAPqpnobQrwXcCRqCw7tWR95DSnQPaMhwJJnv",
"cryptosuite": "ecdsa-rdfc-2019",
"proofPurpose": "assertionMethod",
"proofValue": "z5BvvQfoLh7oUysotjUb5Ru2pEg1cTUg4C4eu5nvhzaDg6BGstD5tUaTkwGhsevuG1jQ72kY1uKvXdp9faaVJnEFw"
}
}
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"id": "https://example.com/credentials/23894672394",
"type": [
"VerifiableCredential"
],
"issuer": "did:example:12345",
"validFrom": "2021-04-05T14:27:42Z",
"credentialStatus": {
"id": "https://example.com/credentials/status/3#94567",
"type": "BitstringStatusListEntry",
"statusPurpose": "revocation",
"statusListIndex": "94567",
"statusListCredential": "https://example.com/credentials/status/3"
},
"credentialSubject": {
"id": "did:example:6789",
"type": "Person"
},
"proof": {
"type": "DataIntegrityProof",
"created": "2025-04-27T20:53:40Z",
"verificationMethod": "did:key:z6MkeVw6bAm59CopQquZcVLUpapvEEELqfpdWfHkSont8HR6",
"cryptosuite": "eddsa-rdfc-2022",
"proofPurpose": "assertionMethod",
"proofValue": "z2Gjztpjjb7iJxNF9YZ4ssG6qTuv48XhsqTnMobv4ofFD12NNaeZmgwgkkPtYKHyESuEe1AHNBavjJaPbH9ZZJqxk"
}
}
{
"kid": "ExHkBMW9fmbkvV266mRpuP2sUY_N_EWIN1lapUzO8ro",
"alg": "ES256"
}
application/vc
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"id": "https://example.com/credentials/23894672394",
"type": [
"VerifiableCredential"
],
"issuer": "did:example:12345",
"validFrom": "2021-04-05T14:27:42Z",
"credentialStatus": {
"id": "https://example.com/credentials/status/3#94567",
"type": "BitstringStatusListEntry",
"statusPurpose": "revocation",
"statusListIndex": "94567",
"statusListCredential": "https://example.com/credentials/status/3"
},
"credentialSubject": {
"id": "did:example:6789",
"type": "Person"
}
}
application/vc+jwt
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"id": "https://example.com/credentials/23894672394",
"type": [
"VerifiableCredential"
],
"issuer": "did:example:12345",
"validFrom": "2021-04-05T14:27:42Z",
"credentialStatus": {
"id": "https://example.com/credentials/status/3#94567",
"type": "BitstringStatusListEntry",
"statusPurpose": "revocation",
"statusListIndex": "94567",
"statusListCredential": "https://example.com/credentials/status/3"
},
"credentialSubject": {
"id": "did:example:6789",
"type": "Person"
}
}
application/vc+cose
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"id": "https://example.com/credentials/status/3",
"type": ["VerifiableCredential", "BitstringStatusListCredential"],
"issuer": "did:example:12345",
"validFrom": "2021-04-05T14:27:40Z",
"credentialSubject": {
"id": "https://example.com/status/3#list",
"type": "BitstringStatusList",
"statusPurpose": "revocation",
"encodedList": "uH4sIAAAAAAAAA-3BMQEAAADCoPVPbQwfoAAAAAAAAAAAAAAAAAAAAIC3AYbSVKsAQAAA"
}
}
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"id": "https://example.com/credentials/status/3",
"type": [
"VerifiableCredential",
"BitstringStatusListCredential"
],
"issuer": "did:example:12345",
"validFrom": "2021-04-05T14:27:40Z",
"credentialSubject": {
"id": "https://example.com/status/3#list",
"type": "BitstringStatusList",
"statusPurpose": "revocation",
"encodedList": "uH4sIAAAAAAAAA-3BMQEAAADCoPVPbQwfoAAAAAAAAAAAAAAAAAAAAIC3AYbSVKsAQAAA"
},
"proof": {
"type": "DataIntegrityProof",
"created": "2025-04-27T20:53:40Z",
"verificationMethod": "did:key:zDnaewCdcZ4ERAPqpnobQrwXcCRqCw7tWR95DSnQPaMhwJJnv",
"cryptosuite": "ecdsa-rdfc-2019",
"proofPurpose": "assertionMethod",
"proofValue": "z5bsyxwuDdVqgh7eXAPZaXQvuixSHXXoodfjsp8hGiLoJknAFZJuasbkioubs4bbjKTkwLfc6NT6V1Ye6BWKUDdXU"
}
}
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"id": "https://example.com/credentials/status/3",
"type": [
"VerifiableCredential",
"BitstringStatusListCredential"
],
"issuer": "did:example:12345",
"validFrom": "2021-04-05T14:27:40Z",
"credentialSubject": {
"id": "https://example.com/status/3#list",
"type": "BitstringStatusList",
"statusPurpose": "revocation",
"encodedList": "uH4sIAAAAAAAAA-3BMQEAAADCoPVPbQwfoAAAAAAAAAAAAAAAAAAAAIC3AYbSVKsAQAAA"
},
"proof": {
"type": "DataIntegrityProof",
"created": "2025-04-27T20:53:40Z",
"verificationMethod": "did:key:z6MkeVw6bAm59CopQquZcVLUpapvEEELqfpdWfHkSont8HR6",
"cryptosuite": "eddsa-rdfc-2022",
"proofPurpose": "assertionMethod",
"proofValue": "z4hwxiLnXHLUAomJXtfoowKc1ZBNpw1Wjw1vYsXEvifETSh6odbtmh6qfEDijRBxCZJ5hjguPotaywncvcHQ9yfRf"
}
}
{
"kid": "ExHkBMW9fmbkvV266mRpuP2sUY_N_EWIN1lapUzO8ro",
"alg": "ES256"
}
application/vc
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"id": "https://example.com/credentials/status/3",
"type": [
"VerifiableCredential",
"BitstringStatusListCredential"
],
"issuer": "did:example:12345",
"validFrom": "2021-04-05T14:27:40Z",
"credentialSubject": {
"id": "https://example.com/status/3#list",
"type": "BitstringStatusList",
"statusPurpose": "revocation",
"encodedList": "uH4sIAAAAAAAAA-3BMQEAAADCoPVPbQwfoAAAAAAAAAAAAAAAAAAAAIC3AYbSVKsAQAAA"
}
}
application/vc+jwt
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"id": "https://example.com/credentials/status/3",
"type": [
"VerifiableCredential",
"BitstringStatusListCredential"
],
"issuer": "did:example:12345",
"validFrom": "2021-04-05T14:27:40Z",
"credentialSubject": {
"id": "https://example.com/status/3#list",
"type": "BitstringStatusList",
"statusPurpose": "revocation",
"encodedList": "uH4sIAAAAAAAAA-3BMQEAAADCoPVPbQwfoAAAAAAAAAAAAAAAAAAAAIC3AYbSVKsAQAAA"
}
}
application/vc+cose
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"id": "https://example.com/credentials/23894672394",
"type": ["VerifiableCredential"],
"issuer": "did:example:12345",
"issuanceDate": "2021-04-05T14:27:42Z",
// 注意使用数组来表示
// 状态条目集合
"credentialStatus": [{
"id": "https://example.com/credentials/status/3#94567",
"type": "BitstringStatusListEntry",
"statusPurpose": "revocation",
"statusListIndex": "94567",
"statusListCredential": "https://example.com/credentials/status/3"
}, {
"id": "https://example.com/credentials/status/4#12345",
"type": "BitstringStatusListEntry",
"statusPurpose": "suspension",
"statusListIndex": "12345",
"statusListCredential": "https://example.com/credentials/status/4"
}],
"credentialSubject": {
"id": "did:example:6789",
"type": "Person"
}
}
单个状态列表可以包含多种类型的状态 目的。这样做可能使检索一个列表比获取多个状态列表 略微更高效。
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"id": "https://example.com/credentials/23894672394",
"type": ["VerifiableCredential"],
"issuer": "did:example:12345",
"issuanceDate": "2021-04-05T14:27:42Z",
// 注意使用单个列表来存储多个
// 状态条目
"credentialStatus": [{
"id": "https://example.com/credentials/status/5#94567",
"type": "BitstringStatusListEntry",
"statusPurpose": "revocation",
"statusListIndex": "94567",
"statusListCredential": "https://example.com/credentials/status/5"
}, {
"id": "https://example.com/credentials/status/5#12345",
"type": "BitstringStatusListEntry",
"statusPurpose": "suspension",
"statusListIndex": "12345",
"statusListCredential": "https://example.com/credentials/status/5"
}],
"credentialSubject": {
"id": "did:example:6789",
"type": "Person"
}
}
本节包含本规范随时间推移所做的实质性更改。
自 v1.0 第一候选推荐标准以来的更改:
ttl 属性不会覆盖有效性。
refresh 状态目的。