本规范描述了一种使用位串发布状态信息(如可验证凭证的暂停或撤销)的隐私保护、空间高效且高性能的机制。

介绍

对于可验证凭证发行者 [[VC-DATA-MODEL-2.0]],链接到一个验证者可以检查凭证是否已被暂停或撤销的位置通常是有用的。在设计、发布和处理状态列表时,需要考虑各种隐私和性能问题。

一种隐私问题发生在可验证凭证与发布状态的URL之间存在一对一映射时。这种映射使得发布URL的网站能够关联持有者、时间和验证者的状态检查。这可能使发行者发现持有者验证者的交互类型,例如在进入酒吧时提供年龄验证凭证。当进入场所时被驾驶执照的发行者跟踪,违反了许多人今天的隐私期望。

类似地,在设计状态列表时也需要考虑性能问题。其中一个考虑是列表的发布位置以及它对服务器和获取信息的客户端在带宽和处理方面的负担。为了满足隐私期望,将大量凭证的状态捆绑到一个列表中以帮助实现群体隐私是有用的。然而,如果每个凭证的状态信息大小达到几百字节,并且覆盖数亿持有者的人群,这可能会对服务器和客户端造成无法承受的负担。

本文档的其余部分提出了一种具有强隐私保护特性的高压缩位串状态列表机制,该机制与Web架构兼容,具有高度的空间效率,并且非常适合内容分发网络。作为使用本规范实现多种隐私和性能目标的一个示例,可以为100,000个可验证凭证创建一个状态列表,其最坏情况下的大小约为12,500字节。在少数几百个凭证被撤销的情况下,列表的大小小于几百字节,同时在100,000人的群体中提供隐私。

概念框架

本节概述了本规范描述的状态列表机制所使用的核心概念。在最基本的层面上,所有由发行者发布的可验证凭证的状态信息以列表项的形式表示。每个发行者管理其发布的所有可验证凭证的列表。每个可验证凭证与其列表中的一个项相关联。当单个位指定状态(例如“已撤销”或“已暂停”)时,该状态在位被设置为`1`时为真,在未设置为`0`时为假。

使用位串的一个好处是它是一种高度可压缩的数据格式,因为在平均情况下,大量凭证将保持未撤销状态。这将确保长段的位值相同,从而可以使用诸如GZIP [[RFC1952]]之类的运行长度压缩技术进行高度压缩。默认状态列表大小为131,072个条目,相当于16 KB的单个位值。当只有少数可验证凭证被撤销时,GZIP将位串压缩到几百字节。

使用位串的另一个好处是它允许大量可验证凭证状态放置在同一个列表中。本规范使用最小列表长度为131,072。这种大小在平均情况下确保了足够的群体隐私。如果需要更好的群体隐私,可以将位串设置得更大。


           图示显示了图像顶部的一组框,其中两个框为红色,表示已撤销的凭证。框右侧的文字显示为16千字节。图像底部显示这些框被GZIP压缩成一个圆柱体,压缩后的最终大小为135字节。
本节概述的概念的视觉描述。

与特定可验证凭证相关的状态信息是关于可验证凭证本身的,可能不适用于任何基础或支持的凭证,例如教育学位。例如,在这种教育学位的情况下,可能会因为用于创建其数字签名的机制被破坏而撤销可验证凭证,而支持的教育学位仍然有效。

术语

本文档中使用的术语在[[[VC-DATA-MODEL-2.0]]]规范的 术语部分中定义。

符合文档是任何遵循第节中相关规范性要求的数据模型的具体表达。

符合处理器是任何以软件和/或硬件实现的算法,根据第节中的相关规范性声明生成和/或消费[=符合文档=]。符合处理器可以选择仅支持位串条目大小为1。符合处理器在消费不符合的文档时必须产生错误。

数据模型

有多种方式可以表达与数字凭证相关的状态信息。这些机制包括证书吊销列表(CRL)[[?RFC5280]]、在线证书状态协议(OCSP)[[?RFC2560]]、布隆过滤器[[?RFC8932]]和加密累加器[[?ALLOSAUR]]。本规范针对不同于其他机制的各种需求进行了优化。这些需求包括:

技术 CRL OCSP 布隆过滤器 累加器 位串
提供可调节的群体隐私
不需要为每个凭证签署断言
验证者获取时对发行者的跟踪具有抵抗性
在存在大量吊销时缓存空间高效
高度可压缩(平均压缩率超过90%)
更新高效(快速且无需整个群体更新)
使用IETF批准的加密原语
无误报
可由持有者传递(绑定)
易于为可验证凭证使用进行配置

位串状态列表条目

发行者希望为可验证凭证启用状态信息时,他们可以添加一个`credentialStatus`属性,该属性使用本节中描述的数据模型。本节中的数据模型的任何表达形式都必须以[[VC-DATA-MODEL-2.0]]中定义的符合可验证凭证的形式表达。

属性 描述
id 一个可选的状态列表条目的标识符。`id`属性的约束在可验证凭证数据模型规范[[VC-DATA-MODEL-2.0]]中列出。如果存在,该值应为一个URL,用于标识与可验证凭证相关的状态信息。它不能是状态列表的URL。该值在验证或校验过程中不使用,也不需要与`statusListCredential`值相关。如果需要,该值可以用于唯一标识`BitstringStatusListEntry`对象,例如在数据库中存储时。
type `type`属性必须为`BitstringStatusListEntry`。
statusPurpose 状态条目的用途必须是一个字符串。虽然字符串的值是任意的,但以下值必须用于其预期用途:
描述
`refresh` 用于表示通过凭证的刷新服务功能可获得更新的可验证凭证。此状态不会使可验证凭证失效,并且不可逆。
`revocation` 用于取消可验证凭证的有效性。此状态不可逆。
`suspension` 用于暂时阻止接受可验证凭证。此状态是可逆的。
`message` 用于传达与可验证凭证状态相关的任意消息。
statusListIndex `statusListIndex`属性必须是一个大于或等于0的任意大小的整数,以十进制字符串表示。该值标识可验证凭证状态的位置。实现应随机分配索引,以避免推断出分配的时间或群体的大小等信息。
statusListCredential `statusListCredential`属性必须是指向可验证凭证的URL。当该URL被解析时,结果可验证凭证必须具有包含`BitstringStatusListCredential`值的`type`属性。
statusSize `statusSize`表示状态条目的位大小。`statusSize`可以提供。如果`statusSize`未作为`credentialStatus`的属性提供,则`statusSize`必须被处理为`1`。如果提供,`statusSize`必须是大于零的整数。如果`statusSize`的值大于`1`,则`credentialStatus.statusMessage`属性必须存在,并且状态消息的数量必须等于可能值的数量。
statusMessage 如果存在,`statusMessage`属性必须是一个数组,其长度必须等于`statusSize`指示的可能状态消息的数量(例如,如果`statusSize`为1位,则`statusMessage`数组必须有2个元素;如果`statusSize`为2位,则有4个元素;如果`statusSize`为3位,则有8个元素,依此类推)。如果`statusSize`为`1`,`statusMessage`可以存在;如果`statusSize`大于`1`,则`statusMessage`必须存在。如果`statusMessage`数组不存在,则与`1`和`0`状态位值相关联的消息值分别为“set”和“unset”。如果`statusMessage`数组存在,每个元素必须包含以下两个属性,并可以包含其他属性:
  • `status`,一个表示状态的十六进制值的字符串,以`0x`为前缀。
  • `message`,一个供软件开发人员调试使用的字符串,不应显示给最终用户。
实现者可以向`statusMessage`数组中的对象添加其他值。实现者可以在值中使用字符串值`undefined`,以指示与相关状态值对应的状态未定义,但可能在未来定义。如何处理各种状态消息的规则超出了本规范的规范性要求范围,但假定实现者将记录处理各种状态代码的规则。
statusReference 实现者可以包含`statusReference`属性。如果存在,其值必须是一个URL或URL数组[[URL]],这些URL解析为与状态相关的材料。使用`message`作为`statusPurpose`的实现者强烈建议提供`statusReference`。

`statusReference`在凭证的状态解释可能涉及对业务案例的理解时尤为重要。

位串状态列表凭证

当状态列表可验证凭证被发布时,它必须是一个符合[[VC-DATA-MODEL-2.0]]定义的文档,并以本节中描述的数据模型形式表达。以下部分描述了封装状态列表的可验证凭证的格式。

状态列表以可验证凭证的形式表达,以便持有者可以直接将其提供给验证者。这种机制有时被称为“证书绑定”,通过确保验证者无需联系发行者来检索状态列表,从而提高了持有者的隐私性。然而,如果验证者希望获取更近期的状态列表版本,即使其真实性是可验证的,也可能选择忽略由持有者提供的状态列表。

建议发行者验证者注意,可验证凭证发行者和相关`BitstringStatusListCredential`的发行者可能并不相同。由于技术、法律、机构、政治及其他原因,将原始凭证的管理权与撤销或更改凭证状态的管理权分离可能是合适的。因此,包含`BitstringStatusListEntry`的可验证凭证的`issuer`值可以与`BitstringStatusListCredential`的`issuer`值不同。

属性 描述
id 包含状态列表的可验证凭证可以表达一个`id`属性,其值应与对应`BitstringStatusListEntry`中`statusListCredential`指定的值匹配(参见)。
type 包含状态列表的可验证凭证必须表达一个`type`属性,其中包括`BitstringStatusListCredential`值。
validFrom 状态列表有效的最早时间点。此属性在《可验证凭证数据模型规范》第4.6节:有效期中定义。
validUntil 状态列表有效的最晚时间点。此属性在《可验证凭证数据模型规范》第4.6节:有效期中定义。
credentialSubject.type 凭证主体的`type`,即状态列表,必须为`BitstringStatusList`。
credentialSubject.statusPurpose 状态条目的用途属性`statusPurpose`的值必须是一个或多个字符串。虽然每个字符串的值是任意的,但以下值必须用于其预期用途:
描述
`refresh` 用于表示通过凭证的刷新服务功能可获得更新的可验证凭证。此状态不会使可验证凭证失效,并且不可逆。
`revocation` 用于取消可验证凭证的有效性。此状态不可逆。
`suspension` 用于暂时阻止接受可验证凭证。此状态是可逆的。
`message` 用于指示与可验证凭证相关的状态消息。状态消息描述必须在`credentialSubject.statusMessages`中定义。当使用此`statusPurpose`值时,必须指定`credentialSubject.statusSize`。
credentialSubject.encodedList 凭证主体的`encodedList`属性必须是多基编码的base64url(无填充) [[RFC4648]] 表示形式,表示与相关可验证凭证状态值范围对应的GZIP压缩[[RFC1952]]位串值。未压缩的位串必须至少为16KB大小。位串的编码方式必须确保索引为零(`0`)的值位于位串的最左侧,而索引为位串长度减一(`bitstring_length - 1`)的值位于位串的最右侧。有关位串编码的更多信息,请参见
credentialSubject.ttl `ttl`是一个可选属性,表示在尝试刷新之前的“生存时间”(以毫秒为单位)。如果未提供,则不假定默认值。该值不会覆盖或替代`BitstringStatusList`的有效期。发布状态列表的实现应将任何协议特定的缓存信息(例如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"
        }
      }
        

算法

以下部分概述了本文档中描述的用于生成和验证状态列表的算法。

如果本节中的任何算法在处理第节中定义的属性时,由于未遵守相关的“必须(MUST)”声明而导致值格式错误,则必须引发MALFORMED_VALUE_ERROR

生成算法

在生成Bitstring状态列表凭证时,必须遵循以下过程或生成完全相同的输出。该算法以|已发行凭证|列表作为输入,并抛出错误或返回状态列表凭证作为输出。

  1. 令|已发行凭证|为所有已发行的可验证凭证的列表。
  2. 令|状态列表凭证|为一个未签名的Bitstring状态列表凭证,且未设置`encodedList`属性。
  3. 通过将|已发行凭证|传递给位串生成算法生成|压缩位串|。
  4. 将`encodedList`设置为|压缩位串|。
  5. 为|状态列表凭证|生成一个证明,并将其发布到可验证凭证中列出的端点。

发行者应以可缓存且不会跟踪谁检索状态列表凭证的方式发布状态列表凭证,例如通过[[[RFC9458]]]、由非发行者运营的内容分发网络,或数据分析师或系统管理员无法访问访问日志的业务流程。

验证算法

在验证包含于Bitstring状态列表凭证中的可验证凭证时,必须遵循以下过程或生成完全相同的输出。该算法以状态列表可验证凭证作为输入,并抛出错误或返回状态列表凭证作为输出。

  1. 令|待验证凭证|为包含`credentialStatus`条目的可验证凭证,该条目是Bitstring状态列表条目
  2. 令|最小条目数|为131,072,除非特定生态系统规范建立了不同的下限。
  3. 令|状态用途|为|待验证凭证|中`credentialStatus`条目中的`statusPurpose`值。
  4. 解析`statusListCredential` URL,并确保所有证明验证成功。如果解析失败,则引发STATUS_RETRIEVAL_ERROR。如果任何证明验证失败,则引发STATUS_VERIFICATION_ERROR
  5. 验证|状态用途|是否等于|状态列表凭证|中的`statusPurpose`值。注意:|状态列表凭证|可能在单个列表中包含多个状态用途。如果值不相等,则引发STATUS_VERIFICATION_ERROR
  6. 令|压缩位串|为Bitstring状态列表凭证的`encodedList`属性的值。
  7. 令|凭证索引|为Bitstring状态列表条目的`statusListIndex`属性的值。
  8. 通过将|压缩位串|传递给位串展开算法生成|撤销位串|。
  9. 如果|撤销位串|的长度除以`statusSize`小于|最小条目数|,则引发STATUS_LIST_LENGTH_ERROR
  10. 令|状态|为|位串|中由|凭证索引|乘以|大小|指示的位置的值。如果|凭证索引|乘以|大小|的值超出|位串|的范围,则必须引发RANGE_ERROR
  11. 令|结果|为一个空的映射
  12. 将|结果|中的`status`键设置为|状态|,并将`purpose`键设置为`statusPurpose`的值。
  13. 如果|状态|为`0`,将|结果|中的`valid`键设置为`true`;否则,将其设置为`false`。
  14. 如果`statusPurpose`为`message`,将|结果|中的`message`键设置为`statusMessages`数组中对应`value`的消息。
  15. 返回|结果|。

当解析`statusListCredential` URL时,服务器实现可以提供一种机制,以解析特定时间点的状态列表。当发行者提供此类机制时,它使验证者能够以发行者选择的精度(例如每小时、每天或每周)确定状态的变化。如果支持此功能,并且URL方案支持查询参数,则查询参数的名称必须为`timestamp`,其值必须是有效的URL编码[[XMLSCHEMA11-2]] dateTimeStamp字符串值。解析此类带时间戳参数的URL的结果必须是包含给定时间点状态列表的状态列表凭证,或STATUS_RETRIEVAL_ERROR。如果结果是错误,实现可以尝试使用不同的时间戳值或不带时间戳值再次检索,只要验证者的验证规则允许此类操作。

验证者应缓存检索到的状态列表,并应使用代理或其他机制(例如[[[RFC9458]]]),以隐藏检索行为不被发行者发现。

预计验证者将确保其信任可验证凭证的发行者以及相关Bitstring状态列表凭证的发行者,然后再使用这两个凭证中包含的信息进行进一步的决策。建议实现者注意,这些凭证的发行者可能不同,例如当可验证凭证的原始发行者不维护其有效性记录时。

位串生成算法

以下过程或生成完全相同输出的过程,必须(MUST)在生成状态列表位串时遵循。该算法以|已发行凭证|列表作为输入,并抛出错误或返回|压缩位串|作为输出。

  1. 令|位串|为一个最小大小为16KB的位列表,其中每个位初始化为0(零)。
  2. 对于`位串`中的每个值,如果`已发行凭证`中的某个凭证具有对应的`statusListIndex`值,则将该值设置为适当的状态。值的位置通过`statusListIndex`乘以`statusSize`计算。
  3. 使用GZIP压缩算法[[RFC1952]]对|位串|进行压缩生成|压缩位串|,然后使用base64url(无填充)多基编码对结果进行编码。
  4. 返回|压缩位串|。

位串展开算法

以下过程或生成完全相同输出的过程,必须(MUST)在展开压缩状态列表位串时遵循。该算法以|压缩位串|作为输入,并抛出错误或返回|未压缩位串|作为输出。

  1. 令|压缩位串|为一个压缩的状态列表位串。
  2. 使用多基解码算法对|压缩位串|进行解码,然后使用GZIP解压缩算法[[RFC1952]]展开输出,生成|未压缩位串|。
  3. 返回|未压缩位串|。

处理错误

本规范中描述的算法会抛出特定类型的错误。实现者可能会发现将这些错误传递给其他库或软件系统是有用的。本节提供了错误的特定URL、描述和错误代码,以便实现本规范所述技术的生态系统在发生错误时能够更有效地互操作。

当通过HTTP接口暴露这些错误时,实施者应(SHOULD)使用[[[RFC9457]]]来编码错误数据结构。如果使用[[RFC9457]]:

STATUS_RETRIEVAL_ERROR
状态列表的检索失败。参见第节。
STATUS_VERIFICATION_ERROR
状态条目的验证失败。参见第节。
STATUS_LIST_LENGTH_ERROR
状态列表长度未满足群体隐私所需的最小长度要求。参见第节。

算法安全性

节中的信息可以通过多种方式进行保护。这些机制在[[[VC-DATA-MODEL-2.0]]]的安全机制部分中详细说明。

当保护包含对Bitstring状态列表凭证引用的可验证凭证时,实施者应(SHOULD)对两个可验证凭证使用相同的保护机制、相同的加密参数和相同的媒体类型。

媒体类型

在解析 `statusListCredential` 时,返回的 `statusListCredential` 内容可能是任何用于表达具有一个或多个证明的可验证凭证的已注册媒体类型。

例如,使用数据完整性证明保护的可验证凭证可能具有媒体类型 `application/vc`,而使用 SD-JWT 保护的可验证凭证可能具有媒体类型 `application/sd-jwt`。

某些实现可能选择支持更不具体的媒体类型,例如 `application/ld+json` 或 `application/json`。

在通过 HTTP 解析时,使用 acceptcontent-type 头,可能允许某些实现协商用于保护 `statusListCredential` 的证明格式。

某些实现可能使用 415 Unsupported Media Type 状态码来表示它们不支持请求的媒体类型。

上下文和词汇表

词汇表

本规范中定义的术语也是 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 摘要:
text/turtle Turtle 格式的词汇表 [[?TURTLE]]。
SHA2-256 摘要:
text/html HTML+RDFa 格式的词汇表 [[?HTML-RDFA]]。
SHA2-256 摘要:

可以通过在现代类 UNIX 操作系统的命令行界面中运行如下命令(用适当的值替换 `<MEDIA_TYPE>` 和 `<DOCUMENT_URL>`)来确认上述加密摘要: `curl -sL -H "Accept: <MEDIA_TYPE>" <DOCUMENT_URL> | openssl dgst -sha256`

JSON-LD 上下文

执行 JSON-LD 处理的实现必须(MUST)将以下 JSON-LD 上下文 URL 视为已解析,其中解析的文档与下面的对应哈希值匹配:

上下文 URL 和哈希
URL: https://www.w3.org/ns/credentials/status/v1
SHA2-256 摘要:

可以通过在现代类 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# 命名空间中。有关详细信息,请参见第 [[[#vocabulary]]] 节。

应用程序或规范可以使用它们自己的 JSON-LD 上下文定义到词汇表 URL 的映射。例如,本节中引用的 JSON-LD 上下文定义也是 [[[?VC-DATA-MODEL-2.0]]] 规范定义的 `https://www.w3.org/ns/credentials/v2` 上下文的一部分。

隐私注意事项

本节详细说明了将本规范部署到生产环境中的一般隐私注意事项和具体隐私影响。

建议读者在阅读本节之前,先熟悉《可验证凭证规范》中的隐私注意事项部分中提供的一般隐私建议。

撤销位串长度

本文档规定了最小撤销位串长度为131,072位,或16KB未压缩。这足以在颁发的可验证凭证数量足够大的情况下,为持有者提供足够的群体隐私。然而,如果颁发的可验证凭证数量较少,由于位串中分配的槽位较少,关联个人的能力会增加。例如,将此信息与地理请求来源相关联,也可能有助于关联从同一地理区域接收凭证的个人。

不必要的关联

状态列表条目中定义的多个全局标识符(参见第[[[#bitstringstatuslistentry]]]节)可以被验证者用来关联主体。这些值可以通过`id`、`statusListIndex`和`statusListCredential`等属性表达。

在某些情况下,例如在展示包含全局标识符(如驾驶证号码)的可验证凭证时,为状态列表信息添加一个或多个全局标识符不会增加关联危害,因为只需要一个全局唯一标识符即可进行关联。

当在使用选择性披露不可关联披露展示中使用全局标识符时,它们可能会违反隐私预期。建议发行者在预期以不需要关联的方式披露特定可验证凭证时,使状态信息可以选择性披露/隐藏,例如在证明某人超过某个年龄时。验证者可以在需要了解凭证当前状态的情况下要求披露状态信息,而持有者可以选择同意或拒绝在特定交易中披露该信息。在所有情况下,建议发行者验证者避免使用全局标识符,以防止关联,除非特定交换需要或要求这样做。

有关其他类型潜在关联的信息,建议读者研究[[[VC-DATA-MODEL-2.0]]]规范中的隐私注意事项部分,特别是以下子部分: 基于标识符的关联基于签名的关联基于长期标识符的关联基于元数据的关联

验证者缓存

验证者可以通过缓存从远程服务器获取的状态列表来提高持有者的隐私性。通过本地缓存内容,可以从基于验证者的状态列表访问模式中推断出更少的可关联信息。

内容分发网络

发行者使用内容分发网络可以通过减少或消除对状态列表的请求来提高持有者的隐私性。通常,对撤销列表的请求将由边缘设备提供服务,从而更快并减少服务器负载,同时掩盖验证者持有者的身份,使其不被发行者发现。

诱饵值

发行者在状态列表中使用诱饵值已被探索为一种增加主体隐私的机制。虽然使用诱饵值的算法超出了本规范的范围,但建议实现者注意,如果诱饵值未能准确模拟与状态列表相关的人群,则可能会损害隐私。如果诱饵值可以与真实值区分开来,则集合中提供的匿名性将因可检测的诱饵值数量而减少。最具隐私保护的状态列表是从未更改的状态列表,因为如果没有可观察的事件发生,就无法确定人群的行为。

鉴于为人群统计模拟状态条目是多么困难,并且由于可验证凭证服务于广泛的用例,无法给出一般建议,建议实现者随机分配状态列表条目索引,并尽量减少——最好是永远不要——更改状态条目的频率。当状态列表分配不会触发任何可观察的更改时,状态列表条目的分配最能保护隐私。

恶意发行者和验证者

通常,本规范提供的群体隐私保护可以被恶意发行者验证者规避。只有当发行者和验证者有意避免跟踪或共享特定凭证的展示时,其隐私优势才能实现。

恶意验证者可能通过与恶意发行者共享展示的凭证信息来故意攻击群体隐私。这种勾结通常通过发行者验证者之间的安全通信渠道进行,因此难以检测。

恶意发行者可能通过为每个颁发的凭证创建唯一的状态列表来故意攻击群体隐私,以建立一对一的映射,从而跟踪验证者何时处理每个映射的凭证。同样,他们可以通过为每个颁发的凭证使用不同的加密密钥并将其与给定状态列表跟踪来建立一对一的映射。

这种勾结可以通过服务于多个持有者持有者软件(例如运行在服务器上的持有者应用程序)检测到,例如通过一个选择加入的过程,发现某些可验证凭证中使用的全局标识符未被其他凭证充分共享。 持有者可以在展示包含某些唯一全局标识符的可验证凭证时收到警告。此类选择加入服务可能会带来一些额外的隐私问题;是否通过持有者软件的潜在暴露来换取可能的全局标识符关联的意识,只能由此类系统的用户评估。

监控状态列表

一旦验证者知道与特定持有者或主体相关联的状态列表和条目索引,该验证者就可以在状态列表继续更新的情况下看到该状态条目的更新。这对需要了解特定可验证凭证状态何时发生变化的验证者很有用,而无需直接向发行者询问特定可验证凭证的状态信息,或者在无法与持有者交互以获取最新状态信息时使用。然而,如果验证者能够对可验证凭证的状态进行近乎实时的检查,这一功能也可能对持有者和/或主体造成隐私侵犯。

发行者可以通过在相对较短的时间内吊销并重新颁发相同的可验证凭证,为持有者提供一定程度的隐私保护。例如,发行者可以每三个月自动重新颁发一次可验证凭证,并在重新颁发时分配一个新的状态条目索引,以打破对可验证凭证状态变化的长期监控。

状态消息的关联

本规范提供了一种机制,可以为状态列表中的特定条目提供多个状态消息。虽然此机制可以为状态列表中的特定条目提供更详细的信息,但这些信息可能提供进一步的关联数据。

例如,如果每个状态消息都与特定流程中的一个步骤相关联,或者提供有关凭证为何被吊销或暂停的更详细信息,那么观察列表变化的攻击者可能能够关联列表中实体群体的信息,从而导致隐私侵犯。了解一个群体如何在业务流程中进展,或者群体中有多少百分比可能与某种状态相关联,可以为攻击者提供额外的信息。基于此类信息,网络钓鱼操作可以预测业务流程的下一步,然后抢先联系当前状态已知的实体。然后,基于这些信息,他们可以尝试通过从状态列表中随时间收集的数据,从目标中钓取更有价值的信息。

因此,建议发行者评估以公开方式发布有关特定实体或群体的详细状态信息的潜在影响。

状态消息的更改

当状态列表使用状态消息功能时,发行者可以随着时间的推移增加与其颁发的可验证凭证相关联的消息类型。

此功能可能会造成隐私侵犯,因为主体或持有者可能会与原始可验证凭证颁发时不存在的额外状态信息相关联。例如,初始状态消息可能传达“延迟”和“取消”,但发行者可能会增加额外的状态消息以传达“因未付款延迟”和“因非法活动取消”。除非有代表他们运行的监控软件警告他们发行者打算公开有关其活动的额外信息,否则主体或持有者无法察觉到这些更改。

持有者软件可以为持有者提供功能,在使用与状态消息相关联的可验证凭证时警告他们持有者和/或主体信息暴露的程度,并在信息暴露程度发生变化时发出警告。

安全注意事项

在处理本规范描述的数据时,实施者应注意许多安全注意事项。忽略或不了解本节的含义可能会导致安全漏洞。

建议读者在阅读本节之前,先熟悉 《可验证凭证规范》的安全注意事项部分中提供的一般安全建议。

尽管本节试图强调广泛的安全注意事项,但它并不是一个完整的列表。建议实施者在使用本规范中概述的技术实现关键任务系统时,寻求安全和加密专业人士的建议。

位串编码

实施者必须特别注意位串的编码和解码方式。未能正确处理可能导致检查错误的位串索引,从而误解其当前状态(例如,将吊销状态误认为未吊销状态)。如第 节所述,位串的编码方式是第一个(第零个)索引指向位串数组的最左侧位。下图展示了未压缩位串的正确布局。

一个图示,显示两个宽矩形并排显示。每个矩形分为八个框,表示字节中的8位。左侧矩形标记为“第一个字节”,右侧矩形标记为“最后一个字节”。左侧矩形的最左侧位框由一个箭头指向,标记为“索引:0”。右侧矩形的最右侧位框由一个箭头指向,标记为“索引:长度 - 1”。
位串布局的视觉描述。

例如,如果位串的大小为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/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/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 第一个候选推荐版本以来的更改: