Copyright © 2026 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
本规范描述了一种用于生成 采用 BBS 签名方案的数字签名时使用的数据完整性密码套件。 该签名套件利用 BBS 签名提供选择性披露和 不可关联的派生证明。
本节描述本文档 在发布时的状态。当前 W3C 出版物列表以及本技术报告的最新修订版可在 W3C 标准与草案 索引中找到。
工作组正在积极征集本 规范的实现反馈。为了退出候选推荐标准阶段,工作 组设定了这样一项要求:对于本规范中的 每项功能,无论是强制性还是可选性功能,都至少需要两个独立实现。有关 一致性测试过程的详细信息,请参阅 实现报告中列出的测试套件。
本文档由可验证凭证工作 组使用 推荐标准 轨道发布为 候选推荐标准草案。
作为 候选推荐标准发布并不意味着获得 W3C 及其成员的认可。候选推荐标准草案 整合了 工作组打算纳入 后续候选推荐标准快照中的上一版候选推荐标准的变更。
这是一份草案文档,随时可能被其他 文档更新、替代或废弃。不应将本文档作为 进行中的工作以外的内容加以引用。
本文档由一个 根据 W3C 专利 政策运作的工作组编制。 W3C 维护了一份 所有专利披露的公开列表, 这些披露与 该工作组的交付成果相关;该页面还包含 披露专利的说明。任何实际 知晓某项专利,并认为该专利包含 必要权利要求的个人, 必须根据 W3C 专利政策第 6 节披露相关信息。
本文档受 2025 年 8 月 18 日 W3C 流程文档管辖。
本规范定义了一种密码套件,用于
按照数据完整性 [VC-DATA-INTEGRITY-1.1] 规范,
使用 BBS 签名方案创建、验证和派生证明。
BBS 签名方案直接提供选择性披露和不可关联的
证明。它提供四个在发行者、
持有者、验证者模型中工作的高级函数。具体而言,发行者使用 BBS Sign 函数
创建一种称为“BBS 签名”的密码学值,该值用于对
原始凭证进行签名。持有者收到
使用 BBS 签名的凭证后,会使用 BBS Verify
函数验证该凭证。
然后,持有者从收到的凭证中选择要选择性披露的信息,
并使用 BBS ProofGen 函数生成一个
称为“BBS 证明”的密码学值,该值用于为此“派生凭证”创建
证明。密码学“BBS 证明”值无法与
原始“BBS 签名”关联,并且持有者可以为其他“派生凭证”
生成不同且不可关联的“BBS 证明”,包括任何
包含完全相同信息的凭证。
最后,验证者使用 BBS ProofVerify 函数验证从持有者收到的派生
凭证。
将 BBS 签名方案应用于可验证凭证涉及
本文档中规定的处理。
通常,该套件使用 RDF 数据集规范化算法
[RDF-CANON] 将输入文档转换为其
规范形式。然后,颁发者使用选择性披露原语将
规范形式分为强制性语句和非强制性语句。这些语句与其他信息
分别进行处理,并与适当的密钥材料一起作为 BBS Sign
函数的输入。此输出用于
生成受保护的凭证。持有者在收到凭证后使用一组选择性披露
函数和 BBS Verify 函数
来确定其有效性。
类似地,在收到使用 BBS 签名的凭证后,持有者使用 RDF 数据集
规范化算法 [RDF-CANON] 将输入
文档转换为其规范形式,然后应用选择性披露
原语,将规范形式分为强制性语句和选择性
披露的语句,这些语句经过适当处理并作为
BBS ProofGen 函数的输入。经过适当处理后,此函数的输出
将成为发送给验证者的已签名选择性披露凭证。通过使用
规范化和选择性披露原语,验证者随后可以使用
BBS verifyProof 函数验证该凭证。
本文档中使用的术语定义于 可验证凭证数据完整性 1.1 规范的 术语章节中。
除了标记为非规范性的章节之外,本规范中的所有编写指南、图表、示例和注释也都是非规范性的。本规范中的其他所有内容均为规范性的。
本文档中的关键字 可以、必须、不得 、可选、必需 和 应当 仅当它们如这里所示以全大写形式出现时, 才应按照 BCP 14 [RFC2119] [RFC8174] 中所述的方式进行解释。
符合要求的 证明是数据模型的任何具体表达形式, 其符合本规范中的规范性陈述。具体而言, 本文档第 2. 数据模型和3. 算法 节中的所有相关规范性陈述都必须得到执行。
符合要求的处理器是任何以 软件和/或硬件实现的算法,其生成或使用 符合要求的证明。符合要求的处理器在 使用不符合要求的文档时必须产生错误。
本文档包含 JSON 和 JSON-LD 数据示例。其中一些示例
是无效的 JSON,因为它们包含诸如用于解释某些部分的行内注释
(//)以及用于表示省略
与示例无关信息的省略号(...)等特性。如果实现者希望将
这些示例作为有效的 JSON 或 JSON-LD 处理,则需要
移除这些部分。
以下各节概述了本规范用于验证 方法和数据完整性证明 格式的数据模型。
这些验证方法用于验证使用符合 [CFRG-BBS-SIGNATURE] 的 BLS12-381 密码密钥材料 生成的数据完整性证明 [VC-DATA-INTEGRITY-1.1]。这些 密钥类型的编码格式 在本节中给出。在处理数字签名期间, 可以使用能够生成等效密码密钥材料的无损密码密钥转换 过程。
受控标识符 v1.0中定义的 Multikey 格式用于表示本规范中 定义的密码套件所使用的公钥。
publicKeyMultibase 属性表示 BLS12-381 G2 群中
381 位公钥的 Multibase 编码 Multikey 表达形式。
验证方法的 publicKeyMultibase 值必须
以 base-58-btc 前缀(z)开头,该前缀定义于
受控标识符
v1.0的
Multibase 一节。随后是
一个经过 Multibase 编码的 BLS12-381 381 位公钥值,
如受控标识符
v1.0的
Multikey 一节中所定义。
不得允许任何其他编码。
建议开发者不要意外发布私钥的表示形式。
如果在 publicKeyMultibase
值中使用了 0xeb01 之外的 Multicodec 值,本规范的实现将产生错误。
{
"id": "https://example.com/issuer/123#key-0",
"type": "Multikey",
"controller": "https://example.com/issuer/123",
"publicKeyMultibase": "zUC7EK3ZakmukHhuncwkbySmomv3FmrkmS36E4Ks5rsb6VQSRpoCrx6
Hb8e2Nk6UvJFSdyw9NK1scFXJp21gNNYFjVWNgaqyGnkyhtagagCpQb5B7tagJu3HDbjQ8h
5ypoHjwBb"
}
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/multikey/v1"
],
"id": "https://example.com/issuer/123",
"verificationMethod": [{
"id": "https://example.com/issuer/123#key-1",
"type": "Multikey",
"controller": "https://example.com/issuer/123",
"publicKeyMultibase": "zUC7EK3ZakmukHhuncwkbySmomv3FmrkmS36E4Ks5rsb6VQSRpoCr
x6Hb8e2Nk6UvJFSdyw9NK1scFXJp21gNNYFjVWNgaqyGnkyhtagagCpQb5B7tagJu3HDbjQ8h
5ypoHjwBb"
}]
}
证明包含 [VC-DATA-INTEGRITY] 的 证明一节 中指定的属性,并具有以下限制。
证明的 verificationMethod 属性必须是一个 URL。
对 verificationMethod 进行解引用必须得到一个对象,
该对象包含值设置为
Multikey 的 type 属性。
证明的 type 属性必须为
DataIntegrityProof。
证明的 cryptosuite 属性必须为
bbs-2023。
证明的 proofValue 属性值必须是一个
按照 [CFRG-BBS-SIGNATURE] 生成的 BBS 签名或
BBS 证明,并按照第 3.
算法节中的过程进行序列化和
编码。
以下算法描述了如何将可验证凭证与 BBS 签名方案 [CFRG-BBS-SIGNATURE] 一起使用。使用 BBS 签名 方案时,应该使用 SHA-256 变体。
在添加或验证证明时,实现应该尽早获取并缓存验证方法信息。本节中传递给 函数的参数使用来自验证 方法的信息(例如公钥大小)来确定函数参数(例如 密码哈希算法)。
使用 RDF 数据集规范化算法 [RDF-CANON] 时, 该算法的实现默认会检测 数据集投毒, 并在检测到后中止处理。
此算法用于配置一个密码套件,供 可验证凭证数据完整性 1.1中的 添加证明和 验证证明 函数使用。该算法接受一个选项对象 (映射 options) 作为输入,并返回一个密码套件 实例(结构体 cryptosuite)。
DataIntegrityProof,返回
cryptosuite。
bbs-2023,则:
以下算法序列化基础证明值,其中包括 BBS 签名、HMAC 密钥和强制指针。 必需的输入为基础签名 bbsSignature、bbsHeader、 publicKey、HMAC 密钥 hmacKey、一个 mandatoryPointers 数组、featureOption,以及根据 featureOption 的值,可能还包括 signer_nym_entropy 值。 输出会生成单个基础证明字符串值。
"baseline":
0xd9、0x5d 和 0x02。
"anonymous_holder_binding":
0xd9、0x5d 和 0x04。
"pseudonym":
0xd9、0x5d 和 0x06。
"holder_binding_pseudonym":
0xd9、0x5d 和 0x08。
proofValue 的
multibase-base64url-no-pad 编码得到的字符串。也就是说,返回一个以“u”开头并以
proofValue 的
base64url-no-pad 编码值结尾的字符串。
以下算法解析 bbs-2023 选择性
披露基础证明值的各个组成部分。必需的输入是一个证明值
(proofValue)。输出会生成单个对象已解析基础证明,其中包含
六个或七个元素,名称分别为 "bbsSignature"、"bbsHeader"、
"publicKey"、
"hmacKey"、"mandatoryPointers"、"featureOption",以及可能存在的可选功能
参数 "signer_nym_entropy"。
proofValue 字符串不是以
u
(U+0075
LATIN SMALL LETTER U)开头,
表明它不是一个 multibase-base64url-no-pad-encoded 值,
则必须引发错误,并且应该传达
PROOF_VERIFICATION_ERROR
错误类型。
proofValue 中前导 u 之后的子字符串进行 base64url-no-pad 解码的结果。
0xd9、
0x5d 和 0x02 开头,则将
featureOption 设置为 "baseline"。
0xd9、
0x5d 和 0x04 开头,则将
featureOption 设置为 "anonymous_holder_binding"。
0xd9、
0x5d 和 0x06 开头,则将
featureOption 设置为 "pseudonym"。
0xd9、
0x5d 和 0x08 开头,则将
featureOption 设置为 "holder_binding_pseudonym"。
components 初始化为一个数组,该数组是对
三字节 BBS 基础证明头之后的字节进行 CBOR 解码的结果。
"baseline",则按顺序将基于
components 的对象
属性名设置为 "bbsSignature"、"bbsHeader"、"publicKey"、"hmacKey"
和 "mandatoryPointers",并添加 featureOption 作为属性。
"anonymous_holder_binding",则将
基于 components 的对象属性名按顺序设置为 "bbsSignature"、"bbsHeader"、
"publicKey"、"hmacKey" 和 "mandatoryPointers",并
添加 featureOption 作为属性。
"pseudonym",则将
基于 components 的对象属性名按顺序设置为 "bbsSignature"、"bbsHeader"、
"publicKey"、"hmacKey"、"mandatoryPointers" 和 "signer_nym_entropy",并
添加 featureOption 作为属性。
"holder_binding_pseudonym",则将
基于 components 的对象属性名按顺序设置为 "bbsSignature"、"bbsHeader"、
"publicKey"、"hmacKey"、"mandatoryPointers" 和 "signer_nym_entropy",并
添加 featureOption 作为属性。
以下算法序列化派生证明值。必需的输入 为 BBS 证明(bbsProof)、标签映射(labelMap)、一个 强制索引数组(mandatoryIndexes)、一个 选择性索引数组(selectiveIndexes)、BBS 呈现头 (presentationHeader)、featureOption 指示符,以及 根据 featureOption 的值,一个 nym_domain、pseudonym 和/或 lengthBBSMessages 值。 输出会生成单个派生证明 值,并将其序列化为字节字符串。
compressedLabelMap 初始化为调用
第 节中的算法并将
labelMap 作为参数传入所得的结果。
"baseline":
0xd9、0x5d 和
0x03 开头。
"anonymous_holder_binding":
0xd9、0x5d 和
0x05 开头。
"pseudonym":
0xd9、0x5d 和
0x07 开头。
"holder_binding_pseudonym":
0xd9、0x5d 和
0x09 开头。
u”开头并以
proofValue 的 base64url-no-pad 编码值结尾的字符串。
以下算法解析派生证明值的各个组成部分。 必需的输入是一个派生证明值(proofValue)。输出会生成 单个派生证明值对象,其中 包含六至九个元素,名称为 "bbsProof"、 "labelMap"、"mandatoryIndexes"、"selectiveIndexes"、"presentationHeader"、 "featureOption",并且根据 featureOption 参数的值, 还包括 "nym_domain"、"pseudonym" 和/或 "lengthBBSMessages"。
proofValue 字符串不是以
u
(U+0075,
LATIN SMALL LETTER U)开头,表明
它不是一个 multibase-base64url-no-pad-encoded 值,
则必须引发错误,并且应该传达
PROOF_VERIFICATION_ERROR
错误类型。
proofValue 中前导 u 之后的子字符串进行 base64url-no-pad 解码的结果。
0xd9、
0x5d 和
0x03 开头,则将 featureOption 设置为 "baseline"。
0xd9、
0x5d 和
0x05 开头,则将 featureOption 设置为
"anonymous_holder_binding"。
0xd9、
0x5d 和
0x07 开头,则将 featureOption 设置为 "pseudonym"。
0xd9、
0x5d 和
0x09 开头,则将 featureOption 设置为
"holder_binding_pseudonym"。
components 初始化为一个数组,该数组是对
三字节 BBS 披露证明头之后的字节进行 CBOR 解码的结果。如果该结果
不是包含五个、六个、七个或八个元素的数组,
则必须引发错误,并且应该传达
PROOF_VERIFICATION_ERROR
错误类型。
components 中的第二个元素,将 components 中现有的
第二个元素作为 compressedLabelMap 传入。
bbs-2023 密码套件接受一个输入文档,并使用 RDF 数据集规范化算法
[RDF-CANON] 对文档进行规范化,然后应用一系列
转换和密码学
操作,最终生成数据完整性证明。本节中的算法
还包括对此类数据完整性证明的验证。
以下算法规定了在给定 未保护数据 文档的情况下如何创建数据完整性 证明。 必需的输入为一个 未保护数据 文档(映射 unsecuredDocument)、一组证明 选项(映射 options)、一个强制 JSON 指针数组 (mandatoryPointers)、一个 featureOption 指示符参数,以及根据 featureOption,一个 commitment_with_proof 字节数组。 输出会生成一个数据完整性 证明(映射) 或一个错误。
featureOption 参数用于指示正在使用哪项可选功能(如果有)。
它可以采用以下值之一:"baseline"、
"anonymous_holder_binding"、"pseudonym" 或
"holder_binding_pseudonym"。请注意,"baseline" 用于表示
不使用任何可选功能的情况。如果 featureOption 设置为
"anonymous_holder_binding"、"pseudonym" 或
"holder_binding_pseudonym",则
必须提供 commitment_with_proof 输入。
如果 featureOption 设置为
"pseudonym" 或 "holder_binding_pseudonym",则
必须提供 signer_nym_entropy 输入。
以下算法由受 BBS 保护的可验证
凭证的发行者调用,规定了如何创建基础证明。该基础证明只会
提供给持有者,由持有者负责从中生成派生证明,
并仅向验证者公开证明中选择性披露的详细信息。此
算法设计为与数据完整性 [VC-DATA-INTEGRITY-1.1]
规范
第 4 节:算法中定义的算法结合使用。必需的输入为
密码哈希数据(hashData)、
featureOption,以及在需要时提供的
commitment_with_proof。
如果 featureOption 设置为 "anonymous_holder_binding"、
"pseudonym" 或 "holder_binding_pseudonym",则
必须提供 commitment_with_proof 输入;如果未提供,
则必须引发错误,并且应该传达
PROOF_GENERATION_ERROR
错误类型。
如果 featureOption 设置为
"pseudonym" 或 "holder_binding_pseudonym",则
必须提供 signer_nym_entropy 输入;如果未提供,
则必须引发错误,并且应该传达
PROOF_GENERATION_ERROR
错误类型。
输出会生成一个以一系列字节表示的数字证明值。
proofHash、mandatoryPointers、mandatoryHash、
nonMandatory
和 hmacKey 初始化为 hashData
中与其属性名关联的值。
bbsHeader 初始化为依次连接 proofHash 和
mandatoryHash 所得的结果。
bbsMessages 初始化为一个字节数组的数组,其中包含
使用 UTF-8 字符编码编码的
nonMandatory 字符串数组中的值。
bbsSignature。
"baseline",则使用
[CFRG-BBS-Signature] 的 Sign
过程计算 bbsSignature,
使用适当的密钥材料,将 bbsHeader 作为 header,并将
bbsMessages
作为 messages。
"anonymous_holder_binding",则使用
[CFRG-Blind-BBS-Signature] 的
BlindSign 过程计算
bbsSignature,
使用适当的密钥材料,将 commitment_with_proof 作为
commitment_with_proof,将 bbsHeader 作为 header,
并将 bbsMessages
作为 messages。这提供
匿名持有者绑定功能。
"pseudonym" 或
"holder_binding_pseudonym",
发行者会为 signer_nym_entropy 生成一个
密码学随机值,并使用
[CFRG-Pseudonym-BBS-Signature]
中的
"Blind Issuance" 操作计算
bbsSignature,
使用
适当的密钥材料,
将 bbsHeader 作为 header,
将 bbsMessages 作为 messages,
将 commitment_with_proof 作为 commitment_with_proof,以及
signer_nym_entropy 值。
如果发行者将来可能需要向此持有者重新发行
绑定到相同 nym_secret 的凭证,则应该
保留 signer_nym_entropy 值;否则,可以丢弃该值。
publicKey 是公钥的字节数组,按照
[CFRG-BBS-SIGNATURE] 进行编码。
proofValue 作为数字证明返回。
以下算法由受 bbs-2023 保护的
可验证
凭证的持有者调用,用于创建选择性披露派生证明。
该派生证明将提供给验证者。输入包括一个
JSON-LD 文档(document)、一个 BBS 基础证明
(proof)、一个用于选择性披露
语句的 JSON 指针数组(selectivePointers)、一个可选的 BBS
presentationHeader(字节数组)、一个 featureOption 参数、支持所选
featureOption 的附加参数(见下文),
以及任何自定义 JSON-LD API 选项,
例如文档加载器。输出会生成单个选择性公开的文档
值,以对象表示。
如果 featureOption 等于 "anonymous_holder_binding",
必需的附加输入为 holderSecret 和
proverBlind。这些值应当
已由持有者预先计算。有关背景
信息,请参见
匿名持有者绑定。
如果 featureOption 等于 "pseudonym",必需的
附加输入为 prover_nym 和 proverBlind,两者均为
持有者所知,以及 nym_dofmain,后者由持有者设置或由验证者传达
给持有者。
有关背景信息,请参见凭证绑定的假名。
如果 featureOption 等于 "holder_binding_pseudonym",必需的
附加输入为 holder_secret、prover_nym 和 proverBlind,
这些值
均为持有者所知,以及 nym_dofmain,后者由持有者设置或
由验证者传达给持有者。
有关背景信息,请参见持有者绑定和假名。
以下算法生成派生证明。 输入为 proofData 和 disclosureData 对象。
"baseline",
将 bbsProof 设置为通过
[CFRG-BBS-SIGNATURE] 中的
ProofGen 过程计算得到的值,即
ProofGen(PK, signature, header, ph, messages, disclosed_indexes),
其中 PK 是原始发行者的公钥,signature 是
bbsSignature,header 是 bbsHeader,
ph 是 presentationHeader
messages 是 bbsMessages,disclosed_indexes 是
selectiveIndexes。
"anonymous_holder_binding",
将 bbsProof 设置为通过
[CFRG-Blind-BBS-Signature] 中的
BlindProofGen
过程计算得到的值,其中
PK 是原始发行者的公钥,
signature 是
bbsSignature,header 是 bbsHeader,ph 是
presentationHeader,
messages 是 bbsMessages,disclosed_indexes 是
selectiveIndexes,
以及 commitment_with_proof。持有者还将提供其
holder_secret,以及用于计算
commitment_with_proof 的 proverBlind。这是
匿名持有者绑定功能选项。
将在 IETF API 最终确定后
更新。
"pseudonym",
使用
[CFRG-Pseudonym-BBS-Signature]
中的 "Verification and Finalization" 操作,
并使用空的 committed_messages 数组,
以同时验证 bbsSignature 并计算
nym_secret 值。此操作使用 prover_nym、
signer_nym_entropy 和 secret_prover_blind。
"holder_binding_pseudonym",
使用
[CFRG-Pseudonym-BBS-Signature]
中的 "Verification and Finalization" 操作,
并使用仅包含
holder_secret 作为其唯一值的 committed_messages 数组,
以同时验证 bbsSignature 并计算
nym_secret 值。此操作使用 prover_nym、
signer_nym_entropy 和 secret_prover_blind。
"anonymous_holder_binding"、
"pseudonym" 或 "holder_binding_pseudonym",则将
lengthBBSMessages
参数设置为 bbsMessages 数组的长度。
以下算法规定了在给定 受保护数据 文档的情况下如何验证数据完整性 证明。必需的输入为一个 受保护数据 文档(映射 securedDocument)。此算法返回 一个验证结果,它是一个结构体,其 项目为:
true 或 falsefalse,则为 Null;否则为一个未保护
数据文档
要验证派生证明,请执行以下步骤:
proof
值后的 document 副本。
"baseline",则将
verified 初始化为应用
[CFRG-BBS-SIGNATURE] 的验证算法
ProofVerify(PK, proof, header, ph,
disclosed_messages, disclosed_indexes)所得的结果,其中
PK 设置为原始发行者的公钥,proof 设置为
bbsProof,header
设置为 bbsHeader,disclosed_messages 设置为
disclosedMessages,ph 设置为
presentationHeader,并且 disclosed_indexes 设置为
selectiveIndexes。
"anonymous_holder_binding",
将 verified 初始化为应用
[CFRG-Blind-BBS-Signature] 的
ProofVerify 验证算法所得的结果,
并将 lengthBBSMessages 用作 "L" 参数。
将在 IETF API 最终确定后更新。
"pseudonym" 或
"holder_binding_pseudonym",
将 verified
初始化为应用
[CFRG-Pseudonym-BBS-Signature]
中的
"Proof Verification with Pseudonym" 操作所得的结果,
将 lengthBBSMessages 用作 "L"
参数,并使用空的 committed_messages 数组。
将在 IETF
API 最终确定后更新。
本节为非规范性内容。
BBS 签名的密码学属性允许支持 高级功能的变体。本规范仅限于 支持这些增强功能中最相关的部分,我们将在 以下各节中进行说明。变量 commitment_with_proof、holder_secret、 prover_nym、signer_nym_entropy 和 pseudonym 与这些 功能相关,除此之外 BBS 签名和证明并不需要它们。
本节描述并包含在本规范 算法中的可选 BBS 功能存在风险,如果它们各自的规范 未能按照相同的时间表在 IETF 达到 RFC 状态,或者每项可选 功能没有至少两个独立实现,则会在 本规范最终定稿前将其移除。
此功能在颁发时将带有基础证明的文档绑定到一个 只有持有者知道的秘密,使得只有该持有者才能生成 能够通过验证的带派生证明的披露文档。例如,如果 攻击者获得了带基础证明的文档,他们也无法创建 能够通过验证的带派生证明的披露文档。
为提供此功能,持有者生成一个 holder_secret 值, 该值通常应至少为 32 字节长,并以密码学随机方式 生成。持有者绝不会共享该值。相反,持有者 使用 [CFRG-Blind-BBS-Signature] 的“承诺计算”操作, 生成一个承诺以及对知晓该 值的零知识证明。 此计算涉及密码学随机值,并计算 commitment_with_proof 和 secret_prover_blind 值。 commitment_with_proof 会传达给颁发者,而 secret_prover_blind 则保持秘密,并由持有者保留以用于 生成派生证明。 请注意,持有者可以多次运行“承诺计算”操作, 以生成不可关联的 commitment_with_proof 值供不同颁发者使用。
颁发者在收到 commitment_with_proof 后,按照本规范的 过程,并使用 [CFRG-Blind-BBS-Signature] 的“盲签名生成”操作,在文档上生成基础证明 (签名), 其中使用持有者提供的 commitment_with_proof。
当持有者希望创建带有派生 证明的选择性披露文档时,他们使用本规范中的过程以及 [CFRG-Blind-BBS-Signature] 的“证明生成”操作。他们将自己的 holder_secret 作为 commited messages 数组中唯一的“消息”,并提供自己的 secret_prover_blind。
对带派生证明的披露文档进行验证时,使用 本规范中的过程以及 [CFRG-Blind-BBS-Signature] 的“证明验证”操作。
本文档规定的使用 BBS 签名的可验证凭证支持 选择性披露和不可关联的密码学证明制品。所谓 “不可关联”,是指 派生证明中的密码学信息无法与其他 证明或原始签名关联。这意味着验证者无法确定 持有者以前是否出示过相同的凭证(使用不同的证明 实例),也无法据此断言某种身份。凭据绑定 假名提供了一种保护隐私的机制,允许密码学假名具备有限的 可关联性。此类假名可以完全由持有者确定, 也可以由持有者和验证者共同确定。
这种密码学假名(密码学标识符/名称)由 两部分计算而成。第一部分 nym_secret 由 持有者指定并且只有持有者知道; 第二部分 nym_domain 可以由持有者 或验证者指定,并由持有者和验证者共享。 颁发者在颁发过程中将凭据绑定到 nym_secret。 随后持有者可以根据 nym_secret 计算假名,并向 验证者证明这些假名与其正在出示的凭据绑定。 使用相同 nym_secret 但不同 nym_domain 值计算出的密码学假名彼此不可关联。
持有者可能会选择一个 nym_domain,以便为自己在某种
公共论坛中使用假名,例如选择 nym_domain = "Mark Twain"。
持有者使用该 nym_domain
和自己的 nym_secret 计算出的密码学假名基本上是唯一的,并且任何既不
知道 nym_secret 也不持有绑定到该
假名的基础可验证凭证的实体,都无法断言这一假名身份。请注意,
(nym_domain, pseudonym)这一二元组必须与派生凭证一起发送,才能断言
此假名身份。
在另一种情况下,持有者可能正在使用验证者提供的服务,而
验证者希望跟踪一段时间内的访问情况,或者监控持有者对某些资源的
使用。在这种情况下,验证者选择持有者
在出示其派生凭证时需要使用的 nym_domain。例如,
验证者可能指定与其 DNS 域名绑定的公共 nym_domain(例如
"www.nym.example")供持有者使用。验证者还可以
通过定期
更改 nym_domain(例如将其与日期绑定,
"www.nym.example/2025-01-02"),表明其以某种方式支持数据最小化。本规范不规定
nym_domain 的取值。
最后,为防止恶意持有者获得另一持有者的 nym_secret 后得到绑定到该值的凭据, [CFRG-Pseudonym-BBS-Signature] 中的操作会让颁发者 添加一个随机化 因子 signer_nym_entropy,在生成签名期间将其与持有者的 部分 prover_nym 安全地“混合”。这会得到一个 nym_secret,颁发者可以从密码学上保证 该值是唯一的,供持有者使用。
凭据绑定假名的创建和使用概览如下 所示。
Commitment" 操作,并传入空的 committed_messages 数组,以计算
commitment_with_proof 和 secret_prover_blind。持有者将
commitment_with_proof 连同凭据请求发送给颁发者,但绝不会
披露 prover_nym 和 secret_prover_blind,而是将它们保留供以后使用。
"pseudonym"),以及
commitment_with_proof。
颁发者为
signer_nym_entropy 生成一个密码学随机值,并使用
[CFRG-Pseudonym-BBS-Signature] 中的“盲颁发”操作生成
基础证明。除其他
信息外,基础证明还将包含 signer_nym_entropy 值。如果
颁发者将来可能需要向该持有者重新颁发绑定到
同一 nym_secret 的凭据,则应保留 signer_nym_entropy 值;
否则,可以丢弃该值。
从某种意义上说,匿名持有者绑定和凭据绑定假名是
相互正交的功能,持有者和凭据生态系统可能希望同时使用
二者。例如,持有者可能希望将可验证
凭据绑定到 holder_secret,使得只有知道该值的持有者才能
根据基础证明生成派生证明,同时将 nym_secret 绑定到
基础证明,使得假名可以绑定到派生证明。这
对应于 featureOption 等于 "holder_binding_pseudonym"。
同时创建和使用匿名持有者绑定和 凭据绑定假名的概览如下所示。
"pseudonym",以及
commitment_with_proof。
颁发者使用本规范中的过程,并为
signer_nym_entropy 生成一个密码学随机值,然后使用
[CFRG-Pseudonym-BBS-Signature] 中的
“盲颁发”操作生成
基础证明。除其他信息外,基础证明还将包含
signer_nym_entropy 值。如果颁发者将来需要向
该持有者重新颁发绑定到同一 nym_secret 的凭据,则应保留
signer_nym_entropy 值,否则可以丢弃该值。
本节为非规范性内容。
本节总结了“baseline”BBS 证明以及 可选功能的输入、输出、证明序列化、 任务和过程。所谓baseline BBS,是指不带附加功能的 BBS 基础证明和派生证明。 所有可选功能在某种意义上都是“附加”的, 即会在“baseline”BBS 签名/证明的基础上 额外生成某些输入、任务或输出。
| 名称 | 任务 | 输入 | 签名算法 |
|---|---|---|---|
| 基线 BBS | baseline:根据 VC 生成 BBS 签名 | baseline:文档、证明选项、密钥材料、强制指针 | BBS |
| 匿名持有者绑定 | baseline | baseline + 来自持有者的带证明承诺 | 盲 BBS |
| 凭据绑定假名 | baseline + 生成 signer_nym_entropy | baseline + signer_nym_entropy、来自持有者的带证明 承诺 | 假名 BBS |
| 持有者绑定和假名 | baseline + 生成 signer_nym_entropy | baseline + signer_nym_entropy、 来自持有者的带证明承诺 | 假名 BBS |
| 名称 | 证明头字节 | 序列化输出 |
|---|---|---|
| 基线 BBS | 0xd9、0x5d 和 0x02 |
baseline:bbsSignature、bbsHeader、publicKey、hmacKey 和 mandatoryPointers |
| 匿名持有者绑定 | 0xd9、0x5d 和 0x04 |
baseline |
| 凭据绑定假名 | 0xd9、0x5d 和 0x06 |
baseline + signer_nym_entropy |
| 持有者绑定和假名 | 0xd9、0x5d 和 0x08 |
baseline + signer_nym_entropy |
| 名称 | 任务 | 输入 | 证明生成算法 |
|---|---|---|---|
| 基线 BBS | 根据带基础证明的 VC 生成 BBS 派生证明 | baseline:(来自基础证明序列化) bbsSignature、bbsHeader、publicKey、hmacKey 和 mandatoryPointers;selectivePointers(持有者的选择) | BBS |
| 匿名持有者绑定 | baseline | baseline + holder_secret、prover_blind(二者均 为持有者所知) | 盲 BBS |
| 凭据绑定假名 | baseline + 计算 nym_secret、计算 pseudonym | baseline + prover_nym、 prover_blind(均为持有者所知)、signer_nym_entropy (包含在颁发者提供的基础证明中)、nym_domain | 假名 BBS |
| 持有者绑定和假名 | baseline + 计算 nym_secret、计算 pseudonym | baseline + holder_secret、prover_nym、 prover_blind(均为持有者所知)、signer_nym_entropy (包含在颁发者提供的基础证明中)、nym_domain | 假名 BBS |
| 名称 | 证明头字节 | 序列化输出 |
|---|---|---|
| 基线 BBS | 0xd9、0x5d 和 0x03 |
baseline:bbsProof、compressedLabelMap、 mandatoryIndexes、selectiveIndexes、presentationHeader |
| 匿名持有者绑定 | 0xd9、0x5d 和 0x05 |
baseline |
| 凭据绑定假名 | 0xd9、0x5d 和 0x07 |
baseline + pseudonym、nym_domain |
| 持有者绑定和假名 | 0xd9、0x5d 和 0x09 |
baseline + pseudonym、nym_domain |
| 名称 | 输入 | 证明验证算法 |
|---|---|---|
| BBS 基线 | baseline:(来自派生证明序列化) bbsProof、compressedLabelMap、mandatoryIndexes、 selectiveIndexes、presentationHeader | BBS |
| 匿名持有者绑定 | baseline | 盲 BBS |
| 凭据绑定假名 | baseline + pseudonym(包含在派生证明中)、 nym_domain | 假名 BBS |
| 持有者绑定和假名 | baseline + pseudonym(包含在派生证明中)、 nym_domain | 假名 BBS |
在阅读本节之前,强烈建议读者先熟悉 数据完整性规范 安全注意事项一节中提供的一般安全建议。
本节为非规范性内容。
基础证明的安全性取决于相关 BBS 签名的安全属性。数字签名可能具有多种 理想的密码学属性 [Taming_EdDSAs],其中包括:
EUF-CMA(选择消息攻击下的 存在性不可伪造性)通常是签名方案所要求的最低安全属性。 它保证任何拥有签名者公钥 并且收到任意数量的、针对其自行选择消息的签名 (以自适应方式)的高效攻击者: , 都无法针对新消息输出有效签名 ,其中新消息 (除非概率可忽略不计)。如果攻击者针对新消息输出了有效 签名: , 则称为存在性伪造。
SUF-CMA(选择 消息攻击下的强不可伪造性)是比 EUF-CMA 更强的概念。它保证 对于任何拥有签名者公钥 并收到任意数量的、针对其自行选择消息的签名的高效攻击者: , 都无法输出新的有效签名对 , 使得 (除非概率可忽略不计)。强不可伪造性意味着 攻击者不仅无法为新消息生成签名,也无法为旧消息 找到新的签名。
在 [CDL2016] 中,在一些合理假设下,BBS 签名被证明 具有 EUF-CMA 安全性。此外,在 [TZ2023] 中,在类似假设下,BBS 签名 被证明具有 SUF-CMA 安全性。在这两种情况下,这些假设都与 离散对数问题的困难性有关,而该问题并不被认为在大规模 量子计算出现后仍然安全。
在非量子计算条件下,[CFRG-BBS-SIGNATURE] 为 BBS 签名套件实现者提供了 其他安全指南。与配对友好曲线有关的进一步 安全注意事项在 [CFRG-PAIRING-FRIENDLY] 中讨论。
本节为非规范性内容。
派生证明的安全性取决于相关
BBS 证明的安全属性。[CDL2016]
和 [TZ2023] 都证明了
BBS 证明是对持有 BBS
签名这一知识的零知识证明
。
如 [CFRG-BBS-SIGNATURE] 中所解释的,这意味着:
收到证明的验证方无法确定生成该证明时 使用的是哪个签名,从而消除了一个常见的关联来源。一般而言, 即使两个证明是由同一签名生成的,每个生成的证明也都与随机值不可区分。
并且
该方案生成的证明向验证者证明,生成证明的一方 (持有者/证明者或其代理)持有一个 签名,而无需披露该签名。
更准确地说,验证BBS 证明需要原始 颁发者的公钥,以及按正确顺序排列且未被更改的、已披露的 BBS 消息。
本节为非规范性内容。
选择性披露允许持有者将向验证者 披露的信息最小化,以实现特定目的。在规定 一个支持选择性披露的完整系统时,需要谨慎确保 尽量减少向 验证者泄露原本无意披露的附加信息。此类泄露可能通过 系统制品发生。这些制品可能来自系统的高层,例如 数据结构,也可能来自底层密码学原语。
例如,BBS 签名方案是一种在多个 消息上生成签名时空间效率极高的方案,也就是说,无论 消息数量是多少,发送给持有者的密码学 签名大小都是恒定的。然后,持有者可以选择性地向 验证者披露其中任意消息;但是作为该 密码学方案的一部分,颁发者最初签名的消息总数 必须向验证者披露。如果需要避免这种信息泄露, 则建议按照 [CFRG-BBS-SIGNATURE] 隐私注意事项一节中的建议, 将消息数量填充到共同长度。
在更高层面,数据如何映射为适合选择性披露的各个 语句,即 BBS 消息,也是潜在的 数据泄露来源。此密码套件能够通过使用 JSON-LD 处理将 输入转换为 RDF,消除许多用于表示 JSON 数据且可能泄露信息的 结构性制品 (嵌套、映射或数组位置等)。然后 RDF 可以表示为一种规范化、扁平化的简单 主语、属性、值语句格式(在可验证 凭证数据模型 [VC-DATA-MODEL-2.0] 中称为声明)。下面, 我们研究 RDF 规范化,即一种将 JSON-LD 格式的可验证凭证映射为 一组语句(BBS 消息)以用于 选择性披露的通用方案。我们将说明在执行此过程后, 仍然存在一个可能的信息泄露来源,并说明如何通过使用 带密钥的伪随机函数(PRF)来缓解这种泄露。
RDF 规范化可用于将 JSON-LD VC 扁平化
为一组
语句。该算法依赖于 VC 的内容,
并使用密码学哈希函数帮助对
语句排序。本质上,其工作方式是:JSON-LD 文档中
表示声明主体的每个 JSON 对象,如果没有定义 @id 字段,
都会被分配一个 id。此类 id 称为
空白节点 id。需要这些 id 才能将声明表示为简单的
主语、属性、值语句,从而能够
区分每条声明中的主体。id 值按照
[RDF-CANON] 确定性设置,并基于文档中的数据以及
SHA-256 等密码学哈希函数的输出。
下面展示了针对一组风帆冲浪帆具的两个略有不同的 VC,以及它们 规范化为一组可用于 选择性披露的语句的结果。通过改变 6.1 尺寸帆具的年份,我们会看到这两个 VC 之间 的语句顺序发生较大变化。如果持有者 只披露其较大帆具(7.0 和 7.8)的信息, 验证者就可能判断这组帆具发生了变化,即发生了 信息泄露。
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
{
"@vocab": "https://windsurf.grotto-networking.com/selective#"
}
],
"type": [
"VerifiableCredential"
],
"credentialSubject": {
"sails": [
{
"size": 5.5,
"sailName": "Kihei",
"year": 2023
},
{
"size": 6.1,
"sailName": "Lahaina",
"year": 2023 // 将更改此值以查看对规范化的影响
},
{
"size": 7.0,
"sailName": "Lahaina",
"year": 2020
},
{
"size": 7.8,
"sailName": "Lahaina",
"year": 2023
}
]
}
}
上述 VC 的规范形式。空白节点 id 的分配,即
_:c14nX
标签取决于 VC 的内容,这也会
影响语句的顺序。
_:c14n0 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n0 <https://windsurf.grotto-networking.com/selective#size> "7.8E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n0 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> . _:c14n1 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n4 . _:c14n2 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n2 <https://windsurf.grotto-networking.com/selective#size> "7"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n2 <https://windsurf.grotto-networking.com/selective#year> "2020"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n3 <https://windsurf.grotto-networking.com/selective#sailName> "Kihei" . _:c14n3 <https://windsurf.grotto-networking.com/selective#size> "5.5E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n3 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n4 <https://windsurf.grotto-networking.com/selective#sails> _:c14n0 . _:c14n4 <https://windsurf.grotto-networking.com/selective#sails> _:c14n2 . _:c14n4 <https://windsurf.grotto-networking.com/selective#sails> _:c14n3 . _:c14n4 <https://windsurf.grotto-networking.com/selective#sails> _:c14n5 . _:c14n5 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n5 <https://windsurf.grotto-networking.com/selective#size> "6.1E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n5 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> .
更新后的风帆冲浪帆具集合,即 6.1 尺寸的帆具已更新为 2024 型号。这通过改变 空白节点 id 的分配而改变了语句顺序。
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
{
"@vocab": "https://windsurf.grotto-networking.com/selective#"
}
],
"type": [
"VerifiableCredential"
],
"credentialSubject": {
"sails": [
{
"size": 5.5,
"sailName": "Kihei",
"year": 2023
},
{
"size": 6.1,
"sailName": "Lahaina",
"year": 2024 // 用新帆具更新旧型号,会改变规范化结果
},
{
"size": 7.0,
"sailName": "Lahaina",
"year": 2020
},
{
"size": 7.8,
"sailName": "Lahaina",
"year": 2023
}
]
}
}
上一个 VC 的规范形式。请注意空白节点 id 分配和语句顺序的差异。
_:c14n0 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n0 <https://windsurf.grotto-networking.com/selective#size> "6.1E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n0 <https://windsurf.grotto-networking.com/selective#year> "2024"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n1 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n1 <https://windsurf.grotto-networking.com/selective#size> "7.8E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n1 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> . _:c14n2 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n5 . _:c14n3 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n3 <https://windsurf.grotto-networking.com/selective#size> "7"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n3 <https://windsurf.grotto-networking.com/selective#year> "2020"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n4 <https://windsurf.grotto-networking.com/selective#sailName> "Kihei" . _:c14n4 <https://windsurf.grotto-networking.com/selective#size> "5.5E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n4 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n0 . _:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n1 . _:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n3 . _:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n4 .
为防止由于这些空白节点 id 的分配及其对
语句施加的顺序而造成此类信息泄露,会对
空白节点 id 运行基于 HMAC 的 PRF。HMAC 秘密密钥仅在
颁发者和持有者之间共享,并且颁发者生成的每个
基础证明都会使用新的 HMAC 密钥。其示例可见于
[DI-ECDSA] 的
规范 HMAC 测试向量。
如下一节所述,为了让 BBS 保持不可关联性,我们不会
使用基于 HMAC 的空白节点 id,而是根据 HMAC 生成一种
打乱
后的顺序,如测试向量 示例 12 所示。
请注意,与 ECDSA-SD 方法相比,这对空白节点
id提供的信息隐藏较少,因为关于
空白节点 id 数量的信息可能泄露,但它能够防止通过
将 HMAC 应用于空白节点 id 后产生的基本唯一标识符进行关联攻击。
在 VC 的某些用途中,为保护持有者隐私,防止跟踪或关联 多个不同的验证者 交互可能非常重要。特别是,我们考虑两个重要情况:(i) 验证者与 颁发者串通,以及 (ii) 验证者与验证者串通。在第一种 情况中,如图 1所示,验证者 会向凭据的原始 颁发者报告其与持有者的一次交互。在 这种情况下,颁发者可以使用已颁发的 VC 跟踪 持有者与不同验证者之间的所有交互。在第二种 情况中,如图 2所示,多个 验证者串通,共享 他们曾经交互过的持有者的信息。
我们使用术语不可关联性来描述 VC 系统
防止此类针对持有者隐私的“关联攻击”的属性。虽然术语
不可关联性相对较新,但 [NISTIR8053] 第 3.3 节讨论并
给出了一个通过关联攻击重新识别
的案例研究。
关于针对数据隐私的关联攻击
的知识体系整理可见于
[Powar2023]。针对用户隐私的关联攻击最
广泛的用途发生在 Web 浏览器指纹识别实践中,相关综述可见于
[Pugliese2020]。
为量化关联这一概念,[Powar2023] 引入了 匿名集的概念。在这里关注的 VC 情形中, 匿名集将包含特定 VC 的持有者以及与特定 颁发者相关联的其他持有者。匿名 集越小,越有可能跨验证者跟踪该持有者。由于签名 VC 包含对颁发者公钥的引用,因此,持有来自特定颁发者 VC 的持有者,其 匿名集的初始大小就是该颁发者使用该特定公钥/私钥对 颁发的 VC 数量。 非恶意颁发者应尽量减少用于颁发 VC 的公钥/私钥 对数量。请注意,匿名集概念与 [vc-bitstring-status-list] 中的 群体隐私概念类似。这里使用术语 关联时,通常是指任何会导致匿名集大小缩小的机制。
支持选择性披露的 VC 系统中的关联来源:
下面逐一讨论这些来源。
密码学哈希、HMAC 和数字签名从本质上会生成 高度唯一的标识符。由于 SHA-256 等哈希函数具有 抗碰撞属性,在不同输入下,其输出基本可以保证唯一, 从而形成强关联,即将匿名集 大小缩减为一。类似地,Ed25519 和 确定性 ECDSA 等确定性签名算法会针对不同输入生成基本唯一的输出, 并导致强关联。
这意味着可以通过 VC 内部的数字签名、HMAC 或哈希制品 在不同验证者之间轻易跟踪持有者, 因而容易受到验证者与验证者串通以及 验证者与颁发者串通的影响。某些 ECDSA 形式等随机化签名算法允许颁发者针对相同输入生成多个不同签名, 并将这些签名发送给持有者供不同 验证者使用。此类方法可以用来防止 基于串通跟踪的验证者与验证者攻击,但无法应对 验证者与颁发者串通。
要实现不可关联性,需要专门设计的密码学签名
方案,使持有者能够生成所谓的对持有签名这一
知识的零知识证明
(ZKPKS)。这意味着
持有者可以获取此类
方案中颁发者提供的签名,计算 ZKPKS 并发送给验证者。该 ZKPKS 无法
关联回原始签名,但具备签名的所有理想属性,
即验证者可以使用它验证消息
是否由颁发者的公钥签名,以及消息是否未被
修改。此外,持有者可以为不同
验证者生成任意多个 ZKPKS,这些证明基本相互独立
且不可关联。BBS 就是支持此功能的一种签名方案。
虽然本文档中称为BBS 证明的 ZKPKS 具有有保证的不可关联性属性,但 BBS 与选择性披露结合使用时, 有两个制品可能导致可关联性。它们是最初签名的 消息总数以及已披露语句的索引值。 有关讨论和缓解技术,请参见 [CFRG-BBS-SIGNATURE] 中的隐私注意事项。
如 [CFRG-BBS-SIGNATURE] 的
颁发者的公钥
一节中所述,存在一种潜在
威胁,即颁发者可能使用多个公钥,其中一些用于通过
验证者与颁发者串通来跟踪特定用户子集。由于颁发者的公钥
必须对验证者可见,即它会在 BBS
证明(派生证明)中被引用,因此如果颁发者
拥有许多不同公钥,尤其是如果其只对少量
用户(持有者)使用其中一小部分密钥,则这些公钥可能被用作关联点。
我们在信息泄露一节中已经看到,RDF 规范化使用
哈希函数对语句排序,并且还会基于 HMAC 对语句顺序进一步
打乱
。这可能留下某种指纹,
从而允许一定程度的关联。关联强度取决于
空白节点的数量(本质上即 VC 内的 JSON 对象数量)以及已披露
索引的数量。给定 n 个空白节点和 k 个已披露索引,
在最坏情况下,这会使匿名集大小缩小
C(n, k) 倍,即从 n 个元素的集合中
选择 k 个元素的组合数。可以通过
减少 VC 中空白节点的数量来使这一数字保持相当低,例如使 VC 保持简短和
简单。
JSON-LD 是一种基于 JSON 的关联数据序列化格式。因此,它支持
为文档内的每个对象
(JSON-LD 术语中的“节点”)分配一个全局无歧义的 @id 属性(节点标识符)。
这实现了关联数据的关联
,从而可以将关于同一实体的信息相互关联。
根据使用场景,这种关联可能是理想的,也可能是不理想的。
使用 BBS 的不可关联性功能时,不能为个人或其个人可识别
信息使用全局无歧义的节点
标识符,因为其提供的强关联是不理想的。请注意,在表达非个人
信息的语句时使用此类标识符是可以接受的(例如使用全局无歧义标识符来标识大型
国家或音乐会活动)。还请注意,JSON-LD 对 @context 的使用会
将术语映射到 IRI,这通常不会影响不可关联性。
在 [VC-DATA-INTEGRITY-1.1]
规范中,给出了 VC 的
proof 属性的若干特性。需要注意的是,可选字段
不应在不同验证者之间提供强关联。可选字段包括:
id、created、expires、domain、
challenge 和 nonce。例如,可选的
created 字段是一个 dateTimeStamp 对象,可以将
证明的创建日期指定到任意亚秒级精度。此类
信息如果存在,可能会大幅缩小匿名集的大小。如果
发行者希望包含此类信息,则应使其粒度尽可能粗,
并与一段时间内发行的 VC 数量相适应。
发行者还可以通过创建
基础证明时使用的 mandatoryPointers 输入,强制持有者向
验证者披露某些语句。参见
示例 9和
示例 10。这里的
强制
是指,
除非向验证者披露这些语句,否则生成的派生证明将无法通过验证。
应注意,如果要求披露此类信息,
则应确保匿名集仍然足够大。
如 [Powar2023] 中所述, 已记录了许多通过 关联攻击重新识别个人的案例。因此,强烈建议持有者 尽可能少地披露信息,以帮助保持较大的匿名 集。此外,多次研究表明,看似无害的 信息也可能高度唯一,从而导致重新识别 或跟踪。有关一个涉及前马萨诸塞州州长的著名 案例的详细过程,请参见 [NISTIR8053];有关对 94 个此类公开案例的进一步 分析和分类,请参见 [Powar2023]。
需要指出的是,要维持不可关联性,即匿名性, 持有和传输 VC 的系统需要格外谨慎。IP 地址(第 3 层)或 Ethernet/MAC 地址(第 2 层)等网络 制品是众所周知的关联来源。例如,如果用户再次访问某个特定接入点, 移动电话的 MAC 地址可以用于跟踪用户,这促使 移动电话制造商提供 MAC 地址随机化功能。 公网 IP 地址通常足以提供信息,将个人地理定位到某个国家内的 城市或地区,从而可能大幅缩小 匿名集。
本节为非规范性内容。
文档测试 向量基于一张完全虚构的永久居民卡,并分为 两组——由 颁发者生成的那些(“基础证明”),以及由 持有者生成的那些(“派生证明”)。
要向文档添加选择性披露基础证明,颁发者需要 以下密码学密钥材料:
用于生成测试添加基础 证明的测试向量所使用的密钥材料如下所示。BBS 密钥 对和 HMAC 密钥使用十六进制表示。
{
"publicKeyHex": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"privateKeyHex": "66d36e118832af4c5e28b2dfe1b9577857e57b042a33e06bdea37b811ed09ee0",
"hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}
在我们的场景中,正在颁发永久居民凭证。未签名的 永久居民文档如下所示。
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/citizenship/v4rc1"
],
"type": [
"VerifiableCredential",
"PermanentResidentCardCredential"
],
"issuer": {
"id": "did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg",
"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg=="
},
"name": "Permanent Resident Card",
"description": "Government of Utopia Permanent Resident Card.",
"credentialSubject": {
"type": [
"PermanentResident",
"Person"
],
"givenName": "JANE",
"familyName": "SMITH",
"gender": "Female",
"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4v43hPwAHIgK1v4tX6wAAAABJRU5ErkJggg==",
"residentSince": "2015-01-01",
"commuterClassification": "C1",
"birthCountry": "Arcadia",
"birthDate": "1978-07-17",
"permanentResidentCard": {
"type": [
"PermanentResidentCard"
],
"identifier": "83627465",
"lprCategory": "C09",
"lprNumber": "999-999-999"
}
},
"validFrom": "2024-12-16T00:00:00Z",
"validUntil": "2025-12-16T23:59:59Z"
}
此强制信息通过 JSON 指针数组指定, 如下所示。
["/issuer"]
将上述 JSON 指针应用于文档的结果 如下所示。
[
{
"pointer": "/issuer",
"value": {
"id": "did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg",
"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg=="
}
}
]
未签名文档的转换从规范化文档开始, 如下所示。
[ "<did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg==> .\n", "_:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCard> .\n", "_:c14n0 <https://schema.org/identifier> \"83627465\" .\n", "_:c14n0 <https://w3id.org/citizenship#lprCategory> \"C09\" .\n", "_:c14n0 <https://w3id.org/citizenship#lprNumber> \"999-999-999\" .\n", "_:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://schema.org/Person> .\n", "_:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResident> .\n", "_:c14n1 <https://schema.org/birthDate> \"1978-07-17\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n", "_:c14n1 <https://schema.org/familyName> \"SMITH\" .\n", "_:c14n1 <https://schema.org/gender> \"Female\" .\n", "_:c14n1 <https://schema.org/givenName> \"JANE\" .\n", "_:c14n1 <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4v43hPwAHIgK1v4tX6wAAAABJRU5ErkJggg==> .\n", "_:c14n1 <https://w3id.org/citizenship#birthCountry> \"Arcadia\" .\n", "_:c14n1 <https://w3id.org/citizenship#commuterClassification> \"C1\" .\n", "_:c14n1 <https://w3id.org/citizenship#permanentResidentCard> _:c14n0 .\n", "_:c14n1 <https://w3id.org/citizenship#residentSince> \"2015-01-01\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n", "_:c14n2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCardCredential> .\n", "_:c14n2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n", "_:c14n2 <https://schema.org/description> \"Permanent Resident Card from Government of Utopia.\" .\n", "_:c14n2 <https://schema.org/name> \"Permanent Resident Card\" .\n", "_:c14n2 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n1 .\n", "_:c14n2 <https://www.w3.org/2018/credentials#issuer> <did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> .\n", "_:c14n2 <https://www.w3.org/2018/credentials#validFrom> \"2024-12-16T00:00:00Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n", "_:c14n2 <https://www.w3.org/2018/credentials#validUntil> \"2025-12-16T23:59:59Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n" ]
为防止空白节点 ID 的顺序可能造成信息泄露, 这些 ID 会通过 PRF(即 HMAC)处理,从而得到如下所示的规范化 HMAC 文档。这表示一个有序的语句列表,这些语句将 接受“强制”和“选择性”(或“非强制”)披露,即 当这些语句根据其披露要求进行分组时,它们 仍将按照此列表中的顺序排列。
[ "<did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg==> .\n", "_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://schema.org/Person> .\n", "_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResident> .\n", "_:b0 <https://schema.org/birthDate> \"1978-07-17\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n", "_:b0 <https://schema.org/familyName> \"SMITH\" .\n", "_:b0 <https://schema.org/gender> \"Female\" .\n", "_:b0 <https://schema.org/givenName> \"JANE\" .\n", "_:b0 <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4v43hPwAHIgK1v4tX6wAAAABJRU5ErkJggg==> .\n", "_:b0 <https://w3id.org/citizenship#birthCountry> \"Arcadia\" .\n", "_:b0 <https://w3id.org/citizenship#commuterClassification> \"C1\" .\n", "_:b0 <https://w3id.org/citizenship#permanentResidentCard> _:b1 .\n", "_:b0 <https://w3id.org/citizenship#residentSince> \"2015-01-01\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n", "_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCard> .\n", "_:b1 <https://schema.org/identifier> \"83627465\" .\n", "_:b1 <https://w3id.org/citizenship#lprCategory> \"C09\" .\n", "_:b1 <https://w3id.org/citizenship#lprNumber> \"999-999-999\" .\n", "_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCardCredential> .\n", "_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n", "_:b2 <https://schema.org/description> \"Permanent Resident Card from Government of Utopia.\" .\n", "_:b2 <https://schema.org/name> \"Permanent Resident Card\" .\n", "_:b2 <https://www.w3.org/2018/credentials#credentialSubject> _:b0 .\n", "_:b2 <https://www.w3.org/2018/credentials#issuer> <did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> .\n", "_:b2 <https://www.w3.org/2018/credentials#validFrom> \"2024-12-16T00:00:00Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n", "_:b2 <https://www.w3.org/2018/credentials#validUntil> \"2025-12-16T23:59:59Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n" ]
上述规范文档中的列表会被分为强制和 非强制语句。选择性披露 转换过程的最终输出如下所示。请注意,这些语句现在被分组为 强制披露或非强制披露,并且每条语句在 前一列表中的索引都会被保留。
{
"mandatoryPointers": [
"/issuer"
],
"mandatory": {
"dataType": "Map",
"value": [
[
0,
"<did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg==> .\n"
],
[
16,
"_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCardCredential> .\n"
],
[
17,
"_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n"
],
[
21,
"_:b2 <https://www.w3.org/2018/credentials#issuer> <did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> .\n"
]
]
},
"nonMandatory": {
"dataType": "Map",
"value": [
[
1,
"_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://schema.org/Person> .\n"
],
[
2,
"_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResident> .\n"
],
[
3,
"_:b0 <https://schema.org/birthDate> \"1978-07-17\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
],
[
4,
"_:b0 <https://schema.org/familyName> \"SMITH\" .\n"
],
[
5,
"_:b0 <https://schema.org/gender> \"Female\" .\n"
],
[
6,
"_:b0 <https://schema.org/givenName> \"JANE\" .\n"
],
[
7,
"_:b0 <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4v43hPwAHIgK1v4tX6wAAAABJRU5ErkJggg==> .\n"
],
[
8,
"_:b0 <https://w3id.org/citizenship#birthCountry> \"Arcadia\" .\n"
],
[
9,
"_:b0 <https://w3id.org/citizenship#commuterClassification> \"C1\" .\n"
],
[
10,
"_:b0 <https://w3id.org/citizenship#permanentResidentCard> _:b1 .\n"
],
[
11,
"_:b0 <https://w3id.org/citizenship#residentSince> \"2015-01-01\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
],
[
12,
"_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCard> .\n"
],
[
13,
"_:b1 <https://schema.org/identifier> \"83627465\" .\n"
],
[
14,
"_:b1 <https://w3id.org/citizenship#lprCategory> \"C09\" .\n"
],
[
15,
"_:b1 <https://w3id.org/citizenship#lprNumber> \"999-999-999\" .\n"
],
[
18,
"_:b2 <https://schema.org/description> \"Permanent Resident Card from Government of Utopia.\" .\n"
],
[
19,
"_:b2 <https://schema.org/name> \"Permanent Resident Card\" .\n"
],
[
20,
"_:b2 <https://www.w3.org/2018/credentials#credentialSubject> _:b0 .\n"
],
[
22,
"_:b2 <https://www.w3.org/2018/credentials#validFrom> \"2024-12-16T00:00:00Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
],
[
23,
"_:b2 <https://www.w3.org/2018/credentials#validUntil> \"2025-12-16T23:59:59Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
]
]
},
"hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}
下一步是创建基础证明配置并对其进行规范化。 以下两个示例展示了这一过程。
{
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/citizenship/v4rc1"
]
}
_:c14n0 <http://purl.org/dc/terms/created> "2023-08-15T23:36:38Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> . _:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/security#DataIntegrityProof> . _:c14n0 <https://w3id.org/security#cryptosuite> "bbs-2023"^^<https://w3id.org/security#cryptosuiteString> . _:c14n0 <https://w3id.org/security#proofPurpose> <https://w3id.org/security#assertionMethod> . _:c14n0 <https://w3id.org/security#verificationMethod> <did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ> .
在哈希步骤中,我们计算规范化证明
选项的 SHA-256 哈希以生成 proofHash,并计算所有强制
N-Quads 的 JOIN 的 SHA-256 哈希以生成 mandatoryHash。它们
以十六进制格式显示如下。
{
"proofHash": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf",
"mandatoryHash": "8e7cc22c318dd2094e02d0bf06c5d73a5dba717611a40f6d1bedc5ea7c300fd6"
}
下面显示的是计算得到的十六进制 bbsSignature,以及
mandatoryPointers。它们与
hmacKey 一起提供给最终序列化步骤。
{
"bbsSignature": "86168dd2b5d0c7c6a56a30f4212ed116a53def05d0d6708207d483c7ff2053aefa22d24ba7659d60852694f8d85be0fa2adc3974c7dc4cc68b3db17b2423975047104162c24502b41591879ac24f1bb1",
"mandatoryPointers": [
"/issuer"
]
}
最后,将上述值通过第
3.2.1
serializeBaseProofValue节的算法运行,以生成
签名基础文档中使用的 proofValue,如下所示。
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/citizenship/v4rc1"
],
"type": [
"VerifiableCredential",
"PermanentResidentCardCredential"
],
"issuer": {
"id": "did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg",
"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg=="
},
"name": "Permanent Resident Card",
"description": "Permanent Resident Card from Government of Utopia.",
"credentialSubject": {
"type": [
"PermanentResident",
"Person"
],
"givenName": "JANE",
"familyName": "SMITH",
"gender": "Female",
"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4v43hPwAHIgK1v4tX6wAAAABJRU5ErkJggg==",
"residentSince": "2015-01-01",
"commuterClassification": "C1",
"birthCountry": "Arcadia",
"birthDate": "1978-07-17",
"permanentResidentCard": {
"type": [
"PermanentResidentCard"
],
"identifier": "83627465",
"lprCategory": "C09",
"lprNumber": "999-999-999"
}
},
"validFrom": "2024-12-16T00:00:00Z",
"validUntil": "2025-12-16T23:59:59Z",
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0ChVhQhhaN0rXQx8alajD0IS7RFqU97wXQ1nCCB9SDx_8gU676ItJLp2WdYIUmlPjYW-D6Ktw5dMfcTMaLPbF7JCOXUEcQQWLCRQK0FZGHmsJPG7FYQDpbvyXTTZCxjDXNI1e-am9CMB6U_J5S936Tt3PFYUvfjnzCLDGN0glOAtC_BsXXOl26cXYRpA9tG-3F6nwwD9ZYYKTvGvo9pXVJbxIrm3i4wkdhUxqKCTIGrnxFuAdZwWi6T3omD5wzZ7bAGbRneEEQSxBmXtvnC6Pr59nPv_v3HrAW9wq_uxYzF_NyaX3GPv0h_FV2T2OSao8C6uoyWiqIj1ggABEiM0RVZneImaq7zN3u_wARIjNEVWZ3iJmqu8zd7v-BZy9pc3N1ZXI"
}
}
创建 BBS 证明
时会使用随机数,并且可选的 presentationHeader 可以作为
额外输入。为了提供一组确定性的测试向量,我们使用了
[CFRG-BBS-SIGNATURE] 中的模拟随机标量
过程。我们用于生成派生证明测试向量的 seed 和
presentationHeader 值以十六进制给出如下。
{
"presentationHeaderHex": "113377aa",
"pseudoRandSeedHex": "332e313431353932363533353839373933323338343632363433333833323739"
}
要创建派生证明,持有者从一个
包含基础证明的已签名文档开始。我们用于这些测试向量的基础文档是
上面第 A.1.1
基础证明节中的最后一个示例。第一
步是运行第 3.2.2
parseBaseProofValue节的算法,以
恢复 bbsSignature、hmacKey 和 mandatoryPointers,
如下所示。
{
"bbsSignature": "86168dd2b5d0c7c6a56a30f4212ed116a53def05d0d6708207d483c7ff2053aefa22d24ba7659d60852694f8d85be0fa2adc3974c7dc4cc68b3db17b2423975047104162c24502b41591879ac24f1bb1",
"hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
"mandatoryPointers": [
"/issuer"
]
}
接下来,持有者需要通过指定用于选择性 披露的 JSON 指针,指明他们希望向验证者披露哪些非强制语句(如果有)。 这些指针如下所示。
["/validFrom", "/validUntil", "/credentialSubject/birthCountry"]
为生成 revealDocument(即最终将
被签名并发送给验证者的未签名文档),我们将选择性指针
追加到强制指针,并将这些组合指针连同
不带证明的文档输入 [DI-ECDSA] 的
selectJsonLd 算法。
得到如下结果。
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/citizenship/v4rc1"
],
"type": [
"VerifiableCredential",
"PermanentResidentCardCredential"
],
"issuer": {
"id": "did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg",
"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg=="
},
"validFrom": "2024-12-16T00:00:00Z",
"validUntil": "2025-12-16T23:59:59Z",
"credentialSubject": {
"type": [
"PermanentResident",
"Person"
],
"birthCountry": "Arcadia"
}
}
既然我们已经知道了公开文档是什么样子,接下来就需要向验证者提供 适当更新的信息,说明哪些语句是 强制的,以及所选非强制语句的索引。运行 § 4.4.3 CreateDisclosureData 会生成大量关于 相对于原始文档的各种语句组的信息。下面,我们展示 这些组的一部分索引。
{"combinedIndexes":[0,1,2,8,16,17,20,21,22,23],"mandatoryIndexes":[0,16,17,21],"nonMandatoryIndexes":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,18,19,20,22,23],"selectiveIndexes":[1,2,8,16,17,20,22,23]}
验证者需要能够聚合并哈希强制语句。为了
实现这一点,我们向其提供强制语句的索引列表,
并将其调整为这些语句在披露文档中的位置(即相对于
combinedIndexes),而 selectiveIndexes 则相对于
它们在 nonMandatoryIndexes 中的位置进行调整。这些“调整后的”索引
如下所示。
{"adjMandatoryIndexes":[0,4,5,7],"adjSelectiveIndexes":[0,1,7,17,18,19]}
最后一项重要的披露数据是 labelMap,它是从
规范化空白节点 ID 到基于 HMAC 的打乱 ID 的映射,按照
§ 4.4.3 CreateDisclosureData 计算得出。如下所示,
同时还展示了除公开文档之外的
其余披露数据。
{"bbsProof":"96ac5ff7b89bf2d8b0f3cc51c547f1a22b01e24e246579d212362cdf6bf0fabe18be0c9d1f84c904bb4c6c613fd0ecabb7ad92e615341da97a45a918721626cc859c455b473a36e39572561d5fc483c637424717a43dcffb3b130d8fe11f88a8802f3b231efe2444f8b47feded0b621e3d5cd22cb3ec23ebc4f6dca745b5c1ce2f42a710b92510a71225a7d39e00e0c26da2fae242cdf154e93de42017270b99023fe95b42c42a461a2eab19e04aa44839af39aa71f830162cb424a5aa0acc046dc7e7b8bdfc73cf3641c76aeeb7fbb56cd936776050dbd632bf7fc80d33c621dc6b837184ade619630f72bd25d8aea626ba994d15a65def1b0dc8af09c54a0cf5e5b54d1b1b28047aa2dbf63805fec9533bab46d12349ca47dfd83ff30454cedacd23da4eb9a3ebe198c80ac1992e2a203ffcf46afaa3482a63b7b00033df1a2da361d600a1cfd5139be010ca302e082af7ee34a5ff3d24cc7062f57fa36d47846edd5219e59bd438576bff709bfd7920d6bad8367b0fe8c749318ef8726beda9c1d9095bed738e4fd1c38333a27f4f2071a21a863671b43fe521f737444be865e887cbf33caa39226fb8013003721e37c6d949867befba1c8b7bf641bd647851ad92aed3da91af52f17d058a9f74eb30744304c05813840be6a528f54cd5a24b73ae2f42dec1bfc2e1354fb061a96c0df3ab96ddc9ada96cb882571cccb89774fcf0326e1c8b2b87cc4cf4eafbd75632518919cbe58a9f86ade12b0f6989c0886e358d801b99b1dd32c7e6e56a653c0e264a84b51d2d23679c75e282451af3bcaa6f19ec7bc3aa603fec87db5a57d42961e2907d899a8fd5d1ce17dde8a75cd1192494cd93b112da7774c2bb2f679f5b4b404dabe485d78a017b2be81e5ff8bacf90d5f24b2e83ab4169f8f55ca6f703141f91565abbec7445e6cf4663f5e34b9188283d57cedf36c586b18a130b83652436bf6862673ddeebd9aefdc2fbfc97dde80e36483491c4357ccd2fc131fb","labelMap":{"dataType":"Map","value":[["c14n0","b0"],["c14n1","b2"]]},"mandatoryIndexes":[0,4,5,7],"adjSelectiveIndexes":[0,1,7,17,18,19],"presentationHeader":{"0":17,"1":51,"2":119,"3":170}}
最后,将上述披露数据用于第 3.2.3 serializeDerivedProofValue节中的算法,我们将得到如下所示的已签名派生(公开) 文档。
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/citizenship/v4rc1"
],
"type": [
"VerifiableCredential",
"PermanentResidentCardCredential"
],
"issuer": {
"id": "did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg",
"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg=="
},
"validFrom": "2024-12-16T00:00:00Z",
"validUntil": "2025-12-16T23:59:59Z",
"credentialSubject": {
"type": [
"PermanentResident",
"Person"
],
"birthCountry": "Arcadia"
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0DhVkC0JasX_e4m_LYsPPMUcVH8aIrAeJOJGV50hI2LN9r8Pq-GL4MnR-EyQS7TGxhP9Dsq7etkuYVNB2pekWpGHIWJsyFnEVbRzo245VyVh1fxIPGN0JHF6Q9z_s7Ew2P4R-IqIAvOyMe_iRE-LR_7e0LYh49XNIss-wj68T23KdFtcHOL0KnELklEKcSJafTngDgwm2i-uJCzfFU6T3kIBcnC5kCP-lbQsQqRhouqxngSqRIOa85qnH4MBYstCSlqgrMBG3H57i9_HPPNkHHau63-7Vs2TZ3YFDb1jK_f8gNM8Yh3GuDcYSt5hljD3K9Jdiupia6mU0Vpl3vGw3IrwnFSgz15bVNGxsoBHqi2_Y4Bf7JUzurRtEjScpH39g_8wRUztrNI9pOuaPr4ZjICsGZLiogP_z0avqjSCpjt7AAM98aLaNh1gChz9UTm-AQyjAuCCr37jSl_z0kzHBi9X-jbUeEbt1SGeWb1DhXa_9wm_15INa62DZ7D-jHSTGO-HJr7anB2Qlb7XOOT9HDgzOif08gcaIahjZxtD_lIfc3REvoZeiHy_M8qjkib7gBMANyHjfG2UmGe--6HIt79kG9ZHhRrZKu09qRr1LxfQWKn3TrMHRDBMBYE4QL5qUo9UzVoktzri9C3sG_wuE1T7BhqWwN86uW3cmtqWy4glcczLiXdPzwMm4ciyuHzEz06vvXVjJRiRnL5Yqfhq3hKw9picCIbjWNgBuZsd0yx-blamU8DiZKhLUdLSNnnHXigkUa87yqbxnse8OqYD_sh9taV9QpYeKQfYmaj9XRzhfd6Kdc0RkklM2TsRLad3TCuy9nn1tLQE2r5IXXigF7K-geX_i6z5DV8ksug6tBafj1XKb3AxQfkVZau-x0RebPRmP140uRiCg9V87fNsWGsYoTC4NlJDa_aGJnPd7r2a79wvv8l93oDjZINJHENXzNL8Ex-6IAAAEChAAEBQeGAAEHERITRBEzd6o"
}
}
演示包括强制披露、 选择性披露及二者重叠在内的选择性披露功能, 需要一个比之前测试 向量包含更多内容的输入凭证文档。为避免测试向量过长,起始文档测试 向量基于一个完全虚构的风帆冲浪(帆船)比赛 场景。此外,我们将测试向量分为两组,分别对应 由颁发者生成的那些(基础证明)和由 持有者生成的那些(派生证明)。
要向文档添加选择性披露基础证明,颁发者需要 以下密码学密钥材料:
用于生成测试添加基础 证明的测试向量所使用的密钥材料如下所示。BBS 密钥 对和 HMAC 密钥使用十六进制表示。
{
"publicKeyHex": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"privateKeyHex": "66d36e118832af4c5e28b2dfe1b9577857e57b042a33e06bdea37b811ed09ee0",
"hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}
在我们的场景中,一名帆船运动员正在向赛事组织者报名参加 将在毛伊岛连续多天举行的一系列 风帆冲浪比赛。组织者将 检查该运动员的装备,以证明其申报内容 准确无误。该运动员未签名的装备清单如下所示。
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
{
"@vocab": "https://windsurf.grotto-networking.com/selective#"
}
],
"type": [
"VerifiableCredential"
],
"issuer": "https://vc.example/windsurf/racecommittee",
"credentialSubject": {
"sailNumber": "Earth101",
"sails": [
{
"size": 5.5,
"sailName": "Kihei",
"year": 2023
},
{
"size": 6.1,
"sailName": "Lahaina",
"year": 2023
},
{
"size": 7.0,
"sailName": "Lahaina",
"year": 2020
},
{
"size": 7.8,
"sailName": "Lahaina",
"year": 2023
}
],
"boards": [
{
"boardName": "CompFoil170",
"brand": "Wailea",
"year": 2022
},
{
"boardName": "Kanaha Custom",
"brand": "Wailea",
"year": 2019
}
]
}
}
除了让其他运动员了解竞争对手 可能使用何种装备之外,每位运动员还必须披露其 最新风帆冲浪板的年份以及其中两张帆的完整详情。请注意, 所有运动员均通过印在其所有 装备上的帆号进行标识。此强制信息通过 JSON 指针数组指定, 如下所示。
["/issuer", "/credentialSubject/sailNumber", "/credentialSubject/sails/1", "/credentialSubject/boards/0/year", "/credentialSubject/sails/2"]
将上述 JSON 指针应用于该运动员装备文档的结果 如下所示。
[
{
"pointer": "/sailNumber",
"value": "Earth101"
},
{
"pointer": "/sails/1",
"value": {
"size": 6.1,
"sailName": "Lahaina",
"year": 2023
}
},
{
"pointer": "/boards/0/year",
"value": 2022
},
{
"pointer": "/sails/2",
"value": {
"size": 7,
"sailName": "Lahaina",
"year": 2020
}
}
]
未签名文档的转换从规范化文档开始, 如下所示。
[ "_:c14n0 <https://windsurf.grotto-networking.com/selective#boardName> \"CompFoil170\" .\n", "_:c14n0 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n", "_:c14n0 <https://windsurf.grotto-networking.com/selective#year> \"2022\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:c14n1 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n", "_:c14n1 <https://windsurf.grotto-networking.com/selective#size> \"7.8E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n", "_:c14n1 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:c14n2 <https://windsurf.grotto-networking.com/selective#boardName> \"Kanaha Custom\" .\n", "_:c14n2 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n", "_:c14n2 <https://windsurf.grotto-networking.com/selective#year> \"2019\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:c14n3 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n", "_:c14n3 <https://windsurf.grotto-networking.com/selective#size> \"7\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:c14n3 <https://windsurf.grotto-networking.com/selective#year> \"2020\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:c14n4 <https://windsurf.grotto-networking.com/selective#sailName> \"Kihei\" .\n", "_:c14n4 <https://windsurf.grotto-networking.com/selective#size> \"5.5E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n", "_:c14n4 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:c14n5 <https://windsurf.grotto-networking.com/selective#boards> _:c14n0 .\n", "_:c14n5 <https://windsurf.grotto-networking.com/selective#boards> _:c14n2 .\n", "_:c14n5 <https://windsurf.grotto-networking.com/selective#sailNumber> \"Earth101\" .\n", "_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n1 .\n", "_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n3 .\n", "_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n4 .\n", "_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n6 .\n", "_:c14n6 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n", "_:c14n6 <https://windsurf.grotto-networking.com/selective#size> \"6.1E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n", "_:c14n6 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:c14n7 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n", "_:c14n7 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n5 .\n", "_:c14n7 <https://www.w3.org/2018/credentials#issuer> <https://vc.example/windsurf/racecommittee> .\n" ]
为防止空白节点 ID 的顺序可能造成信息泄露, 这些 ID 会通过 PRF(即 HMAC)处理,从而得到如下所示的规范化 HMAC 文档。这表示一个将接受强制和选择性披露的 有序语句列表,即 语句会从此列表中进行分组。
[ "_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n", "_:b0 <https://www.w3.org/2018/credentials#credentialSubject> _:b3 .\n", "_:b0 <https://www.w3.org/2018/credentials#issuer> <https://vc.example/windsurf/racecommittee> .\n", "_:b1 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n", "_:b1 <https://windsurf.grotto-networking.com/selective#size> \"7.8E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n", "_:b1 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:b2 <https://windsurf.grotto-networking.com/selective#boardName> \"CompFoil170\" .\n", "_:b2 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n", "_:b2 <https://windsurf.grotto-networking.com/selective#year> \"2022\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:b3 <https://windsurf.grotto-networking.com/selective#boards> _:b2 .\n", "_:b3 <https://windsurf.grotto-networking.com/selective#boards> _:b4 .\n", "_:b3 <https://windsurf.grotto-networking.com/selective#sailNumber> \"Earth101\" .\n", "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b1 .\n", "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b5 .\n", "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b6 .\n", "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b7 .\n", "_:b4 <https://windsurf.grotto-networking.com/selective#boardName> \"Kanaha Custom\" .\n", "_:b4 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n", "_:b4 <https://windsurf.grotto-networking.com/selective#year> \"2019\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:b5 <https://windsurf.grotto-networking.com/selective#sailName> \"Kihei\" .\n", "_:b5 <https://windsurf.grotto-networking.com/selective#size> \"5.5E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n", "_:b5 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:b6 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n", "_:b6 <https://windsurf.grotto-networking.com/selective#size> \"6.1E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n", "_:b6 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:b7 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n", "_:b7 <https://windsurf.grotto-networking.com/selective#size> \"7\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:b7 <https://windsurf.grotto-networking.com/selective#year> \"2020\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n" ]
上述规范文档会被分为强制和非强制 语句。选择性披露转换过程的最终输出 如下所示。现在每条语句都被分组为强制或非强制,并且 其在前一个语句列表中的索引都会被保留。
{
"mandatoryPointers": [
"/issuer",
"/credentialSubject/sailNumber",
"/credentialSubject/sails/1",
"/credentialSubject/boards/0/year",
"/credentialSubject/sails/2"
],
"mandatory": {
"dataType": "Map",
"value": [
[
0,
"_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n"
],
[
1,
"_:b0 <https://www.w3.org/2018/credentials#credentialSubject> _:b3 .\n"
],
[
2,
"_:b0 <https://www.w3.org/2018/credentials#issuer> <https://vc.example/windsurf/racecommittee> .\n"
],
[
8,
"_:b2 <https://windsurf.grotto-networking.com/selective#year> \"2022\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
],
[
9,
"_:b3 <https://windsurf.grotto-networking.com/selective#boards> _:b2 .\n"
],
[
11,
"_:b3 <https://windsurf.grotto-networking.com/selective#sailNumber> \"Earth101\" .\n"
],
[
14,
"_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b6 .\n"
],
[
15,
"_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b7 .\n"
],
[
22,
"_:b6 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n"
],
[
23,
"_:b6 <https://windsurf.grotto-networking.com/selective#size> \"6.1E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n"
],
[
24,
"_:b6 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
],
[
25,
"_:b7 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n"
],
[
26,
"_:b7 <https://windsurf.grotto-networking.com/selective#size> \"7\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
],
[
27,
"_:b7 <https://windsurf.grotto-networking.com/selective#year> \"2020\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
]
]
},
"nonMandatory": {
"dataType": "Map",
"value": [
[
3,
"_:b1 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n"
],
[
4,
"_:b1 <https://windsurf.grotto-networking.com/selective#size> \"7.8E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n"
],
[
5,
"_:b1 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
],
[
6,
"_:b2 <https://windsurf.grotto-networking.com/selective#boardName> \"CompFoil170\" .\n"
],
[
7,
"_:b2 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n"
],
[
10,
"_:b3 <https://windsurf.grotto-networking.com/selective#boards> _:b4 .\n"
],
[
12,
"_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b1 .\n"
],
[
13,
"_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b5 .\n"
],
[
16,
"_:b4 <https://windsurf.grotto-networking.com/selective#boardName> \"Kanaha Custom\" .\n"
],
[
17,
"_:b4 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n"
],
[
18,
"_:b4 <https://windsurf.grotto-networking.com/selective#year> \"2019\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
],
[
19,
"_:b5 <https://windsurf.grotto-networking.com/selective#sailName> \"Kihei\" .\n"
],
[
20,
"_:b5 <https://windsurf.grotto-networking.com/selective#size> \"5.5E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n"
],
[
21,
"_:b5 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
]
]
},
"hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}
下一步是创建基础证明配置并对其进行规范化。 以下两个示例展示了这一过程。
{
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"@context": [
"https://www.w3.org/ns/credentials/v2",
{
"@vocab": "https://windsurf.grotto-networking.com/selective#"
}
]
}
_:c14n0 <http://purl.org/dc/terms/created> "2023-08-15T23:36:38Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> . _:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/security#DataIntegrityProof> . _:c14n0 <https://w3id.org/security#cryptosuite> "bbs-2023"^^<https://w3id.org/security#cryptosuiteString> . _:c14n0 <https://w3id.org/security#proofPurpose> <https://w3id.org/security#assertionMethod> . _:c14n0 <https://w3id.org/security#verificationMethod> <did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ> .
在哈希步骤中,我们计算规范化证明
选项的 SHA-256 哈希以生成 proofHash,并计算所有强制
N-Quads 拼接结果的 SHA-256 哈希以生成 mandatoryHash。它们
以十六进制格式显示如下。
{
"proofHash": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf",
"mandatoryHash": "555de05f898817e31301bac187d0c3ff2b03e2cbdb4adb4d568c17de961f9a18"
}
下面显示的是计算得到的十六进制 bbsSignature,以及
mandatoryPointers。它们与
hmacKey 一起提供给最终序列化步骤。
{
"bbsSignature": "8331f55ad458fe5c322420b2cb806f9a20ea6b2b8a29d51710026d71ace5da080064b488818efc75a439525bd031450822a6a332da781926e19360b90166431124efcf3d060fbc750c6122c714c07f71",
"mandatoryPointers": [
"/issuer",
"/credentialSubject/sailNumber",
"/credentialSubject/sails/1",
"/credentialSubject/boards/0/year",
"/credentialSubject/sails/2"
]
}
最后,将上述值通过第
3.2.1
serializeBaseProofValue节的算法运行,以生成
如下所示的签名基础文档中使用的 proofValue。
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
{
"@vocab": "https://windsurf.grotto-networking.com/selective#"
}
],
"type": [
"VerifiableCredential"
],
"issuer": "https://vc.example/windsurf/racecommittee",
"credentialSubject": {
"sailNumber": "Earth101",
"sails": [
{
"size": 5.5,
"sailName": "Kihei",
"year": 2023
},
{
"size": 6.1,
"sailName": "Lahaina",
"year": 2023
},
{
"size": 7,
"sailName": "Lahaina",
"year": 2020
},
{
"size": 7.8,
"sailName": "Lahaina",
"year": 2023
}
],
"boards": [
{
"boardName": "CompFoil170",
"brand": "Wailea",
"year": 2022
},
{
"boardName": "Kanaha Custom",
"brand": "Wailea",
"year": 2019
}
]
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0ChVhQgzH1WtRY_lwyJCCyy4BvmiDqayuKKdUXEAJtcazl2ggAZLSIgY78daQ5UlvQMUUIIqajMtp4GSbhk2C5AWZDESTvzz0GD7x1DGEixxTAf3FYQDpbvyXTTZCxjDXNI1e-am9CMB6U_J5S936Tt3PFYUvfVV3gX4mIF-MTAbrBh9DD_ysD4svbSttNVowX3pYfmhhYYKTvGvo9pXVJbxIrm3i4wkdhUxqKCTIGrnxFuAdZwWi6T3omD5wzZ7bAGbRneEEQSxBmXtvnC6Pr59nPv_v3HrAW9wq_uxYzF_NyaX3GPv0h_FV2T2OSao8C6uoyWiqIj1ggABEiM0RVZneImaq7zN3u_wARIjNEVWZ3iJmqu8zd7v-FZy9pc3N1ZXJ4HS9jcmVkZW50aWFsU3ViamVjdC9zYWlsTnVtYmVyeBovY3JlZGVudGlhbFN1YmplY3Qvc2FpbHMvMXggL2NyZWRlbnRpYWxTdWJqZWN0L2JvYXJkcy8wL3llYXJ4Gi9jcmVkZW50aWFsU3ViamVjdC9zYWlscy8y"
}
}
创建 BBS 证明
时会使用随机数,并且可选的 presentationHeader 可以作为输入。
为了提供一组确定性的测试
向量,我们使用了
[CFRG-BBS-SIGNATURE] 中的模拟随机标量
过程。我们用于
生成派生证明测试向量的 seed 和
presentationHeader 值以十六进制给出如下。
{
"presentationHeaderHex": "113377aa",
"pseudoRandSeedHex": "332e313431353932363533353839373933323338343632363433333833323739"
}
要创建派生证明,持有者从一个
包含基础证明的已签名文档开始。我们用于这些测试向量的基础文档是
上面第 A.1.1
基础证明节中的最后一个示例。第一
步是运行第 3.2.2
parseBaseProofValue节的算法,以
恢复 bbsSignature、hmacKey 和 mandatoryPointers,
如下所示。
{
"bbsSignature": "8331f55ad458fe5c322420b2cb806f9a20ea6b2b8a29d51710026d71ace5da080064b488818efc75a439525bd031450822a6a332da781926e19360b90166431124efcf3d060fbc750c6122c714c07f71",
"hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
"mandatoryPointers": [
"/issuer",
"/credentialSubject/sailNumber",
"/credentialSubject/sails/1",
"/credentialSubject/boards/0/year",
"/credentialSubject/sails/2"
]
}
接下来,持有者需要通过指定用于选择性披露的 JSON 指针, 指明还希望向验证者披露哪些内容(如果有)。在我们的 风帆冲浪比赛场景中,一名运动员(持有者)刚刚完成 第一天的比赛,并希望向公众(验证者) 披露其在比赛中使用的所有风帆冲浪板的详细信息。这些 如下所示。请注意,这与强制披露 信息略有重叠,后者只包含其最新冲浪板的年份。
["/credentialSubject/boards/0", "/credentialSubject/boards/1"]
为生成 revealDocument(即最终将
被签名并发送给验证者的未签名文档),我们将选择性指针
追加到强制指针,并将这些组合指针连同
不带证明的文档输入 [DI-ECDSA] 的
selectJsonLd 算法,
得到如下结果。
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
{
"@vocab": "https://windsurf.grotto-networking.com/selective#"
}
],
"type": [
"VerifiableCredential"
],
"issuer": "https://vc.example/windsurf/racecommittee",
"credentialSubject": {
"sailNumber": "Earth101",
"sails": [
{
"size": 6.1,
"sailName": "Lahaina",
"year": 2023
},
{
"size": 7,
"sailName": "Lahaina",
"year": 2020
}
],
"boards": [
{
"year": 2022,
"boardName": "CompFoil170",
"brand": "Wailea"
},
{
"boardName": "Kanaha Custom",
"brand": "Wailea",
"year": 2019
}
]
}
}
既然我们已经知道了公开文档是什么样子,就需要向验证者提供 适当更新的信息,说明哪些语句是 强制的,以及所选非强制语句的索引。运行 § 4.4.3 CreateDisclosureData 会生成大量关于 相对于原始文档的各种语句组的信息。下面我们展示 这些组的一部分索引。
{
"combinedIndexes":[0,1,2,6,7,8,9,10,11,14,15,16,17,18,22,23,24,25,26,27],
"mandatoryIndexes":[0,1,2,8,9,11,14,15,22,23,24,25,26,27],
"nonMandatoryIndexes":[3,4,5,6,7,10,12,13,16,17,18,19,20,21],
"selectiveIndexes":[0,1,6,7,8,9,10,16,17,18]
}
验证者需要能够聚合并哈希强制语句。为了
实现这一点,我们向其提供强制语句的索引列表,
并将其调整为这些语句在披露文档中的位置(即相对于
combinedIndexes),而 selectiveIndexes 需要相对于
它们在 nonMandatoryIndexes 中的位置进行调整。这些“调整后的”索引
如下所示。
{
"adjMandatoryIndexes":[0,1,2,5,6,8,9,10,14,15,16,17,18,19],
"adjSelectiveIndexes":[3,4,5,8,9,10]
}
最后一项重要的披露数据是从规范空白节点
ID 到基于 HMAC 的打乱 ID 的映射,即 labelMap,它按照第
§ 4.4.3 CreateDisclosureData节计算得出。如下所示,
同时还展示了
除公开文档之外的其余披露数据。
{
"bbsProof":"9831ba06852694fb44eb56cd9f66581330d9493671a3ad5ed28610c2550c5bfda6cada7cbaf37e9af0c873a4ec6813bf857d539543bc45ba1349fe3233b446f6c46190c40aa8456d98312ed7535c3003e3a77af752ed6f7ee162df4e38a268ad87cc5a10ff38dcc6633810e08ac5a80dacfe6e7dec3ca65fb1dab8d1b0da22b8f26040238c700b8310de92c9c2ec118b2de6b0ccdc72fbdd3329ccf7bc729829e8492d0a796f6e09131884f6fdd0df8028d5ef8f05d9aa9817872598c56421526dbe5db40586cd2b83a454652f71637e57917abd22f45bb67d48fcebdf5464671aec2e845f87f87c1d0eb934db3fb9e2310d483d67110b5f64127827888e8cd9259ea78f6683184ca4e71845b803d93a3554f4577716f939bd36f26eb740771bd5c35247ef4abc2b0e701721a6e8edf62a63af3a032df895cde06d0b15ca8c1a7507249118f9d096fcc5a3f9a39ec1a870ef619efa6af61fd93b74b82b24317def59f981fc8ec2b5633d8eb8711b108552b7b6e748648503fecdf52ac0a76eca89306361262cc4767bbb84e904d1a7523bc19d67bc501c78949616bef65470b067f81759d9a29f9c2775c0888a4617b57018ece111e62cd8365b4783fbe53bcec846bf724bdddc196fced05c59c35ebb735aea9a83f0e5233cdb9fbb8fd2e3b007ee7f69cafc37c4993ddfc747d7793b48ea48213154b459260c29da6dd41de9539a3352855afa398b2bafd47d07d765",
"labelMap":{"dataType":"Map","value":[["c14n0","b2"],["c14n1","b4"],["c14n2","b3"],["c14n3","b7"],["c14n4","b6"],["c14n5","b0"]]},
"mandatoryIndexes":[0,1,2,5,6,8,9,10,14,15,16,17,18,19],
"adjSelectiveIndexes":[3,4,5,8,9,10],
"presentationHeader":{"0":17,"1":51,"2":119,"3":170}
}
最后,将上述披露数据用于第 3.2.3 serializeDerivedProofValue节中的算法,我们将得到如下所示的已签名派生(公开) 文档。
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
{
"@vocab": "https://windsurf.grotto-networking.com/selective#"
}
],
"type": [
"VerifiableCredential"
],
"issuer": "https://vc.example/windsurf/racecommittee",
"credentialSubject": {
"sailNumber": "Earth101",
"sails": [
{
"size": 6.1,
"sailName": "Lahaina",
"year": 2023
},
{
"size": 7,
"sailName": "Lahaina",
"year": 2020
}
],
"boards": [
{
"year": 2022,
"boardName": "CompFoil170",
"brand": "Wailea"
},
{
"boardName": "Kanaha Custom",
"brand": "Wailea",
"year": 2019
}
]
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0DhVkCEJgxugaFJpT7ROtWzZ9mWBMw2Uk2caOtXtKGEMJVDFv9psrafLrzfprwyHOk7GgTv4V9U5VDvEW6E0n-MjO0RvbEYZDECqhFbZgxLtdTXDAD46d691Ltb37hYt9OOKJorYfMWhD_ONzGYzgQ4IrFqA2s_m597DymX7HauNGw2iK48mBAI4xwC4MQ3pLJwuwRiy3msMzccvvdMynM97xymCnoSS0KeW9uCRMYhPb90N-AKNXvjwXZqpgXhyWYxWQhUm2-XbQFhs0rg6RUZS9xY35XkXq9IvRbtn1I_OvfVGRnGuwuhF-H-HwdDrk02z-54jENSD1nEQtfZBJ4J4iOjNklnqePZoMYTKTnGEW4A9k6NVT0V3cW-Tm9NvJut0B3G9XDUkfvSrwrDnAXIabo7fYqY686Ay34lc3gbQsVyowadQckkRj50Jb8xaP5o57BqHDvYZ76avYf2Tt0uCskMX3vWfmB_I7CtWM9jrhxGxCFUre250hkhQP-zfUqwKduyokwY2EmLMR2e7uE6QTRp1I7wZ1nvFAceJSWFr72VHCwZ_gXWdmin5wndcCIikYXtXAY7OER5izYNltHg_vlO87IRr9yS93cGW_O0FxZw167c1rqmoPw5SM825-7j9LjsAfuf2nK_DfEmT3fx0fXeTtI6kghMVS0WSYMKdpt1B3pU5ozUoVa-jmLK6_UfQfXZaYAAgEEAgMDBwQGBQCOAAECBQYICQoODxAREhOGAwQFCAkKRBEzd6o"
}
}
使用匿名持有者绑定功能的第一步是由 持有者生成其 holderSecret 值,然后按照 [CFRG-Blind-BBS-Signature] 的承诺计算过程 为该值计算带证明的承诺。该过程的示例值和 输出如下所示。
{
"holderSecretHex": "8fc6cc3f65db4ba5e3ed63fe9d2bd57a9c7df9c7f6bf2b898b308d5493b07eb6"
}
{
"secretProverBlind": "12901a77b3906af68d9e4214dce887d127b2a51d6311bbe7d087d45737acd2db",
"commitmentWithProof": "ab77a14fddfafc7ae6ea82b0ef6048059225f96c9206903a34c6ec6beba702652e9d64fac1917e372853867d944e4a8059e0c26bc871cac14736e73685cd3006299539b93df64cdf661af2bc6300976528c5092c6dc842abaaa624f2184d3d5b75be0ede9c4822161149ef51a965ddda260e10b9246ecaea020ef952e3b3ed6e724bcb5d1a9c4004f0aea2cba030c27c"
}
holderSecret 和 secretProverBlind 应由持有者保留并保持秘密。 commitmentWithProof 值应传达给颁发者。
在匿名持有者绑定选项下添加基础证明的过程始于 颁发者从持有者接收 commitmentWithProof 值,然后 使用 [CFRG-Blind-BBS-Signature] 的承诺验证过程 验证该值。 基础证明一节中说明并使用的密码学密钥材料 也将在此处使用,并在 下面再次列出。
{
"publicKeyHex": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"privateKeyHex": "66d36e118832af4c5e28b2dfe1b9577857e57b042a33e06bdea37b811ed09ee0",
"hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}
在此场景中,我们考虑驾驶执照的电子版本。
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
],
"type": [
"VerifiableCredential",
"Iso18013DriversLicenseCredential"
],
"issuer": {
"id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
"name": "Utopia Department of Motor Vehicles",
"url": "https://dmv.utopia.example/",
"image": "https://dmv.utopia.example/logo.png"
},
"issuanceDate": "2023-11-15T10:00:00-07:00",
"expirationDate": "2028-11-15T12:00:00-06:00",
"name": "Utopia Driver's License",
"image": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC",
"description": "A license granting driving privileges in Utopia.",
"credentialSubject": {
"type": "LicensedDriver",
"driversLicense": {
"type": "Iso18013DriversLicense",
"document_number": "542426814",
"family_name": "TURNER",
"given_name": "SUSAN",
"portrait": "data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==",
"birth_date": "1998-08-28",
"issue_date": "2023-01-15T10:00:00-07:00",
"expiry_date": "2028-08-27T12:00:00-06:00",
"issuing_country": "UA",
"issuing_authority": "UADMV",
"driving_privileges": [
{
"codes": [
{
"code": "D"
}
],
"vehicle_category_code": "D",
"issue_date": "2019-01-01",
"expiry_date": "2027-01-01"
},
{
"codes": [
{
"code": "C"
}
],
"vehicle_category_code": "C",
"issue_date": "2019-01-01",
"expiry_date": "2017-01-01"
}
],
"un_distinguishing_sign": "UTA",
"aamva_aka_suffix": "1ST",
"sex": 2,
"aamva_family_name_truncation": "N",
"aamva_given_name_truncation": "N"
}
}
}
为保护持有者的隐私,唯一的强制字段是 "issuer" 和 "expirationDate",通过下面给出的强制指针实现。
["/issuer", "/expirationDate"]
未签名文档的转换从规范化文档开始, 如下所示。
[
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/image> <https://dmv.utopia.example/logo.png> .\n",
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/name> \"Utopia Department of Motor Vehicles\" .\n",
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/url> <https://dmv.utopia.example/> .\n",
"_:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicenseCredential> .\n",
"_:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n",
"_:c14n0 <https://schema.org/description> \"A license granting driving privileges in Utopia.\" .\n",
"_:c14n0 <https://schema.org/image> <data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC> .\n",
"_:c14n0 <https://schema.org/name> \"Utopia Driver's License\" .\n",
"_:c14n0 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n1 .\n",
"_:c14n0 <https://www.w3.org/2018/credentials#expirationDate> \"2028-11-15T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:c14n0 <https://www.w3.org/2018/credentials#issuanceDate> \"2023-11-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:c14n0 <https://www.w3.org/2018/credentials#issuer> <did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> .\n",
"_:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#LicensedDriver> .\n",
"_:c14n1 <https://w3id.org/vdl#license> _:c14n2 .\n",
"_:c14n2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicense> .\n",
"_:c14n2 <https://w3id.org/vdl#birthDate> \"1998-08-28\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:c14n2 <https://w3id.org/vdl#documentNumber> \"542426814\" .\n",
"_:c14n2 <https://w3id.org/vdl#drivingPrivileges> \"[{\\\"codes\\\":[{\\\"code\\\":\\\"D\\\"}],\\\"expiry_date\\\":\\\"2027-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"D\\\"},{\\\"codes\\\":[{\\\"code\\\":\\\"C\\\"}],\\\"expiry_date\\\":\\\"2017-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"C\\\"}]\"^^<http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON> .\n",
"_:c14n2 <https://w3id.org/vdl#expiryDate> \"2028-08-27T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:c14n2 <https://w3id.org/vdl#familyName> \"TURNER\" .\n",
"_:c14n2 <https://w3id.org/vdl#givenName> \"SUSAN\" .\n",
"_:c14n2 <https://w3id.org/vdl#issueDate> \"2023-01-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:c14n2 <https://w3id.org/vdl#issuingAuthority> \"UADMV\" .\n",
"_:c14n2 <https://w3id.org/vdl#issuingCountry> \"UA\" .\n",
"_:c14n2 <https://w3id.org/vdl#portrait> <data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==> .\n",
"_:c14n2 <https://w3id.org/vdl#sex> \"2\"^^<http://www.w3.org/2001/XMLSchema#unsignedInt> .\n",
"_:c14n2 <https://w3id.org/vdl#unDistinguishingSign> \"UTA\" .\n",
"_:c14n2 <https://w3id.org/vdl/aamva#akaSuffix> \"1ST\" .\n",
"_:c14n2 <https://w3id.org/vdl/aamva#familyNameTruncation> \"N\" .\n",
"_:c14n2 <https://w3id.org/vdl/aamva#givenNameTruncation> \"N\" .\n"
]
为防止空白节点 ID 的顺序可能导致信息泄露, 会通过 PRF(即 HMAC)对这些 ID 进行处理,从而得到如下所示的规范化 HMAC 文档。这表示一个将接受 强制和选择性披露的有序语句列表,即 语句会从该列表中进行分组。
[
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/image> <https://dmv.utopia.example/logo.png> .\n",
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/name> \"Utopia Department of Motor Vehicles\" .\n",
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/url> <https://dmv.utopia.example/> .\n",
"_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#LicensedDriver> .\n",
"_:b0 <https://w3id.org/vdl#license> _:b2 .\n",
"_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicenseCredential> .\n",
"_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n",
"_:b1 <https://schema.org/description> \"A license granting driving privileges in Utopia.\" .\n",
"_:b1 <https://schema.org/image> <data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC> .\n",
"_:b1 <https://schema.org/name> \"Utopia Driver's License\" .\n",
"_:b1 <https://www.w3.org/2018/credentials#credentialSubject> _:b0 .\n",
"_:b1 <https://www.w3.org/2018/credentials#expirationDate> \"2028-11-15T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:b1 <https://www.w3.org/2018/credentials#issuanceDate> \"2023-11-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:b1 <https://www.w3.org/2018/credentials#issuer> <did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> .\n",
"_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicense> .\n",
"_:b2 <https://w3id.org/vdl#birthDate> \"1998-08-28\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:b2 <https://w3id.org/vdl#documentNumber> \"542426814\" .\n",
"_:b2 <https://w3id.org/vdl#drivingPrivileges> \"[{\\\"codes\\\":[{\\\"code\\\":\\\"D\\\"}],\\\"expiry_date\\\":\\\"2027-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"D\\\"},{\\\"codes\\\":[{\\\"code\\\":\\\"C\\\"}],\\\"expiry_date\\\":\\\"2017-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"C\\\"}]\"^^<http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON> .\n",
"_:b2 <https://w3id.org/vdl#expiryDate> \"2028-08-27T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:b2 <https://w3id.org/vdl#familyName> \"TURNER\" .\n",
"_:b2 <https://w3id.org/vdl#givenName> \"SUSAN\" .\n",
"_:b2 <https://w3id.org/vdl#issueDate> \"2023-01-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:b2 <https://w3id.org/vdl#issuingAuthority> \"UADMV\" .\n",
"_:b2 <https://w3id.org/vdl#issuingCountry> \"UA\" .\n",
"_:b2 <https://w3id.org/vdl#portrait> <data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==> .\n",
"_:b2 <https://w3id.org/vdl#sex> \"2\"^^<http://www.w3.org/2001/XMLSchema#unsignedInt> .\n",
"_:b2 <https://w3id.org/vdl#unDistinguishingSign> \"UTA\" .\n",
"_:b2 <https://w3id.org/vdl/aamva#akaSuffix> \"1ST\" .\n",
"_:b2 <https://w3id.org/vdl/aamva#familyNameTruncation> \"N\" .\n",
"_:b2 <https://w3id.org/vdl/aamva#givenNameTruncation> \"N\" .\n"
]
上述规范文档会被分组为强制和非强制 语句。选择性披露转换过程的最终输出 如下所示。现在每条语句都被分组为强制或非强制,并且 会记住其在前一个语句列表中的索引。
{
"mandatoryPointers": [
"/issuer",
"/expirationDate"
],
"mandatory": {
"dataType": "Map",
"value": [
[
0,
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/image> <https://dmv.utopia.example/logo.png> .\n"
],
[
1,
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/name> \"Utopia Department of Motor Vehicles\" .\n"
],
[
2,
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/url> <https://dmv.utopia.example/> .\n"
],
[
5,
"_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicenseCredential> .\n"
],
[
6,
"_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n"
],
[
11,
"_:b1 <https://www.w3.org/2018/credentials#expirationDate> \"2028-11-15T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
],
[
13,
"_:b1 <https://www.w3.org/2018/credentials#issuer> <did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> .\n"
]
]
},
"nonMandatory": {
"dataType": "Map",
"value": [
[
3,
"_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#LicensedDriver> .\n"
],
[
4,
"_:b0 <https://w3id.org/vdl#license> _:b2 .\n"
],
[
7,
"_:b1 <https://schema.org/description> \"A license granting driving privileges in Utopia.\" .\n"
],
[
8,
"_:b1 <https://schema.org/image> <data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC> .\n"
],
[
9,
"_:b1 <https://schema.org/name> \"Utopia Driver's License\" .\n"
],
[
10,
"_:b1 <https://www.w3.org/2018/credentials#credentialSubject> _:b0 .\n"
],
[
12,
"_:b1 <https://www.w3.org/2018/credentials#issuanceDate> \"2023-11-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
],
[
14,
"_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicense> .\n"
],
[
15,
"_:b2 <https://w3id.org/vdl#birthDate> \"1998-08-28\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
],
[
16,
"_:b2 <https://w3id.org/vdl#documentNumber> \"542426814\" .\n"
],
[
17,
"_:b2 <https://w3id.org/vdl#drivingPrivileges> \"[{\\\"codes\\\":[{\\\"code\\\":\\\"D\\\"}],\\\"expiry_date\\\":\\\"2027-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"D\\\"},{\\\"codes\\\":[{\\\"code\\\":\\\"C\\\"}],\\\"expiry_date\\\":\\\"2017-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"C\\\"}]\"^^<http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON> .\n"
],
[
18,
"_:b2 <https://w3id.org/vdl#expiryDate> \"2028-08-27T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
],
[
19,
"_:b2 <https://w3id.org/vdl#familyName> \"TURNER\" .\n"
],
[
20,
"_:b2 <https://w3id.org/vdl#givenName> \"SUSAN\" .\n"
],
[
21,
"_:b2 <https://w3id.org/vdl#issueDate> \"2023-01-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
],
[
22,
"_:b2 <https://w3id.org/vdl#issuingAuthority> \"UADMV\" .\n"
],
[
23,
"_:b2 <https://w3id.org/vdl#issuingCountry> \"UA\" .\n"
],
[
24,
"_:b2 <https://w3id.org/vdl#portrait> <data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==> .\n"
],
[
25,
"_:b2 <https://w3id.org/vdl#sex> \"2\"^^<http://www.w3.org/2001/XMLSchema#unsignedInt> .\n"
],
[
26,
"_:b2 <https://w3id.org/vdl#unDistinguishingSign> \"UTA\" .\n"
],
[
27,
"_:b2 <https://w3id.org/vdl/aamva#akaSuffix> \"1ST\" .\n"
],
[
28,
"_:b2 <https://w3id.org/vdl/aamva#familyNameTruncation> \"N\" .\n"
],
[
29,
"_:b2 <https://w3id.org/vdl/aamva#givenNameTruncation> \"N\" .\n"
]
]
},
"hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}
接下来的步骤是创建基础证明配置并对其进行规范化。 以下两个示例展示了这一过程。
{
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
]
}
_:c14n0 <http://purl.org/dc/terms/created> "2023-08-15T23:36:38Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> . _:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/security#DataIntegrityProof> . _:c14n0 <https://w3id.org/security#cryptosuite> "bbs-2023"^^<https://w3id.org/security#cryptosuiteString> . _:c14n0 <https://w3id.org/security#proofPurpose> <https://w3id.org/security#assertionMethod> . _:c14n0 <https://w3id.org/security#verificationMethod> <did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ> .
在哈希步骤中,我们计算规范化证明
选项的 SHA-256 哈希以生成 proofHash,并计算所有
强制 N-Quads 拼接结果的 SHA-256 哈希以生成 mandatoryHash。这些值
以十六进制格式显示如下。
{
"proofHash": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf",
"mandatoryHash": "8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb"
}
现在,我们在 3.3.2 基础 证明序列化 (bbs-2023) 过程中使用 [CFRG-Blind-BBS-Signature] 的盲签名生成过程。 下面显示计算得到的 bbsSignature、bbsHeader、publicKey、 hmacKey、mandatoryPointers 和 featureOption,其中字节 数据以十六进制显示。
{
"bbsSignature": "90eadd70a16661f3d596f3560fc485f7c23ba969eb7c237d481b3596b2f66279bd5a62fa523777eb73b5cfa361885f1a00864b960baf1b92d2b55c0652ebe39024f88e1377911c40bf14cb5fbc808ee1",
"bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
"publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
"mandatoryPointers": [
"/issuer",
"/expirationDate"
],
"featureOption": "anonymous_holder_binding"
}
最后,将上述值通过第 3.2.1 serializeBaseProofValue节的算法运行,以生成 如下所示的已签名基础文档中使用的 proofValue。
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
],
"type": [
"VerifiableCredential",
"Iso18013DriversLicenseCredential"
],
"issuer": {
"id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
"name": "Utopia Department of Motor Vehicles",
"url": "https://dmv.utopia.example/",
"image": "https://dmv.utopia.example/logo.png"
},
"issuanceDate": "2023-11-15T10:00:00-07:00",
"expirationDate": "2028-11-15T12:00:00-06:00",
"name": "Utopia Driver's License",
"image": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC",
"description": "A license granting driving privileges in Utopia.",
"credentialSubject": {
"type": "LicensedDriver",
"driversLicense": {
"type": "Iso18013DriversLicense",
"document_number": "542426814",
"family_name": "TURNER",
"given_name": "SUSAN",
"portrait": "data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==",
"birth_date": "1998-08-28",
"issue_date": "2023-01-15T10:00:00-07:00",
"expiry_date": "2028-08-27T12:00:00-06:00",
"issuing_country": "UA",
"issuing_authority": "UADMV",
"driving_privileges": [
{
"codes": [
{
"code": "D"
}
],
"vehicle_category_code": "D",
"issue_date": "2019-01-01",
"expiry_date": "2027-01-01"
},
{
"codes": [
{
"code": "C"
}
],
"vehicle_category_code": "C",
"issue_date": "2019-01-01",
"expiry_date": "2017-01-01"
}
],
"un_distinguishing_sign": "UTA",
"aamva_aka_suffix": "1ST",
"sex": 2,
"aamva_family_name_truncation": "N",
"aamva_given_name_truncation": "N"
}
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0EhVhQkOrdcKFmYfPVlvNWD8SF98I7qWnrfCN9SBs1lrL2Ynm9WmL6Ujd363O1z6NhiF8aAIZLlguvG5LStVwGUuvjkCT4jhN3kRxAvxTLX7yAjuFYQDpbvyXTTZCxjDXNI1e-am9CMB6U_J5S936Tt3PFYUvfjuoRLATYnhM4gPlnZuuuc2k_dfG7y7qkc9wGJUvexPtYYKTvGvo9pXVJbxIrm3i4wkdhUxqKCTIGrnxFuAdZwWi6T3omD5wzZ7bAGbRneEEQSxBmXtvnC6Pr59nPv_v3HrAW9wq_uxYzF_NyaX3GPv0h_FV2T2OSao8C6uoyWiqIj1ggABEiM0RVZneImaq7zN3u_wARIjNEVWZ3iJmqu8zd7v-CZy9pc3N1ZXJvL2V4cGlyYXRpb25EYXRl"
}
}
如 一节中所述,我们使用 模拟随机数生成过程,并演示 presentationHeader 的使用。 此处使用相同的 seed 和 presentationHeader, 并在下面再次列出。
{
"presentationHeaderHex": "113377aa",
"pseudoRandSeedHex": "332e313431353932363533353839373933323338343632363433333833323739"
}
要创建派生证明,持有者从 包含基础证明的已签名文档开始。我们用于这些测试向量的基础文档是 上面第 A.3.2 持有者绑定基础证明节中的最后一个示例。 第一步是运行第 3.2.2 parseBaseProofValue节的算法,以 恢复 bbsSignature、bbsHeader、publicKey、hmacKey、 mandatoryPointers 和 featureOption,如下所示。
{
"bbsSignature": "90eadd70a16661f3d596f3560fc485f7c23ba969eb7c237d481b3596b2f66279bd5a62fa523777eb73b5cfa361885f1a00864b960baf1b92d2b55c0652ebe39024f88e1377911c40bf14cb5fbc808ee1",
"bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
"publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
"mandatoryPointers": [
"/issuer",
"/expirationDate"
],
"featureOption": "anonymous_holder_binding"
}
接下来,持有者需要通过指定用于选择性披露的 JSON 指针, 指明还希望向验证者披露哪些内容(如果有)。在这种 情况下,持有者只希望披露其驾驶权限。
["/credentialSubject/driversLicense/issuing_country", "/credentialSubject/driversLicense/driving_privileges"]
为生成 revealDocument(即最终将
被签名并发送给验证者的未签名文档),我们将选择性指针
追加到强制指针,并将这些组合指针连同
不带证明的文档输入 [DI-ECDSA] 的
selectJsonLd 算法,
得到如下结果。
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
],
"type": [
"VerifiableCredential",
"Iso18013DriversLicenseCredential"
],
"issuer": {
"id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
"name": "Utopia Department of Motor Vehicles",
"url": "https://dmv.utopia.example/",
"image": "https://dmv.utopia.example/logo.png"
},
"expirationDate": "2028-11-15T12:00:00-06:00",
"credentialSubject": {
"type": "LicensedDriver",
"driversLicense": {
"type": "Iso18013DriversLicense",
"issuing_country": "UA",
"driving_privileges": [
{
"codes": [
{
"code": "D"
}
],
"vehicle_category_code": "D",
"issue_date": "2019-01-01",
"expiry_date": "2027-01-01"
},
{
"codes": [
{
"code": "C"
}
],
"vehicle_category_code": "C",
"issue_date": "2019-01-01",
"expiry_date": "2017-01-01"
}
]
}
}
}
既然我们已经知道了公开文档是什么样子,就需要向验证者提供 适当更新的信息,说明哪些语句是 强制的,以及所选非强制语句的索引。运行 § 4.4.3 CreateDisclosureData 会生成大量关于 相对于原始文档的各种语句组的信息。下面,我们展示 这些组的一部分索引。
{"combinedIndexes":[0,1,2,3,4,5,6,10,11,13,14,17,23],"mandatoryIndexes":[0,1,2,5,6,11,13],"nonMandatoryIndexes":[3,4,7,8,9,10,12,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29],"selectiveIndexes":[3,4,5,6,10,14,17,23]}
验证者需要能够聚合并哈希强制语句。为了
实现这一点,我们向其提供强制语句的索引列表,
并将其调整为这些语句在披露文档中的位置(即相对于
combinedIndexes),而 selectiveIndexes 则需要相对于
它们在 nonMandatoryIndexes 中的位置进行调整。这些“调整后的”索引
如下所示。
{"adjMandatoryIndexes":[0,1,2,5,6,8,9],"adjSelectiveIndexes":[0,1,5,7,10,16]}
最后一项重要的披露数据是从规范空白节点
ID 到基于 HMAC 的打乱 ID 的映射,即 labelMap,它按照第
§ 4.4.3 CreateDisclosureData节计算得出。如下所示,
同时还展示了
除公开文档之外的其余披露数据。请注意,这里我们
展示的是适用于 featureOption 等于
"anonymous_holder_binding" 时的结果,该选项使用
[CFRG-Blind-BBS-Signature] 的盲证明生成
过程。请注意,
blindAdjDisclosedIdxs 是
证明序列化过程中使用的最终 BBS 选择性索引集,
它来自以
adjSelectiveIndexes 作为输入的盲 BBS 证明生成函数。
{"bbsProof":"a19db05cca1237d9965b0bb3197c4962a7fb49c97af131c80ea2d8f949078ff5642acdb33d27d06b97f87ff906a2a23bb0c3dd778572b892785faefdc25811318b0b46e25b8863898b0600701a71c256ee9a7347a1a577fe2e3793b1c0390e4d8f9fff9161074eebba852bcca8089eed76416ac9f178b850e7688c26cfbdee344fa75d9ba2cf22417e3c70be7891f6de040928d4a665005ddbe3b7372ecb87baad726f1535d4600a0198d3a36a17ad673160f8ef5e5fd74f2542b214cc4534ee82b0a90c0501ca9749c8327afcb97e14220f2e516dfc3cb2ed2ffdd3845a25cb64e1a2aa9987bbc122755158d787a2356e28f2affff31b83a2cdff26d5ac1aa72f4d6c40fe96ad230ce09fd4e9b8998357c2964da031e59c3b8c2241da00bc66a6216af7cd02b535577fa3b54bf9a0d230183b03aa145dbabc7fed3710d879c6b8d4273e6e377bed382de985f561ff9b2b3445f29957655600cbd1b29714f52c55ff05bc204203e65bdf6f818e976c690becfed9284b27c2dead96803efad949ffb519b7024530b08b5ed4c8e7472ed20c3866b79658e1b2d2c5b88a60da07614afa4906c73a6e5ad9113282288173e265236fa57d72c97f85c86b43349516f8e2f52f756d43cd2d9cf8c673db404d14007706ebbd4f7b5bbd19cdce9f48b2dac2db7f0f0c3fb18bd8e66e28fe46dafc3961e5945779faf5407190a33ce00efd07222cc142d40cab9b9d591589a30d056dae47d376d3ac5fab3201bbada604dd8e5e292185f38e2bcd58e81b2fec1e7b5754b7b28bd127abc929e950cb75100e94695f1ad13c09c1d394664029b66bdd49304df3ae1e2a90a6309f07c47555ccaea9cd17d80eaad6b7c29e9335a69338446ff666ac5802cfe36057c449d392bda99d2657fb8b6cf02d7ce4d9dccd8e97033accc5c10f092ec7bf0b3c0b2afc64a1a429d81cc485388f6f390dd97f648c3712ee0b93a7e96b268437e6e3537fb7918cee2a4ac3f895c7945988d7d3880238b8cf6062da171aa87545cf62072b20e698eb4ac12450c0b95a77e946fada8d46102abfa9a5a12d2a71380dedb51e2a57c97514813c17ea93e6ca19077c2a2511bf8fd158c4ed7361590b040915a3cb76f323300111303d8dd31c55474d514209bf01ed6639d4d81a1b30be54444e523e2ddef9a0a6bfe792d3037944aec29154c02bb79d09bd53856797dceb6c599f4103ff7f13dfdb8b2d18477832e5fe21","labelMap":{"dataType":"Map","value":[["c14n0","b1"],["c14n1","b2"],["c14n2","b0"]]},"mandatoryIndexes":[0,1,2,5,6,8,9],"adjSelectiveIndexes":[0,1,5,7,10,16],"presentationHeader":{"0":17,"1":51,"2":119,"3":170},"featureOption":"anonymous_holder_binding","lengthBBSMessages":23}
最后,将上述披露数据用于第 3.2.3 serializeDerivedProofValue节中的算法,我们将得到如下所示的已签名派生 (公开)文档。
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
],
"type": [
"VerifiableCredential",
"Iso18013DriversLicenseCredential"
],
"issuer": {
"id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
"name": "Utopia Department of Motor Vehicles",
"url": "https://dmv.utopia.example/",
"image": "https://dmv.utopia.example/logo.png"
},
"expirationDate": "2028-11-15T12:00:00-06:00",
"credentialSubject": {
"type": "LicensedDriver",
"driversLicense": {
"type": "Iso18013DriversLicense",
"issuing_country": "UA",
"driving_privileges": [
{
"codes": [
{
"code": "D"
}
],
"vehicle_category_code": "D",
"issue_date": "2019-01-01",
"expiry_date": "2027-01-01"
},
{
"codes": [
{
"code": "C"
}
],
"vehicle_category_code": "C",
"issue_date": "2019-01-01",
"expiry_date": "2017-01-01"
}
]
}
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0FhlkDcKGdsFzKEjfZllsLsxl8SWKn-0nJevExyA6i2PlJB4_1ZCrNsz0n0GuX-H_5BqKiO7DD3XeFcriSeF-u_cJYETGLC0biW4hjiYsGAHAaccJW7ppzR6Gld_4uN5OxwDkOTY-f_5FhB07ruoUrzKgInu12QWrJ8Xi4UOdojCbPve40T6ddm6LPIkF-PHC-eJH23gQJKNSmZQBd2-O3Ny7Lh7qtcm8VNdRgCgGY06NqF61nMWD4715f108lQrIUzEU07oKwqQwFAcqXScgyevy5fhQiDy5Rbfw8su0v_dOEWiXLZOGiqpmHu8EidVFY14eiNW4o8q__8xuDos3_JtWsGqcvTWxA_patIwzgn9TpuJmDV8KWTaAx5Zw7jCJB2gC8ZqYhavfNArU1V3-jtUv5oNIwGDsDqhRdurx_7TcQ2HnGuNQnPm43e-04LemF9WH_mys0RfKZV2VWAMvRspcU9SxV_wW8IEID5lvfb4GOl2xpC-z-2ShLJ8LerZaAPvrZSf-1GbcCRTCwi17UyOdHLtIMOGa3lljhstLFuIpg2gdhSvpJBsc6blrZETKCKIFz4mUjb6V9csl_hchrQzSVFvji9S91bUPNLZz4xnPbQE0UAHcG671Pe1u9Gc3On0iy2sLbfw8MP7GL2OZuKP5G2vw5YeWUV3n69UBxkKM84A79ByIswULUDKubnVkViaMNBW2uR9N206xfqzIBu62mBN2OXikhhfOOK81Y6Bsv7B57V1S3sovRJ6vJKelQy3UQDpRpXxrRPAnB05RmQCm2a91JME3zrh4qkKYwnwfEdVXMrqnNF9gOqta3wp6TNaaTOERv9masWALP42BXxEnTkr2pnSZX-4ts8C185NnczY6XAzrMxcEPCS7Hvws8Cyr8ZKGkKdgcxIU4j285Ddl_ZIw3Eu4Lk6fpayaEN-bjU3-3kYzuKkrD-JXHlFmI19OIAji4z2Bi2hcaqHVFz2IHKyDmmOtKwSRQwLlad-lG-tqNRhAqv6mloS0qcTgN7bUeKlfJdRSBPBfqk-bKGQd8KiURv4_RWMTtc2FZCwQJFaPLdvMjMAERMD2N0xxVR01RQgm_Ae1mOdTYGhswvlRETlI-Ld75oKa_55LTA3lErsKRVMArt50JvVOFZ5fc62xZn0ED_38T39uLLRhHeDLl_iGjAAEBAgIAhwABAgUGCAmGAAEFBwoQRBEzd6oX"
}
}
使用凭据绑定假名功能的第一步是让 持有者生成其秘密 prover_nym 值,然后按照 [CFRG-Pseudonym-BBS-Signature] 中的“Commitment”操作 为该值计算带证明的 承诺。该过程的示例 值和输出如下所示。
{
"proverNymHex": "5e2087638f71057ef108f83923189a71cea1f7c4b4ef69afb473c9a7074ddf49"
}
{
"secretProverBlind": "2df3cd3d451b21069b72269f9984df449219c41273b19b1a8487d836fbb8baa1",
"commitmentWithProof": "a80f61f9470cb8ab88644fbef3616eaf5d3b147c4dc1dcad810148a5f2e73186cb3ffa27ea55728a6df470d0c3928be1408b95f5d261cee4d66992ecacf5ca2d6348c33bb7f90c2cef513cdc88be536550e9701d9a466320f49ce097551f8097317c530e2b80710748362b03f5a74280669c00eb29145eb3ec51975d8189fdf2c810d7fadefe36f93b0d2068a494175c"
}
prover_nym 和 secretProverBlind 应由持有者保留并保持秘密。 commitmentWithProof 值应传达给颁发者。
在假名功能选项下添加基础证明的过程始于 颁发者从持有者接收 commitmentWithProof 值,并 为 signer_nym_entropy 生成密码学随机值。
{
"signerNymEntropyHex": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140"
}
此示例将使用 示例 27中所示的相同密钥材料、 示例 50中所示的相同未签名文档, 以及 示例 51中所示的相同 强制指针。这会产生 与 示例 52中所示相同的规范文档、 与 示例 53中所示相同的规范 HMAC 文档, 以及与 示例 54中所示相同的“添加 基础证明转换”。
此示例使用与 示例 55相同的证明配置。 这会产生与 示例 56中相同的规范基础证明。 将其与上述假设结合,会得到与 示例 57相同的基础哈希。
由于 featureOption 等于 "pseudonym",第
3.3.2
基础证明序列化 (bbs-2023)节中的过程将产生
如下所示的输出。这里使用了
[CFRG-Pseudonym-BBS-Signature] 的
签名生成算法。请注意其中包含 signer_nym_entropy 和 featureOption 值,因为这些
值需要传达给持有者。
{
"bbsSignature": "b9389149bab1b5a6032c20781732105a5cbc209592e712e182eec5c055f2072877683dee2949af32290d350ed9e9ffa246f65b8c3f6f199c4d29009d2ce6dff374ed4f22f2f9a7e12dc3c342e8c18107",
"bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
"publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
"mandatoryPointers": [
"/issuer",
"/expirationDate"
],
"signerNymEntropyHex": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140",
"featureOption": "pseudonym"
}
最后,将上述值通过第
3.2.1
serializeBaseProofValue节的算法运行,生成
如下所示的已签名基础文档中使用的 proofValue。
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
],
"type": [
"VerifiableCredential",
"Iso18013DriversLicenseCredential"
],
"issuer": {
"id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
"name": "Utopia Department of Motor Vehicles",
"url": "https://dmv.utopia.example/",
"image": "https://dmv.utopia.example/logo.png"
},
"issuanceDate": "2023-11-15T10:00:00-07:00",
"expirationDate": "2028-11-15T12:00:00-06:00",
"name": "Utopia Driver's License",
"image": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC",
"description": "A license granting driving privileges in Utopia.",
"credentialSubject": {
"type": "LicensedDriver",
"driversLicense": {
"type": "Iso18013DriversLicense",
"document_number": "542426814",
"family_name": "TURNER",
"given_name": "SUSAN",
"portrait": "data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==",
"birth_date": "1998-08-28",
"issue_date": "2023-01-15T10:00:00-07:00",
"expiry_date": "2028-08-27T12:00:00-06:00",
"issuing_country": "UA",
"issuing_authority": "UADMV",
"driving_privileges": [
{
"codes": [
{
"code": "D"
}
],
"vehicle_category_code": "D",
"issue_date": "2019-01-01",
"expiry_date": "2027-01-01"
},
{
"codes": [
{
"code": "C"
}
],
"vehicle_category_code": "C",
"issue_date": "2019-01-01",
"expiry_date": "2017-01-01"
}
],
"un_distinguishing_sign": "UTA",
"aamva_aka_suffix": "1ST",
"sex": 2,
"aamva_family_name_truncation": "N",
"aamva_given_name_truncation": "N"
}
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0IhlhQuTiRSbqxtaYDLCB4FzIQWly8IJWS5xLhgu7FwFXyByh3aD3uKUmvMikNNQ7Z6f-iRvZbjD9vGZxNKQCdLObf83TtTyLy-afhLcPDQujBgQdYQDpbvyXTTZCxjDXNI1e-am9CMB6U_J5S936Tt3PFYUvfjuoRLATYnhM4gPlnZuuuc2k_dfG7y7qkc9wGJUvexPtYYKTvGvo9pXVJbxIrm3i4wkdhUxqKCTIGrnxFuAdZwWi6T3omD5wzZ7bAGbRneEEQSxBmXtvnC6Pr59nPv_v3HrAW9wq_uxYzF_NyaX3GPv0h_FV2T2OSao8C6uoyWiqIj1ggABEiM0RVZneImaq7zN3u_wARIjNEVWZ3iJmqu8zd7v-CZy9pc3N1ZXJvL2V4cGlyYXRpb25EYXRlwlggJVVc9jUYihwzmJBW9RKearS-DnxcxYjEjTCOAlTu0UA"
}
}
如第 A.1.2 派生证明节中所述,我们使用 模拟随机数生成过程来演示 presentationHeader 的使用。此处使用 示例 19中给出的相同 seed 和 presentationHeader。
要创建派生证明,持有者从 包含基础证明的已签名文档开始。我们用于这些测试向量的基础文档来自 上面的 示例 72。 第一步是运行第 3.2.2 parseBaseProofValue节的算法,以 恢复 bbsSignature、bbsHeader、publicKey、hmacKey、 mandatoryPointers、signer_nym_entropy 和 featureOption,如下 所示。
{
"bbsSignature": "b9389149bab1b5a6032c20781732105a5cbc209592e712e182eec5c055f2072877683dee2949af32290d350ed9e9ffa246f65b8c3f6f199c4d29009d2ce6dff374ed4f22f2f9a7e12dc3c342e8c18107",
"bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
"publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
"mandatoryPointers": [
"/issuer",
"/expirationDate"
],
"signerNymEntropy": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140",
"featureOption": "pseudonym"
}
接下来,持有者使用 [CFRG-Pseudonym-BBS-Signature] 中的“验证和最终确定”操作, 以同时验证签名并计算 nym_secret 值。此操作会使用 prover_nym、 signer_nym_entropy 和 secret_prover_blind 等值。
{
"nymSecretHex": "f883d069aec1252f167b0880e8960d72fa2623e11b6967541a457aa5c3cb088"
}
接下来,持有者需要通过指定用于选择性 披露的 JSON 指针,指明希望向验证者披露哪些非强制语句(如果有)。 在这种情况下,持有者披露与 示例 62中给出的相同信息。 这会产生与 示例 63中所示相同的 revealDocument。
运行 § 4.4.3 CreateDisclosureData 会生成与 示例 64中所示相同的 派生组索引信息,以及与 示例 65中所示相同的 调整后强制索引和选择性索引。
在 3.2.3 serializeDerivedProofValue 中,我们基于 中所示的相同 verfifier_id 计算 pseudonym。 § 4.4.3 CreateDisclosureData 的最终输出如下所示。请注意 其中包含 featureOption 和计算得到的 pseudonym 值。
{
"bbsProof":"b394693d54d67937aae0e4175ecf4331200c23470171188ac5513b30d27d9bd2e06173d44e1aca7c743ba30b3f59af0595965bf8256437bce6bef824fe243183af6aa14a1e8224ed7e4eeb16445594df13a46e75d8dfbae0a3e2e1e0871260e68f71de7be4309eb53523a446b8189446b8d5c60892bdd855b5067e0433b46d5b9ffc4dc54b712ff97ec9d7c44cff648929d826bf9e3a7f873c9bcd07c6a3747fc6befceaf892c4d8d38d385c19c399ab342a76c000a3ff9050fa9223e20acfdf4404f43605a24c44622ebcaaf144b161226a6cbe7c08474f9fb80a736be3a818e4e62aa738e701007871859bea36e062324ff3afd8670a5de8b69911fae58aa40e48e29a046c37b9f9cc3868c30482d2339746955c3deaf6f1d4c8cf8be8e503f3ea4715d11e385eb7ed9de6379b7de8436a4e89cf4427d53358b1882e27c6e1e3ba2e81cf10fbc792cf3461a0fdd63f35a151b8c8350505a9b6d612e9adc1dca11b2698a3d0a9f0df6e9bc0ece7aa462afab02d93a87fd5bebb0eee058770c81c5f2fe6eeefcb0a657d9f116b96e2b04b4cc7f4baad4fe784bd9563aea20272138f2dbe94a5e25d30633b5f83eac4b42af25f144bddb631738bf3d54206e8d8b5172c8d52d3c272f799b782c73d480e1289e262ddbb70ab29491cf85a8428c4672437677407524a6dacb53332565dab5d056dbc5451becb123f91d173f6a7c785b7d9f19c43864a785bd941db248322539a097e9ac06244308a3b8df88b5213724cf09715b09e06425448c400680b943ba4711f14a719920b06ec2c6aff908ecf4f5793afd233d270a5ef92131606035517a89e4118dc65dbeb9051f92797036f54f8400910fa56cdd7b87b122e39e41233ea493239fab55c4c836a0a38732a68e6a9f9e11d32b991599e19edbb386f0d364b91e10dd9bf82898f79e90045a0c4987a0cf365d37d8380539a794284841c50c83f2bc3ee9cf7432f44dbfca897ff99feabf224e51137313630c5000d39429d9ea69a2a8237fe3a1857121c14ebb00d57b90db39e2e11bfa37858187d183027c45e317a72e5334681de26788e3176bd48d5761d54c1f2af0a6c3549a0de05b21d0a066c732a540072ae7676b867027b18323e08fcbfaf38ec22aeccd3375bb7b6965d9f6ab3ac4adc2a0700a4bc82fe58afbdd035af48fb85fcd8bf14f81d5ca3f2626be8962cbea13da31ff3cc6c6ebfeeef42f25708af872a14019f83",
"labelMap":{"dataType":"Map","value":[["c14n0","b1"],["c14n1","b2"],["c14n2","b0"]]},
"mandatoryIndexes":[0,1,2,5,6,8,9],
"adjSelectiveIndexes":[0,1,5,7,10,16],
"presentationHeader":{"0":17,"1":51,"2":119,"3":170},
"pseudonym":"838607ff2c8dcb2a0740ef13c2c87418efb57559243232a69daf1e294dd092af833ad4df1e99e0034c737b932916f378",
"featureOption":"pseudonym",
"lengthBBSMessages":23
}
最后,将上述披露数据用于第 3.2.3 serializeDerivedProofValue节中的算法,我们将得到如下所示的已签名派生(公开) 文档。
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
],
"type": [
"VerifiableCredential",
"Iso18013DriversLicenseCredential"
],
"issuer": {
"id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
"name": "Utopia Department of Motor Vehicles",
"url": "https://dmv.utopia.example/",
"image": "https://dmv.utopia.example/logo.png"
},
"expirationDate": "2028-11-15T12:00:00-06:00",
"credentialSubject": {
"type": "LicensedDriver",
"driversLicense": {
"type": "Iso18013DriversLicense",
"issuing_country": "UA",
"driving_privileges": [
{
"codes": [
{
"code": "D"
}
],
"vehicle_category_code": "D",
"issue_date": "2019-01-01",
"expiry_date": "2027-01-01"
},
{
"codes": [
{
"code": "C"
}
],
"vehicle_category_code": "C",
"issue_date": "2019-01-01",
"expiry_date": "2017-01-01"
}
]
}
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0Jh1kDcLOUaT1U1nk3quDkF17PQzEgDCNHAXEYisVROzDSfZvS4GFz1E4aynx0O6MLP1mvBZWWW_glZDe85r74JP4kMYOvaqFKHoIk7X5O6xZEVZTfE6RuddjfuuCj4uHghxJg5o9x3nvkMJ61NSOkRrgYlEa41cYIkr3YVbUGfgQztG1bn_xNxUtxL_l-ydfETP9kiSnYJr-eOn-HPJvNB8ajdH_Gvvzq-JLE2NONOFwZw5mrNCp2wACj_5BQ-pIj4grP30QE9DYFokxEYi68qvFEsWEiamy-fAhHT5-4CnNr46gY5OYqpzjnAQB4cYWb6jbgYjJP86_YZwpd6LaZEfrliqQOSOKaBGw3ufnMOGjDBILSM5dGlVw96vbx1MjPi-jlA_PqRxXRHjhet-2d5jebfehDak6Jz0Qn1TNYsYguJ8bh47ougc8Q-8eSzzRhoP3WPzWhUbjINQUFqbbWEumtwdyhGyaYo9Cp8N9um8Ds56pGKvqwLZOof9W-uw7uBYdwyBxfL-bu78sKZX2fEWuW4rBLTMf0uq1P54S9lWOuogJyE48tvpSl4l0wYztfg-rEtCryXxRL3bYxc4vz1UIG6Ni1FyyNUtPCcveZt4LHPUgOEoniYt27cKspSRz4WoQoxGckN2d0B1JKbay1MzJWXatdBW28VFG-yxI_kdFz9qfHhbfZ8ZxDhkp4W9lB2ySDIlOaCX6awGJEMIo7jfiLUhNyTPCXFbCeBkJUSMQAaAuUO6RxHxSnGZILBuwsav-Qjs9PV5Ov0jPScKXvkhMWBgNVF6ieQRjcZdvrkFH5J5cDb1T4QAkQ-lbN17h7Ei455BIz6kkyOfq1XEyDago4cypo5qn54R0yuZFZnhntuzhvDTZLkeEN2b-CiY956QBFoMSYegzzZdN9g4BTmnlChIQcUMg_K8PunPdDL0Tb_KiX_5n-q_Ik5RE3MTYwxQANOUKdnqaaKoI3_joYVxIcFOuwDVe5DbOeLhG_o3hYGH0YMCfEXjF6cuUzRoHeJniOMXa9SNV2HVTB8q8KbDVJoN4Fsh0KBmxzKlQAcq52drhnAnsYMj4I_L-vOOwirszTN1u3tpZdn2qzrErcKgcApLyC_livvdA1r0j7hfzYvxT4HVyj8mJr6JYsvqE9ox_zzGxuv-7vQvJXCK-HKhQBn4OjAAEBAgIAhwABAgUGCAmGAAEFBwoQRBEzd6pYMIOGB_8sjcsqB0DvE8LIdBjvtXVZJDIypp2vHilN0JKvgzrU3x6Z4ANMc3uTKRbzeBc"
}
}
使用持有者绑定和假名功能的第一步是 让 持有者生成其 holder_secret 和 prover_nym 值,然后 根据 [CFRG-Pseudonym-BBS-Signature] 中的“承诺”操作 为这些值计算 带证明的承诺。该过程的示例 值和输出如下所示。
{
"holderSecretHex": "8fc6cc3f65db4ba5e3ed63fe9d2bd57a9c7df9c7f6bf2b898b308d5493b07eb6"
}
{
"proverNymHex": "5e2087638f71057ef108f83923189a71cea1f7c4b4ef69afb473c9a7074ddf49"
}
{
"secretProverBlind": "0d215067232c77c94a7572eb80794592090da8aff35cca53d2d528d059e70fce",
"commitmentWithProof": "ab72f3e6d7a4185d100ede6ce7dde1c69db9a2128ad11d1b6991a018c340ca2672d7be636f153398be50f44ee434edf14322dd115f7527e770a0f0c41d8aeb2088d004f2703548db6ce15e2505368a1f686f20702aa9ff46bce301330ea0c4c16ef4d8bbf624064a60df3a563142d7b236cad6cf6bcf1f3694d0bf4c2b5ffce55bb26abc05e31f9aaf8b60674fefe02666f89c150c479694f4a89a9088b28a1e6e2cf0c2caaa01810d2e3a52853f3a2a"
}
holder_secret、prover_nym 和 secretProverBlind 需要由持有者 保留 并保持秘密。commitmentWithProof 值需要 传达给颁发者。
在假名功能选项下添加基础证明的过程始于 颁发者从持有者接收 commitmentWithProof 值,并 为 signer_nym_entropy 生成一个密码学随机值。
{
"signerNymEntropyHex": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140"
}
此示例将使用 示例 27中所示的相同密钥材料, 以及 示例 50中所示的相同未签名文档, 以及 示例 51中所示的相同 强制指针。这会产生 与 示例 52中所示相同的规范文档、 与 示例 53中所示相同的规范 HMAC 文档, 以及与 示例 54中所示相同的“添加 基础证明转换”。
此示例使用与 示例 55中相同的证明配置。 这会产生与 示例 56中相同的规范基础证明。 将其与上述假设结合,会得到与 示例 57中相同的基础哈希。
由于 featureOption 等于 "holder_binding_pseudonym",第
3.3.2
基础证明序列化 (bbs-2023)节中的过程将产生
如下所示的输出。这里使用了
[CFRG-Pseudonym-BBS-Signature] 的
签名生成算法。请注意其中包含 signer_nym_entropy 和 featureOption 值,因为这些
值需要传达给持有者。
{
"bbsSignature": "9251f497cb002c19f959a760fa24c5e961df9cb8ff5fbaaef14f2b7f1f41649990c30bd8c1d373e878a5d120123d658a326141275eee7833352d611cc1c05175c9c0f0ddeb0fdec09ad1bfad8796e410",
"bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
"publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
"mandatoryPointers": [
"/issuer",
"/expirationDate"
],
"signerNymEntropyHex": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140",
"featureOption": "holder_binding_pseudonym"
}
最后,将上述值通过第
3.2.1
serializeBaseProofValue节的算法运行,生成
如下所示的已签名基础文档中使用的 proofValue。
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
],
"type": [
"VerifiableCredential",
"Iso18013DriversLicenseCredential"
],
"issuer": {
"id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
"name": "Utopia Department of Motor Vehicles",
"url": "https://dmv.utopia.example/",
"image": "https://dmv.utopia.example/logo.png"
},
"issuanceDate": "2023-11-15T10:00:00-07:00",
"expirationDate": "2028-11-15T12:00:00-06:00",
"name": "Utopia Driver's License",
"image": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC",
"description": "A license granting driving privileges in Utopia.",
"credentialSubject": {
"type": "LicensedDriver",
"driversLicense": {
"type": "Iso18013DriversLicense",
"document_number": "542426814",
"family_name": "TURNER",
"given_name": "SUSAN",
"portrait": "data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==",
"birth_date": "1998-08-28",
"issue_date": "2023-01-15T10:00:00-07:00",
"expiry_date": "2028-08-27T12:00:00-06:00",
"issuing_country": "UA",
"issuing_authority": "UADMV",
"driving_privileges": [
{
"codes": [
{
"code": "D"
}
],
"vehicle_category_code": "D",
"issue_date": "2019-01-01",
"expiry_date": "2027-01-01"
},
{
"codes": [
{
"code": "C"
}
],
"vehicle_category_code": "C",
"issue_date": "2019-01-01",
"expiry_date": "2017-01-01"
}
],
"un_distinguishing_sign": "UTA",
"aamva_aka_suffix": "1ST",
"sex": 2,
"aamva_family_name_truncation": "N",
"aamva_given_name_truncation": "N"
}
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0IhlhQklH0l8sALBn5Wadg-iTF6WHfnLj_X7qu8U8rfx9BZJmQwwvYwdNz6Hil0SASPWWKMmFBJ17ueDM1LWEcwcBRdcnA8N3rD97AmtG_rYeW5BBYQDpbvyXTTZCxjDXNI1e-am9CMB6U_J5S936Tt3PFYUvfjuoRLATYnhM4gPlnZuuuc2k_dfG7y7qkc9wGJUvexPtYYKTvGvo9pXVJbxIrm3i4wkdhUxqKCTIGrnxFuAdZwWi6T3omD5wzZ7bAGbRneEEQSxBmXtvnC6Pr59nPv_v3HrAW9wq_uxYzF_NyaX3GPv0h_FV2T2OSao8C6uoyWiqIj1ggABEiM0RVZneImaq7zN3u_wARIjNEVWZ3iJmqu8zd7v-CZy9pc3N1ZXJvL2V4cGlyYXRpb25EYXRlwlggJVVc9jUYihwzmJBW9RKearS-DnxcxYjEjTCOAlTu0UA"
}
}
如第 A.1.2 派生证明节中所述,我们使用 模拟随机数生成过程,并演示 presentationHeader 的使用。此处使用 示例 19中给出的相同 seed 和 presentationHeader。
要创建派生证明,持有者从一个 包含基础证明的已签名文档开始。我们用于这些测试向量的基础文档来自 上面的 示例 72。 第一步是运行第 3.2.2 parseBaseProofValue节的算法,以 恢复 bbsSignature、bbsHeader、publicKey、hmacKey、 mandatoryPointers、signer_nym_entropy 和 featureOption,如下 所示。
{
"bbsSignature": "9251f497cb002c19f959a760fa24c5e961df9cb8ff5fbaaef14f2b7f1f41649990c30bd8c1d373e878a5d120123d658a326141275eee7833352d611cc1c05175c9c0f0ddeb0fdec09ad1bfad8796e410",
"bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
"publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
"mandatoryPointers": [
"/issuer",
"/expirationDate"
],
"signerNymEntropy": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140",
"featureOption": "holder_binding_pseudonym"
}
接下来,持有者使用 [CFRG-Pseudonym-BBS-Signature] 中的“验证和最终确定”操作, 以同时验证 签名并计算 nym_secret 值。此操作会使用 holder_secret、 prover_nym、 signer_nym_entropy 和 secret_prover_blind 等值。
{"nymSecretHex":"f883d069aec1252f167b0880e8960d72fa2623e11b6967541a457aa5c3cb088"}
接下来,持有者需要指明希望向验证者 披露哪些非强制语句(如果有), 方法是指定用于选择性披露的 JSON 指针。在这种 情况下,持有者披露与 示例 62中给出的相同信息。 这会产生与 示例 63中所示相同的 revealDocument。
运行 § 4.4.3 CreateDisclosureData 会生成与 示例 64中所示相同的 派生组索引信息,以及与 示例 65中所示相同的 调整后强制索引和选择性索引。
在 3.2.3 serializeDerivedProofValue 中,我们基于 中所示的相同 verfifier_id 计算 pseudonym。 3.2.3 serializeDerivedProofValue 的最终输出如下所示。请注意 其中包含 featureOption 和计算得到的 pseudonym 值。
{
"bbsProof":"94752c678297191b42617aca412377d4a5b3d7872779ffea31e0b418f50e95056d923a97e8dc156edc2a3a3a54e7b27cafa26a989fc3e8a8bc7a08b84e706a1863bd06c396b973b1af0da4f6c20ea463e124d2ad97060a25ccc3ff695c71977ba2e83a6468205d9e0bfb756089ad40dededab480eeb13cf00265f49824c5f89e23ac48d07fa3164823741df5c066bdc31a231a7d4fecb75c912adb800b1efe8da3cd26805ffa56775b1c32da34e36e9716a4da909fa6803ca0aa2df2d82f697229ccb210503274d4d61c7386a44e9fb459c020fbcd62c7f437da8ffd5ea7e56d2c4e7d9c3f593b2a964346f24f71bec30a2c3ededa0bd3707e2e06cac2dddb66762135a229dc09b67fa61d690d33be78150bc60f3655ac1063f96d6fe95a260004c7bf9e924cc7439c6426f951d0cee963985557097788d2387b72c9aeb390f9a4fa4b519bc11ca81dfca8a4fd3c77805e1a0ef5c165b16c3cdc564e7a5593f0ddd0560f3514393c1b305d3950c29fbb72cc8b58979843cec768e9a77b14f70704771f877c49fc0d0d4ffbe3f0aaf8e472a83b14e32e46207d5012e79b9bcfc6197c858eb18ad97f589dddb5dc45e9ef65f482d3c07fbcbfef92bf293643539fffc94a8bc98b3b4dd3335bb8b248aa606a751330516f148211d5f2d513e02d45ec5a51add1f878948a673a0349d7cb4417b1f9c16945e1f607bdecf6ca3b96a64fb14ee1fc5dbecf751be23041df32842367285f2b3b02c13512c28c0e7671874699b9ff169e35f91debc796fd487d3e41dcc5f12949558f2705be3e8195d4c93a6c149dcb5f63e62d3ce0bf51034021251b74ed2a1186fd77741ce3bf51f57f19a9d4a9e6315a88024062269a9fec426a73199882113168573da451ca38aeacf28f7eef3892181f0bc511562fba00d035f608c4f85579fc9614618763fa4e6c2210184e12f83e1c22078dd4ca488de41dbf2c146a2e0c47137be7f006c6810f44746a819229349b50ca59a51f7c51bb62cacc1a1cc4a6f089680514d41800da57470ef275f390eb4a08db78789e71bd32bd8929961c9f79d1ca071a2608a393f162c2f644584473f11b41cc35c838f11fbd2adf47051829d378ac9dc151e64bc70cd21b2ea6bca3f77b9c2b35abcebb0ecbf1c09365a8e372a2fce74b97088c9e9505c5c0272a4d6959bec54911a99b6c8a1654395f0cd4e7d38d695ab45875ecc535439dde3fb3d4658d9ff9427d8e36d7bd19ea53fb875c4b138f6ffc06bfd496b1a744a63283ebc0fa34ea828d98",
"labelMap":{"dataType":"Map","value":[["c14n0","b1"],["c14n1","b2"],["c14n2","b0"]]},
"mandatoryIndexes":[0,1,2,5,6,8,9],"adjSelectiveIndexes":[0,1,5,7,10,16],
"presentationHeader":{"0":17,"1":51,"2":119,"3":170},
"pseudonym":"838607ff2c8dcb2a0740ef13c2c87418efb57559243232a69daf1e294dd092af833ad4df1e99e0034c737b932916f378",
"featureOption":"holder_binding_pseudonym",
"lengthBBSMessages":23
}
最后,将上述披露数据用于第 3.2.3 serializeDerivedProofValue节中的算法,我们将得到如下所示的已签名派生(公开) 文档。
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
],
"type": [
"VerifiableCredential",
"Iso18013DriversLicenseCredential"
],
"issuer": {
"id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
"name": "Utopia Department of Motor Vehicles",
"url": "https://dmv.utopia.example/",
"image": "https://dmv.utopia.example/logo.png"
},
"expirationDate": "2028-11-15T12:00:00-06:00",
"credentialSubject": {
"type": "LicensedDriver",
"driversLicense": {
"type": "Iso18013DriversLicense",
"issuing_country": "UA",
"driving_privileges": [
{
"codes": [
{
"code": "D"
}
],
"vehicle_category_code": "D",
"issue_date": "2019-01-01",
"expiry_date": "2027-01-01"
},
{
"codes": [
{
"code": "C"
}
],
"vehicle_category_code": "C",
"issue_date": "2019-01-01",
"expiry_date": "2017-01-01"
}
]
}
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0Jh1kDkJR1LGeClxkbQmF6ykEjd9Sls9eHJ3n_6jHgtBj1DpUFbZI6l-jcFW7cKjo6VOeyfK-iapifw-iovHoIuE5wahhjvQbDlrlzsa8NpPbCDqRj4STSrZcGCiXMw_9pXHGXe6LoOmRoIF2eC_t1YImtQN7e2rSA7rE88AJl9JgkxfieI6xI0H-jFkgjdB31wGa9wxojGn1P7LdckSrbgAse_o2jzSaAX_pWd1scMto0426XFqTakJ-mgDygqi3y2C9pcinMshBQMnTU1hxzhqROn7RZwCD7zWLH9Dfaj_1ep-VtLE59nD9ZOyqWQ0byT3G-wwosPt7aC9Nwfi4GysLd22Z2ITWiKdwJtn-mHWkNM754FQvGDzZVrBBj-W1v6VomAATHv56STMdDnGQm-VHQzuljmFVXCXeI0jh7csmus5D5pPpLUZvBHKgd_Kik_Tx3gF4aDvXBZbFsPNxWTnpVk_Dd0FYPNRQ5PBswXTlQwp-7csyLWJeYQ87HaOmnexT3BwR3H4d8SfwNDU_74_Cq-ORyqDsU4y5GIH1QEuebm8_GGXyFjrGK2X9Ynd213EXp72X0gtPAf7y_75K_KTZDU5__yUqLyYs7TdMzW7iySKpganUTMFFvFIIR1fLVE-AtRexaUa3R-HiUimc6A0nXy0QXsfnBaUXh9ge97PbKO5amT7FO4fxdvs91G-IwQd8yhCNnKF8rOwLBNRLCjA52cYdGmbn_Fp41-R3rx5b9SH0-QdzF8SlJVY8nBb4-gZXUyTpsFJ3LX2PmLTzgv1EDQCElG3TtKhGG_Xd0HOO_UfV_GanUqeYxWogCQGImmp_sQmpzGZiCETFoVz2kUco4rqzyj37vOJIYHwvFEVYvugDQNfYIxPhVefyWFGGHY_pObCIQGE4S-D4cIgeN1MpIjeQdvywUai4MRxN75_AGxoEPRHRqgZIpNJtQylmlH3xRu2LKzBocxKbwiWgFFNQYANpXRw7ydfOQ60oI23h4nnG9Mr2JKZYcn3nRygcaJgijk_FiwvZEWERz8RtBzDXIOPEfvSrfRwUYKdN4rJ3BUeZLxwzSGy6mvKP3e5wrNavOuw7L8cCTZajjcqL850uXCIyelQXFwCcqTWlZvsVJEambbIoWVDlfDNTn041pWrRYdezFNUOd3j-z1GWNn_lCfY42170Z6lP7h1xLE49v_Aa_1Jaxp0SmMoPrwPo06oKNmKMAAQECAgCHAAECBQYICYYAAQUHChBEETN3qlgwg4YH_yyNyyoHQO8Twsh0GO-1dVkkMjKmna8eKU3Qkq-DOtTfHpngA0xze5MpFvN4Fw"
}
}
本节为非规范性内容。
本规范的工作得到了 Rebooting the Web of Trust 社区的支持,该社区由 Christopher Allen、Shannon Appelcline、Kiara Robles、 Brian Weller、Betty Dhamers、Kaliya Young、Manu Sporny、Drummond Reed、Joe Andrieu、Heather Vescent、Kim Hamilton Duffy、Samantha Chase、Andrew Hughes、 Erica Connell、Shigeya Suzuki 和 Zaïda Rivai 推动。由 Phil Windley、Kaliya Young、Doc Searls 和 Heidi Nobantu Saul 推动的 Internet Identity Workshop 参与者也通过多次 旨在介绍、讨论并改进本 规范的工作会议,支持了这项工作的完善。
工作组还感谢我们的主席 Brent Zundel、前主席 Kristina Yasuda,以及我们的 W3C 工作人员联系人 Ivan Herman,感谢他们在整个 W3C 标准化 过程中以专业的管理和持续的指导带领本工作组。
本规范的部分工作得到了美国 国土安全部科学与技术局的资助,合同编号为 70RSAT20T00000003、70RSAT20T00000029、70RSAT20T00000033、 70RSAT21T00000016、70RSAT23T00000005、70RSAT20T00000010/P00001、 70RSAT20T00000029、70RSAT21T00000016/P00001、70RSAT23T00000005、 70RSAT23C00000030、70RSAT23R00000006、70RSAT24T00000011,以及国家科学基金会 通过 NSF 22-572 提供的资助。本规范的内容不一定 反映美国政府的立场或政策,也不应据此推断 存在任何官方认可。
工作组感谢以下人员审阅 本规范并提供反馈(按字母顺序排列):
Will Abramson, Mahmoud Alkhraishi, Christopher Allen, Joe Andrieu, Bohdan Andriyiv, Anthony, George Aristy, Hadley Beeman, Greg Bernstein, Bob420, Sarven Capadisli, Melvin Carvalho, David Chadwick, Matt Collier, Gabe Cohen, Sebastian Crane, Kyle Den Hartog, Veikko Eeva, Eric Elliott, Raphael Flechtner, Julien Fraichot, Benjamin Goering, Kim Hamilton Duffy, Joseph Heenan, Helge, Ivan Herman, Michael Herman, Anil John, Andrew Jones, Michael B. Jones, Rieks Joosten, Gregory K, Gregg Kellogg, Filip Kolarik, David I. Lehn, Charles E. Lehner, Christine Lemmer-Webber, Eric Lim, Dave Longley, Tobias Looker, Jer Miller, nightpool, Luis Osta, Nate Otto, George J. Padayatti, Addison Phillips, Mike Prorock, Brian Richter, Anders Rundgren, Eugeniu Rusu, Markus Sabadello, silverpill, Wesley Smith, Manu Sporny, Patrick St-Louis, Orie Steele, Henry Story, Oliver Terbu, Ted Thibodeau Jr, John Toohey, Bert Van Nuffelen, Mike Varley, Snorre Lothar von Gohren Edwin, Jeffrey Yasskin, Kristina Yasuda, Benjamin Young, Dmitri Zagidulin, 以及 Brent Zundel。