可验证凭证条形码 v1.0

在光学条形码中嵌入可验证凭证

W3C 工作草案

关于本文档的更多详细信息
本版本:
https://www.w3.org/TR/2026/WD-vc-barcodes-1.0-20260623/
最新发布版本:
https://www.w3.org/TR/vc-barcodes-1.0/
最新编辑草案:
https://w3c.github.io/vc-barcodes/
历史:
https://www.w3.org/standards/history/vc-barcodes-1.0/
提交历史
编辑:
Wesley Smith (Digital Bazaar)
Elaine Wooton (受邀专家)
Manu Sporny (Digital Bazaar)
作者:
Manu Sporny (Digital Bazaar)
Dave Longley (Digital Bazaar)
Wesley Smith (Digital Bazaar)
反馈:
GitHub w3c/vc-barcodes (拉取请求新议题未解决议题)
相关规范
可验证凭证数据模型 v2.0
可验证凭证数据完整性 v1.1
椭圆曲线数字签名算法 密码套件 v1.1
链接数据的紧凑二进制对象 表示 v1.0

摘要

本规范描述了一种使用可验证凭证 [VC-DATA-MODEL-2.0] 保护光学条形码的机制, 例如驾驶证上的条形码(PDF417)和旅行证件上的机器可读区(MRZ)。 可验证凭证 表示足够紧凑,可以容纳在 150 字节以内, 因此可与使用标准印刷工艺印刷在实体卡上的 传统二维条形码集成。

本文档状态

本节描述的是本文档 在发布时的状态。当前 W3C 出版物列表以及本技术报告的最新修订版可在 W3C 标准和草案 索引中找到。

本文档由 可验证凭证工作组 作为工作草案发布,并使用 推荐标准 轨道

作为 工作草案发布,并不表示 W3C 及其成员认可。

这是一份草案文档,可能随时被其他文档 更新、取代或废弃。除作为正在进行中的工作外, 不宜引用本文档。

本文档由一个根据 W3C 专利 政策 运作的小组制作。 W3C 维护一个 任何专利披露的公开列表, 这些披露与该小组的交付成果有关;该页面还包括 披露专利的说明。任何实际知晓某项专利, 并认为该专利包含 必要权利要求 的个人,必须依照 W3C 专利政策第 6 节 披露相关信息。

本文档受 2025年8月18日 W3C 流程文档约束。

1. 引言

实体凭证,例如驾驶证、护照和旅行 凭证,通常包含机器可读数据,可用于快速读取 文档中的信息。这些信息以诸如 PDF417 [ISO15438-2015]、 机器可读区(MRZ)[ICAO9303-3], 以及 其他格式化为一维或二维“条”的光学可扫描代码等格式编码; 因此产生了“条形码”这一术语。这些信息通常 未受到防篡改保护,而现成的条形码生成和 扫描库意味着任何人生成这些 条形码都相当容易。

因此,对于这些条形码的签发者而言,保护 条形码中包含的信息以及 生成该条形码的实体是有用的。

可验证凭证数据模型 v2.0 规范为表达凭证信息提供了一个全球标准, 例如驾驶证或旅行证件中的信息。可验证凭证数据完整性 1.0 规范为保护凭证信息提供了一个 全球标准。这两项规范结合后,提供了一种防止凭证被篡改、 表达凭证作者身份,并以隐私保护方式提供凭证当前状态的 手段。然而,这些数据格式通常 过大,无法在光学条形码中表达。

链接数据的紧凑二进制对象 表示 v1.0 规范提供了一种压缩受保护 可验证 凭证的方法,使其达到可以 将信息表达为光学条形码,或嵌入光学 条形码中的程度。

本规范描述了一种保护光学条形码的机制, 例如驾驶证上的条形码(PDF417)和旅行证件上的机器可读区(MRZ), 其方法是使用可验证凭证 [VC-DATA-MODEL-2.0] 来表达 有关条形码本身或条形码主体的信息。 接着,该可验证凭证使用数据完整性 [VC-DATA-INTEGRITY] 进行保护,然后 使用 CBOR-LD [CBOR-LD] 进行压缩。

可验证凭证可通过两种主要机制 用于保护条形码:

这两个用例都为可验证凭证保护的数据实现了真实性、 完整性和防篡改性。此外,对于需要这些能力的用例, 这些可验证凭证可以按每个条形码为单位 被撤销或暂停。

1.1 入门示例

以下各节提供了一些入门示例,说明 本规范可如何用于通过可验证 凭证,用数字签名增强现有实体凭证。

1.1.1 驾驶证

本节提供一个示例,说明如何利用本规范中的技术 来保护使用 PDF417 条形码的驾驶证上的 光学条形码。我们从一个示例驾驶证开始:

由乌托邦州签发的驾驶证正面图片,其中包含驾驶证主体个人的照片以及其属性,例如姓名、地址、身高、体重、眼睛颜色和驾驶权限。
1 由乌托邦州签发的驾驶证正面。

驾驶证背面包含一个 PDF417 条形码:

由乌托邦州签发的驾驶证背面图片,其中包含使用规则以及一个 PDF417 条形码,该条形码编码了卡片正面显示的大部分信息。
2 由乌托邦州签发的驾驶证背面。

PDF417 数据包含使用本规范中描述的算法 保护的信息。也就是说,PDF417 条形码包含一个 如下形式的可验证 凭证

示例 1:嵌入 PDF417 条形码中的可验证凭证
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/vdl/v2",
    "https://w3id.org/vdl/utopia/v1"
  ],
  "type": [
    "VerifiableCredential",
    "OpticalBarcodeCredential"
  ],
  // 下面的 issuer 值在上方的 'utopia/v1' 上下文中定义为 URL
  "issuer": "did:web:dmv.utopia.example",
  "credentialStatus": {
    "type": "TerseBitstringStatusListEntry",
    "terseStatusListBaseUrl": "https://dmv.utopia.gov/statuses/12345/status-lists"
    "terseStatusListIndex": 123567890
  },
  "credentialSubject": {
    "type": "AamvaDriversLicenseScannableInformation",
    "protectedComponentIndex": "uP_BA"
  },
  "proof": {
    "type": "DataIntegrity",
    "cryptosuite": "ecdsa-xi-2023",
    // 下面的公钥在上方的 'utopia/v1' 上下文中定义为 URL
    "verificationMethod": "did:web:dmv.utopia.example#key-1",
    "proofPurpose": "assertionMethod",
    "proofValue": "z4peo48uwK2EF4Fta8P...HzQMDYJ34r9gL"
  }
}

随后,上述可验证 凭证使用 [CBOR-LD] 压缩为以下输出(采用 CBOR 诊断表示法):

示例 2:CBOR-LD 压缩的可验证凭证(145 字节)
1281{
  1 => [ 32768, 32769, 32770],                           // @context
  155 => [ 116, 164 ],                                   // type
  192 => 174,                                            // issuer
  186 => { 154 => 166, 206 => 178, 208 => 1234567890 },  // credentialStatus
  188 => { 154 => 172, 180 => h'753FF040 },              // credentialSubject
  194 => {                                               // proof
    154 => 108,                                          // type
    214 => 4,                                            // cryptosuite
    224 => 230                                           // verificationMethod
    228 => 176,                                          // proofPurpose
    210 => Uint8Array(65) [ ... ],                       // proofValue
  }
}

1.1.2 就业许可

本节提供一个示例,说明如何利用本规范中的技术 来保护就业许可文件上的机器可读区;该文件在卡片背面 使用机器可读区(MRZ)。我们从一个示例就业许可文件开始:

由乌托邦州签发的就业许可文件正面图片,其中包含该文件主体个人的照片以及其属性,例如姓名、地址、身高、体重、眼睛颜色和就业权限。
3 由乌托邦州签发的就业许可文件正面。

就业许可文件背面包含一个机器可读区(MRZ), 其中的信息设计为通过光学字符识别来读取:

由乌托邦州签发的就业许可文件背面图片,其中包含使用规则以及机器可读区数据,该数据编码了卡片正面显示的大部分信息。
4 由乌托邦州签发的就业许可文件背面。

MRZ 数据包含使用本规范中描述的算法 保护的信息。也就是说,卡片正面的二维码包含一个 如下形式的可验证 凭证,该凭证保护 卡片背面的信息。

示例 3:作为卡片正面二维码表达的 可验证凭证
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/citizenship/v2",
    "https://w3id.org/citizenship/utopia/v1"
  ],
  "type": [
    "VerifiableCredential",
    "OpticalBarcodeCredential"
  ],
  // 下面的值在上方的 'utopia/v1' 上下文中定义为 URL
  "issuer": "did:web:immigration.utopia.example",
  "credentialSubject": {
    "type": "MachineReadableZone",
  },
  "proof": {
    "type": "DataIntegrity",
    "cryptosuite": "ecdsa-xi-2023",
    // 下面的值在上方的 'utopia/v1' 上下文中定义为 URL
    "verificationMethod": "did:web:immigration.utopia.example#key-4"
    "proofPurpose": "assertionMethod",
    "proofValue": "z4peo48uwK2EF4Fta8P...HzQMDYJ34r9gL"
  }
}
: credentialStatus 是可选的

读者可能会注意到,上述凭证不包含可选的 credentialStatus 属性。并非每个光学条形码凭证签发者都 有撤销光学条形码凭证的需求。

随后,上述可验证 凭证使用 [CBOR-LD] 压缩为以下输出(采用 CBOR 诊断表示法):

示例 4:CBOR-LD 压缩的可验证凭证(120 字节)
{
  1 => [ 32768, 32769, 32770],           // @context
  155 => [ 116, 176 ],                   // type
  208 => 194,                          // issuer
  204 => { 154 => 192 },                 // credentialSubject
  210 => {                               // proof
    154 => 108,                          // type
    226 => 4,                        // cryptosuite
    236 => 242                         // verificationMethod
    240 => 196,                          // proofPurpose
    210 => Uint8Array(65) [ ... ],       // proofValue
  }
}

1.1.3 出生证明

本节提供一个示例,说明如何利用本规范中的技术 将出生证明作为可验证 凭证进行保护,然后 将其表达为打印纸质文档上的二维码:

出生证明正面的图片,其中包含新生儿姓名、父母姓名、医院信息、在场人员以及负责登记人员等信息。
5 由乌托邦州一家医院签发的出生证明正面。

二维码编码以下可验证 凭证。有关 编码的详细信息可在下方单独的标签页中查看:

示例 5:表示简短格式 出生证明的可验证凭证
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/vital-records/v1rc1"
  ],
  "type": [
    "VerifiableCredential",
    "BirthCertificateCredential"
  ],
  "issuer": "https://hospital.example/issuer",
  "validFrom": "2023-09-30T11:30:00Z",
  "credentialSubject": {
    "type": "BirthCertificate",
    "certificationDate": "2023-09-30T13:44:52Z",
    "newborn": {
      "type": "Newborn",
      "name": "Tim Doe",
      "gender": "Male",
      "birthDate": "2023-10-05T14:29:00Z",
      "birthPlace": {
        "type": "PostalAddress",
        "streetAddress": "123 Hospital Rd",
        "addressLocality": "Utopia Town",
        "addressRegion": "Utopolis",
        "postalCode": "12345",
        "addressCountry": "Utopia"
      },
      "parent": [{
        "type": "Mother",
        "name": "Jane Doe",
        "namePriorToMarriage": "Jane Smith"
      }, {
        "type": "Father",
        "name": "John Doe"
      }]
    }
  }
}
application/vc+cborld

d9cb1d8201a60182782468747470733a2f2f7777772e77332e6f72672f6e732f63726564656e7469616c732f7632782468747470733a2f2f773369642e6f72672f766974616c2d7265636f7264732f7631726331189d82187618a4190130a3189c18a218cc74323032332d30392d33305431333a34343a35325a190104a618966754696d20446f65189c18ae18bc74323032332d31302d30355431343a32393a30305a18c4a6189c18b21901446655746f7069611901466b55746f70696120546f776e1901486855746f706f6c697319014a65313233343519014c6f31323320486f73706974616c20526418e2644d616c6519010b82a31896684a616e6520446f65189c18ac1901026a4a616e6520536d697468a21896684a6f686e20446f65189c18aa190134820277686f73706974616c2e6578616d706c652f697373756572190136a6189c186c1901501a6a3abdd71901526f65636473612d726466632d3230313919015c19016219015e58417ae780156acdf39b8a76dd9dfdcc7d9cf32636e91579f894a2f1fc8cafc9fd0fb5a72660ed343f1ca88542eafd94e542c509080ab479da5e303fb74dcdd20656741901608219040158238024035ecd0dd569e4db7f6feefdb0249d9156db32899632ae707466310043e3cb954b1901401a651806b8

JSON-LD 大小:1037 字节
CBOR-LD 大小:484 字节
压缩率:53%

application/vc
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/vital-records/v1rc1"
  ],
  "type": [
    "VerifiableCredential",
    "BirthCertificateCredential"
  ],
  "issuer": "https://hospital.example/issuer",
  "validFrom": "2023-09-30T11:30:00Z",
  "credentialSubject": {
    "type": "BirthCertificate",
    "certificationDate": "2023-09-30T13:44:52Z",
    "newborn": {
      "type": "Newborn",
      "name": "Tim Doe",
      "gender": "Male",
      "birthDate": "2023-10-05T14:29:00Z",
      "birthPlace": {
        "type": "PostalAddress",
        "streetAddress": "123 Hospital Rd",
        "addressLocality": "Utopia Town",
        "addressRegion": "Utopolis",
        "postalCode": "12345",
        "addressCountry": "Utopia"
      },
      "parent": [
        {
          "type": "Mother",
          "name": "Jane Doe",
          "namePriorToMarriage": "Jane Smith"
        },
        {
          "type": "Father",
          "name": "John Doe"
        }
      ]
    }
  },
  "proof": {
    "type": "DataIntegrityProof",
    "created": "2026-06-23T17:09:43Z",
    "verificationMethod": "did:key:zDnaep3M6F9WVbtR4JaDCpS84JphmppHXBh8NNLWQYJDvpa8i",
    "cryptosuite": "ecdsa-rdfc-2019",
    "proofPurpose": "assertionMethod",
    "proofValue": "z5dT3pjsBWEXyquJXoNX1atkXDisQaLJMcrkJPNYMSMqSMocrqhHkK9nRiztfTDSANzg5iEi6YurddLfD
nnStdeTm"
  }
}
            

CBOR-LD 诊断模式
51997(
  [
    1,
    {
      1: [
        "https://www.w3.org/ns/credentials/v2",
        "https://w3id.org/vital-records/v1rc1"
      ],
      157: [
        118,
        164
      ],
      304: {
        156: 162,
        204: "2023-09-30T13:44:52Z",
        260: {
          150: "Tim Doe",
          156: 174,
          188: "2023-10-05T14:29:00Z",
          196: {
            156: 178,
            324: "Utopia",
            326: "Utopia Town",
            328: "Utopolis",
            330: "12345",
            332: "123 Hospital Rd"
          },
          226: "Male",
          267: [
            {
              150: "Jane Doe",
              156: 172,
              258: "Jane Smith"
            },
            {
              150: "John Doe",
              156: 170
            }
          ]
        }
      },
      308: [
        2,
        "hospital.example/issuer"
      ],
      310: {
        156: 108,
        336: 1782234583,
        338: "ecdsa-rdfc-2019",
        348: 354,
        350: h'7ae780156acdf39b8a76dd9dfdcc7d9cf32636e91579f894a2f1fc8cafc9fd0fb5a72660ed343f1ca8854
2eafd94e542c509080ab479da5e303fb74dcdd2065674',
        352: [
          1025,
          h'8024035ecd0dd569e4db7f6feefdb0249d9156db32899632ae707466310043e3cb954b'
        ]
      },
      320: 1696073400
    }
  ])}
            
image/png

可验证凭证二维码
二维码版本:15
纠错级别:低

二维码内容(文本)
VC1-R0OR*W3H90Q80L8FA9DIWENPEJ/5S4F03F53F7*5$KE$:5CPEXPC  C1$CBWEAECCPEI.EL8FA9DIWENPEJ/553FPED7*5$K
E006-EDAECOX5Z C04EKVC006DB6DOC1534KG$-EOXKY60$RK0XJ6MK5%PNF6QF63W5CA79L6/SAJL6:Q66G7KG6B73KQ0*43$2D
YEDP34W3E053I53W531VE8466L6$963W5HX6-963G7PA7646OHBW%O053M53B735T86 A/3EMEDB73R+86 A/3EMED-3454EF-DD
70O8DHWES9EXVDZOEF70UZCQF60R6B73$T9*96%K6379WQE-EDAEC*34JTC-RS9Z9TVDB73LK1$RKT0J6I91/DP34W3E053G53B7
3XD06I91/D+34J$DAWE6MKT0JKI949DP34W3E053E53B73WS61E059DWQE-EDAEC.%5$9FQ$DTVDW:5ZQE%$E4JE+60+:K0XJ/TD
L70CF37J7U8RN70W3EJPCHQEOX57VC9OCNF61A6B73.SB*70B73W-BMC88VI17O7KH*PAHK7DEN BQ$HAPSE/EE451E7EPCRGYJZ
V5TPNQ62SAJO2AUSG2DUDIO 2IOER26ON44.4M:-QVC0%ZBY+M/ACB7319CE73T70/L4*O4E:BVX1IHDVXRY6E93WDS4 GI:VRWH
HEI6X9EG-CM10+ZSE*IB73U485ZCA%0
            

JSON-LD 诊断模式
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/vital-records/v1rc1"
  ],
  "type": [
    "VerifiableCredential",
    "BirthCertificateCredential"
  ],
  "issuer": "https://hospital.example/issuer",
  "validFrom": "2023-09-30T11:30:00Z",
  "credentialSubject": {
    "type": "BirthCertificate",
    "certificationDate": "2023-09-30T13:44:52Z",
    "newborn": {
      "type": "Newborn",
      "name": "Tim Doe",
      "gender": "Male",
      "birthDate": "2023-10-05T14:29:00Z",
      "birthPlace": {
        "type": "PostalAddress",
        "streetAddress": "123 Hospital Rd",
        "addressLocality": "Utopia Town",
        "addressRegion": "Utopolis",
        "postalCode": "12345",
        "addressCountry": "Utopia"
      },
      "parent": [
        {
          "type": "Mother",
          "name": "Jane Doe",
          "namePriorToMarriage": "Jane Smith"
        },
        {
          "type": "Father",
          "name": "John Doe"
        }
      ]
    }
  },
  "proof": {
    "type": "DataIntegrityProof",
    "created": "2026-06-23T17:09:43Z",
    "verificationMethod": "did:key:zDnaep3M6F9WVbtR4JaDCpS84JphmppHXBh8NNLWQYJDvpa8i",
    "cryptosuite": "ecdsa-rdfc-2019",
    "proofPurpose": "assertionMethod",
    "proofValue": "z3xU4Hqfs6EKrrwiRyNP6Pwxfo8yHfyHA5SFt4Dn9cSfQVcqDsCzSeD8CSDs2XqU7Y4qB6zkWrJqt9t2P
s13mzgoA"
  }
}}
            

1.2 设计目标

以下是本规范中技术的设计目标:

1.3 术语

本文档通篇使用的术语定义在 可验证凭证数据模型 v2.0 规范的 术语一节中,以及 可验证凭证数据完整性 1.0 规范中。

Unicode 码点 顺序
这指的是使用 Unicode 码点 排序规则来确定两个 Unicode 字符串(AB) 的顺序, 如 [XPATH-FUNCTIONS] 中所定义,它定义了一种按码点比较 字符串全序。 请注意,对于 UTF-8 编码的字符串,比较字节序列会得到与码点 顺序相同的结果。

1.4 一致性

除标记为非规范性的章节外,本规范中的所有编写指南、图表、示例和注释 均为非规范性内容。本规范中的其他所有内容均为规范性内容。

本文档中的关键词 MAYMUSTRECOMMENDEDREQUIREDSHOULD 应按 BCP 14 [RFC2119] [RFC8174] 中的描述解释,但仅当它们像这里所示那样全部 大写出现时才如此。

一致性 文档是数据模型的任何具体表达, 且该表达符合本规范中的规范性陈述。具体而言, 必须执行本文档 2. 数据模型3. 算法 各节中的所有相关规范性陈述。

一致性处理器是以软件和/或硬件实现的任何算法, 它生成或消费 一致性文档。一致性处理器在消费 不符合一致性的文档时MUST产生错误。

本文档包含 JSON 和 JSON-LD 数据示例。其中一些示例 是无效 JSON,因为它们包含诸如内联注释(//) 用于解释某些部分,以及省略号(...)用于表示省略 与示例无关的信息。如果实现者希望将这些示例视为有效 JSON 或 JSON-LD, 则需要移除这些部分。

2. 数据模型

以下各节概述了本规范使用的数据模型, 用于表达保护光学印刷信息的可验证凭证, 例如旅行证件上的条形码和机器可读区。

2.1 OpticalBarcodeCredential

OpticalBarcodeCredential 用于以一种提供 1)作者身份信息、2)防篡改性, 以及 3)可选的撤销和暂停状态的方式,保护光学 条形码的内容。换句话说, 该凭证可以告诉你是谁签发了该光学条形码, 光学条形码自首次签发以来是否被篡改过,以及 该光学条形码的签发者是否仍然 保证 该文档仍然有效。这些特性为实体文档提供了重要的 反欺诈保护。

OpticalBarcodeCredentialcredentialSubject 要么是 AamvaDriversLicenseScannableInformation 类型,要么是 MachineReadableZoneAamvaDriversLicenseScannableInformation 表示 该可验证凭证 保护实体 文档上的 PDF417 条形码,以及 可验证凭证 中表达的信息。 MachineReadableZone 表示 该可验证凭证 保护实体文档上的机器可读区, 以及 可验证凭证 中表达的信息。

如果 OpticalBarcodeCredential 的类型为 AamvaDriversLicenseScannableInformation, 则有一个REQUIRED的附加字段 protectedComponentIndex, 其中包含 PDF417 中哪些字段 被数字签名的信息。protectedComponentIndex MUST 是一个三字节/24 位值, 以 multibase-base64url 编码后在 JSON-LD 凭证中总计为 5 个字符。符合 AAMVA 的驾驶证 PDF417 [aamva-dl-id-card-design-standard] 中有 22 个 必填字段,protectedComponentIndex 值的前 22 位对应这些字段。每个 AAMVA 必填 字段都以一个三字符元素 ID 开头(例如,DBA 表示文档有效期)。为了在 protectedComponentIndex 值中的位与这些字段之间构造 映射,请按 Unicode 码点顺序对这些 元素 ID 排序。然后,如果 protectedComponentIndex 中位置 i 的位为 1, 则已排序元素 ID 中位置 i 的 AAMVA 必填字段由数字 签名保护。protectedComponentIndex 中最后两位MUST0。更多 信息请参见第 3.2.4.4 创建 opticalDataBytes

为了实现尽可能高的压缩率,RECOMMENDED issuerverificationMethod 字段使用来自 JSON-LD Context 的术语, 这样由于 CBOR-LD 的语义 压缩机制,它们可以被压缩到几个字节。

下面提供了一个使用本节中指定属性的 光学条形码凭证示例:

示例 6:使用 TerseBitstringStatusListEntry 的 OpticalBarcodeCredential
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/vdl/v2",
    "https://w3id.org/vdl/utopia/v1"
  ],
  "type": [
    "VerifiableCredential",
    "OpticalBarcodeCredential"
  ],
  "issuer": "did:web:dmv.utopia.example",
  "credentialStatus": {
    "type": "TerseBitstringStatusListEntry",
    "terseStatusListBaseUrl": "dmv.utopia.gov/statuses/12345/status-lists"
    "terseStatusListIndex": 123567890
  },
  "credentialSubject": {
    "type": "AamvaDriversLicenseScannableInformation",
    "protectedComponentIndex": "uP_BA"
  }
}

2.2 TerseBitstringStatusListEntry

TerseBitstringStatusListEntryBitstringStatusListEntry 的一种紧凑表示,如 Bitstring Status List v1.0 规范中所定义。

TerseBitstringStatusListEntry 类型的对象MUST具有两个 附加属性:

要处理 TerseBitstringStatusListEntry,请应用第 3.2.3 转换状态列表条目中的算法,将其转换为 BitstringStatusListEntry, 然后按 Bitstring Status List v1.0 中所述进行处理。

实现者需要为单个状态列表的长度设置一个值 listLength。对于 32 位 terseStatusListIndex, 这会得到状态列表数量 listCount = 2^32 / listLength。 从 TerseBitstringStatusListEntry 转换为 BitstringStatusListEntry 时需要 listLength。 注意到 listLength 的某些值会损害这些状态列表的隐私保护属性, 实现MUST使用 listLength = 2^26 和 listCount = 2^6。

2.3 与条形码之间的编码和解码

虽然本规范中的凭证使用 CBOR-LD 以二进制格式高效编码可验证凭证, 但二进制数据通常很难低效地或不兼容地直接转换为标准条形码 图像格式。为此,我们在此为实现提供要求。

RECOMMENDED 实现者在将 CBOR-LD 编码的 AamvaDriversLicenseScannableInformation 凭证编码进 PDF417 之前,先将其字符编码为 base64url。可以在 base 编码的 VCB 数据前添加 multibase 标头。PDF417 字段标头规范预计会指明 multibase 标头是否存在。

REQUIRED 实现者在将 CBOR-LD 编码的 MachineReadableZone 凭证 编码进二维码之前,将其重新编码为带有前置字符串 'VC1-' 的 base45-multibase。

3. 算法

以下一节描述了用于在实体介质上添加和验证数字 证明的算法,这些证明保护光学信息,例如驾驶证和旅行证件上的 条形码和机器可读区。

3.1 通用算法

本节包含对编码和解码 可验证 凭证通用的算法。

3.1.1 CBOR-LD 压缩表

本规范要求在编码和解码 可验证 凭证时, 向 CBOR-LD 处理器提供一个特定于应用的压缩表。针对各种 签发者的所有上下文 URL 的注册表以 逗号分隔值文件形式提供,并且可通过对该文件的 变更请求以仅追加和先到先得的方式更新和修改。 实现SHOULD每月 检索并使用最新文件,以确保压缩和解压缩支持最新值。

3.1.2 将 VC 编码为二维码

以下算法指定了如何将可验证 凭证编码为 可在二维码中表达的文本字符串。必需输入为一个 可验证 凭证映射 inputDocument),以及一组选项 (映射 options)。输出是一个已编码的可验证 凭证字符串)或错误。 每当该算法编码字符串时,它MUST使用 UTF-8 编码。

  1. typeTableoptions.typeTable 的值。
  2. registryEntryIdoptions.registryEntryId 的值。
  3. cborldDocument JSON-LD 到 CBOR-LD 编码算法的结果,并将 inputDocumenttypeTableregistryEntryId 作为输入传入。如果发生编码错误, 则MUST引发错误。
  4. base45ValueBase 编码算法的结果,并将 cborldDocument 作为 bytes、整数 45 作为 targetBase,以及 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./: 作为 baseAlphabet 传入。
  5. qrCodeText 为连接以下值的结果: VC1-R(base45 的 Multibase 前缀),以及 base45Value
  6. 返回 qrCodeText 作为已编码的可验证 凭证,然后可以将其 作为文本提供给任何二维码库,以编码为二维码图像。

3.1.3 将二维码解码为 VC

以下算法指定了如何解码已编码进二维码的可验证 凭证。 必需输入为文本字符串(字符串 inputDocument),以及一组选项(映射 options)。输出是一个 可验证 凭证映射)或错误。每当该算法 编码 字符串时,它MUST使用 UTF-8 编码。

  1. 确保 inputDocument 以文本 VC1-R 开头。如果不是, 则MUST引发 错误。
  2. base45Value 为移除前五个字符 (VC1-R) 后的 inputDocument
  3. cborldDocumentBase 解码算法的结果,并将 base45Value 作为 sourceEncoding、整数 45 作为 sourceBase,以及 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./: 作为 baseAlphabet 传入。
  4. jsonldDocument CBOR-LD 到 JSON-LD 解码算法的结果,并将 cborldDocument 作为 输入传入。如果发生解码错误,则MUST引发错误。
  5. 返回 jsonldDocument 作为已解码的可验证 凭证

3.2 OpticalBarcodeCredential 算法

本节包含特定于编码和解码 typeOpticalBarcodeCredential可验证凭证 的算法。

3.2.1 编码 OpticalBarcodeCredential

  1. opticalData 设置为待保护的光学条形码中的数据。
  2. statusListEntryVerbose 设置为签发者 希望添加到 OpticalBarcodeCredential 中的 BitstringStatusListCredential (如 Bitstring Status List v1.0 规范中所定义)。
  3. statusListEntryTerse 为空映射。将 statusListEntryTerse.type 设置为 TerseBitstringStatusListEntry, 并将 statusListEntryTerse.index 设置为 statusListEntryVerbose.statusListIndex 的整数表示。
  4. issuerUrl 设置为签发者希望用于凭证验证的 URL。
  5. unsignedStatus 设置为一个 OpticalBarcodeCredential, 其中 unsignedStatus.issuer 设置为 issuerUrl, 并且 unsignedStatus.credentialStatus 设置为 statusListEntryTerse
  6. signedStatusVc 设置为使用 3.2.4.1 添加证明 (ecdsa-xi-2023) 中的算法对 opticalDataunsignedStatus 进行签名的结果。
  7. 使用 CBOR-LD [CBOR-LD] 编码 signedStatusVc, 并将其添加到 opticalData 的指定区域。
  8. 生成机器可读凭证(MRZ 或 PDF417)。

3.2.2 解码 OpticalBarcodeCredential

  1. securedDocument 设置为 PDF417 或 MRZ 中的数据。
  2. verificationResult 设置为将第 3.2.4.2 验证证明 (ecdsa-xi-2023)中的算法应用于 securedDocument 的结果。
  3. credential 设置为 securedDocument 中的 OpticalBarcodeCredential
  4. statusListEntry 设置为将第 3.2.3 转换状态列表条目中的算法应用于 credential 的结果。
  5. statusResult 设置为将 Bitstring Status List v1.0:验证算法应用于 statusListEntry 的结果。
  6. 返回(validationResultstatusResult)。

3.2.3 转换状态列表 条目

本节中的算法用于将 TerseBitstringStatusListEntry 转换为 BitstringStatusListEntry; 在已对可验证 凭证 执行验证之后, 该对象会在验证过程中使用。

可验证 凭证验证完成之后, 该算法接受一个 OpticalBarcodeCredential 可验证 凭证结构 vc)、 一个整数 listLength(包含与 vc 关联的 BitstringStatusListCredential 中的条目数量),以及一个字符串 statusPurpose(例如,'revocation'、'suspension'...)作为输入,并返回 一个 'BitstringStatusListEntry' 对象。

  1. result 设置为空映射
  2. listIndex 设置为 vc.credentialStatus.terseStatusListIndex/listLength 向下取整到 下一个最低整数(即,应用 floor() 操作)。
  3. statusListIndex 设置为 vc.credentialStatus.terseStatusListIndex % listLength
  4. result.statusListCredential 设置为连接以下 值的结果: vc.credentialStatus.terseStatusListBaseUrl、'/'、 statusPurpose、'/'、listIndex
  5. result.type 设置为 'BitstringStatusListEntry'。
  6. result.statusListIndex 设置为 statusListIndex
  7. result.statusPurpose 设置为 statusPurpose
  8. 返回 result

result 可用作 Bitstring Status List v1.0 规范中 验证算法的输入。

:状态 列表是可选的

建议实现者注意,并非所有签发者都会为其可验证 凭证发布状态 列表信息。一些签发者 可能要求授权,然后才允许验证者访问 状态列表凭证。

3.2.4 ecdsa-xi-2023

ecdsa-xi-2023 密码套件实际上是 ecdsa-rdfc-2019 算法 [VC-DI-ECDSA],并添加了一个步骤, 该步骤接受一些“额外信息” (xi)作为输入,例如原始光学条形码数据,并将该数据 纳入由数字签名保护的信息中。本节中的算法 详细说明了如何创建和验证此类签名。

3.2.4.1 添加证明 (ecdsa-xi-2023)

要生成证明,MUST执行数据完整性 [VC-DATA-INTEGRITY] 规范中 第 4.1 节:添加证明中的算法。 对于该算法,特定于密码套件的 转换算法定义在 数据 完整性 ECDSA 密码套件 v1.0 转换 (ecdsa-rdfc-2019)一节中, 哈希算法定义在第 3.2.4.3 哈希 (ecdsa-xi-2023)中,并且 证明序列化算法定义在 数据 完整性 ECDSA 密码套件 v1.0 证明序列化 (ecdsa-rdfc-2019)一节中。

3.2.4.2 验证证明 (ecdsa-xi-2023)

要验证证明,MUST执行数据完整性 [VC-DATA-INTEGRITY] 规范中 第 4.2 节:验证证明中的算法。对于该算法,特定于密码 套件的 转换算法定义在 数据 完整性 ECDSA 密码套件 v1.0 转换 (ecdsa-rdfc-2019)一节中, 哈希算法定义在 第 3.2.4.3 哈希 (ecdsa-xi-2023)中,并且 证明验证算法定义在 数据 完整性 ECDSA 密码套件 v1.0 证明验证 (ecdsa-rdfc-2019)一节中。

3.2.4.3 哈希 (ecdsa-xi-2023)

哈希算法是在 数据完整性 ECDSA 密码套件 v1.0 规范的 哈希 (ecdsa-rdfc-2019)一节中定义的算法, 并添加了如下所述的光学数据哈希。假定 实现会向该哈希算法提供机器可读光学数据(PDF417 或 MRZ 数据)。

该算法所需的输入是一个已转换数据文档transformedDocument)、一个规范证明配置canonicalProofConfig),以及光学数据opticalDataBytes)。输出会产生一个表示为 一系列字节的哈希数据值。

哈希算法是在 数据完整性 ECDSA 密码套件 v1.0 哈希 (ecdsa-rdfc-2019)一节中定义的算法,并将步骤 3 替换为以下两个步骤:

  1. opticalDataHash 为将同一个哈希算法 应用于 opticalDataBytes 值所得的结果, 该哈希算法与应用于 hashData 的算法相同。
  2. hashData 为连接 proofConfigHash(第一个 哈希)、transformedDocumentHash(第二个哈希)和 opticalDataHash(第三个哈希)的结果。
3.2.4.4 创建 opticalDataBytes
AamvaDriversLicenseScannableInformation 凭证
  1. dataToCanonicalize 设置为空数组。
  2. bitfieldDecoded 设置为对 credentialSubject.protectedComponentIndex 从 multibase-base64url 解码为 二进制后所得长度为 24 的位串的前 22 位。
  3. fieldsAlphabetized 设置为包含 22 个 AAMVA 必填 PDF417 元素 ID 的数组 [aamva-dl-id-card-design-standard], 并按 Unicode 码点顺序排序(即,['DAC', 'DAD' ... 'DDG'])。
  4. bitfieldDecoded 中每个值为 1 的位:
    1. 将字符串 fieldName 设置为 fieldsAlphabetized[i],其中 ibitfieldDecoded 中该位的索引。
    2. 将字符串 fieldData 设置为将出现在 PDF417 中 与该字段名称关联的数据。
    3. fieldData 连接到 fieldName 的末尾, 再将换行字符(\nU+000A)连接到末尾, 并将结果追加到 dataToCanonicalize
  5. canonicalizedData 设置为对 dataToCanonicalize 按 Unicode 码点顺序排序后,再应用 join 操作 从数组创建单个字符串所得的结果。
  6. canonicalizedData 进行哈希并返回结果。
MachineReadableZone 凭证
  1. dataToCanonicalize 设置为空数组。
  2. 对凭证上机器可读区中的每一行:
    1. mrzLine 设置为一个包含该行中数据的字符串。
    2. mrzLine 末尾追加换行字符,并将 mrzLine 追加到 dataToCanonicalize
  3. canonicalizedData 设置为按元素在凭证上出现的顺序 对 dataToCanonicalize 的元素进行排序后, 再应用 join 操作从数组创建单个字符串所得的结果。
  4. canonicalizedData 进行哈希并返回结果。
3.2.4.5 证明 配置 (ecdsa-xi-2023)

证明配置算法是在 数据 完整性 ECDSA 密码套件 v1.0 证明配置 (ecdsa-rdfc-2019)一节中定义的算法,并将 步骤 4 替换为以下步骤:

  1. 如果 options.type 未设置为 DataIntegrityProof, 并且 proofConfig.cryptosuite 未设置为 ecdsa-xi-2023, 则MUST引发 INVALID_PROOF_CONFIGURATION 错误。

4. 安全考量

本节为非规范性内容。

在阅读本节之前,强烈建议读者熟悉 数据完整性规范的 安全考量一节中提供的一般安全建议,以及 ECDSA 密码套件规范的 安全考量一节中提供的具体安全建议。

在以下各节中,我们会回顾这些要点,并引导 读者了解更多信息。

4.1 光学数据重复

针对 OpticalBarcodeCredentials 的一种攻击向量涉及复制 包含数字签名的光学条形码,以用于欺诈性文档。 虽然复制的条形码会像原始条形码一样通过签名验证,但此攻击 可通过文档验证者检查以下三项来缓解:签名数据 与文档上可见的数据相匹配,签名数据与 用户的实体属性相匹配,并且可见数据与用户的实体属性相匹配。当这 三项全部等同时,OpticalBarcodeCredential 可能是 副本的唯一方式,是欺诈性文档创建者能够访问一个真实的 OpticalBarcodeCredential,且其中已签名的实体属性与 欺诈性文档使用者的属性完全重叠。存在一个未被发现的 被盗 OpticalBarcodeCredential,并且其完全匹配 任意人员外观的可能性很低,因此此攻击不太可能成功。

4.2 部分签名的光学数据

在某些情况下,数字签名可能无法覆盖 现有光学数据的全部内容。例如,考虑这样一种情况: 某个序列号由实体凭证制造商注入, 因而签发者在签名时并不知道该序列号。在这种情况下,验证者 会假定任何未被数字签名的数据都可能已在 光学条形码中被更改,而不会影响 OpticalBarcodeCredential 成功验证的能力。

在检查光学条形码中的数据是否与 文档上可见的数据以及文档持有者的特征相匹配时,实现者 被建议只使用经过数字签名的字段。验证者被 建议只使用受数字签名保护的字段,无论 其他字段在未签名文档上的欺诈检测中多么常用。例如, 如果眼睛颜色和头发颜色受签名保护,但 持有者的 肖像未受保护,则建议验证者在尝试通过肖像检测欺诈时, 更强调眼睛 颜色和头发颜色。

建议由验证者使用的软件的实现者, 在验证过程中只显示 已通过数字签名保护的卡片数据。显示 未签名数据(这些数据可能已被篡改)可能会干扰欺诈检测。

4.3 安全验证

建议验证者 始终使用可信程序和接口来检查 OpticalBarcodeCredential 的有效性。使用不可信软件验证文档 可能导致欺诈性凭证被接受,或真实凭证被盗。

5. 隐私考量

在阅读本节之前,强烈建议读者熟悉 数据完整性规范的 安全考量一节中提供的一般安全建议,以及 ECDSA 密码套件规范的 安全考量一节中提供的具体安全建议。

以下一节描述了实现本规范的开发者 应当了解的隐私考量,以避免违反 隐私假设。

议题 1
添加更多隐私考量,至少包括以下内容:
  • 条形码可以在一定距离外读取;因此,非常 敏感的信息不应编码进条形码,而可能更适合通过 NFC 或加密的在线通信通道传输。

6. 测试向量

本节为非规范性内容。

本节包含可验证凭证条形码的示例,以及 它们如何生成和验证的逐步过程。

在本节中,我们将分析两个贯穿示例:一个用于保护 乌托邦就业许可文件 MRZ 的 VCB,以及一个用于保护 乌托邦驾驶证 PDF417 的 VCB。

6.1 创建 VCB

6.1.1 乌托邦驾驶证

我们从将由 VCB 签名的数据开始(即 PDF417 中的 AAMVA 必填字段):

示例 7:可能出现在 乌托邦驾驶证上的 PDF417 字段
DACJOHN
DADNONE
DAG123 MAIN ST
DAIANYVILLE
DAJUTO
DAKF87P20000
DAQF987654321
DAU069 IN
DAYBRO
DBA04192030
DBB04191988
DBC1
DBD01012024
DCAC
DCBNONE
DCDNONE
DCFUTODOCDISCRIM
DCGUTO
DCSSMITH
DDEN
DDFN
DDGN
6.1.1.1 创建 opticalDataBytes

为简单起见,假设你想要签名的 PDF417 中唯一数据是 名字(DAC)、姓氏(DCS)和驾驶证号(DAQ)。 用于 protectedComponentIndex 的位串值随后为 100000100000000000100000, 并且 protectedComponentIndex 的值为 "uggAg"。应用 3.2.4.4 创建 opticalDataBytes,我们得到

示例 8:乌托邦 驾驶证规范化所得的数据
canonicalizedData = 'DACJOHN\nDAQF987654321\nDCSSMITH\n'
opticalDataBytes:
  [188,  38, 200, 146, 227, 213,  90, 250,
  50,  18, 126, 254,  47, 177,  91,  23,
  64, 129, 104, 223, 136,  81, 116,  67,
  136, 125, 137, 165, 117,  63, 152, 207]

现在,我们可以将此哈希值与 3.2.4.3 哈希 (ecdsa-xi-2023) 一起使用,以签名该 VC。 使用 BitstringStatusListCredential 执行 3.2.1 编码 OpticalBarcodeCredential,我们得到以下 JSON-LD VC:

6.1.1.2 示例 VC
示例 9:乌托邦驾驶证 VCB 的 JSON-LD VC
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/vc-barcodes/v1",
    "https://w3id.org/utopia/v2"
  ],
  "type": [
    "VerifiableCredential",
    "OpticalBarcodeCredential"
  ],
  "credentialSubject": {
    "type": "AamvaDriversLicenseScannableInformation",
    "protectedComponentIndex": "uggAg"
  },
  "issuer": "did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj",
  "credentialStatus": {
    "type": "TerseBitstringStatusListEntry",
    "terseStatusListBaseUrl": "https://sandbox.platform.veres.dev/statuses/z19rJ4oGrbFCqf3cNTVDHSbNd/status-lists",
    "terseStatusListIndex": 3851559041
  },
  "proof": {
    "type": "DataIntegrityProof",
    "verificationMethod": "did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj#zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj",
    "cryptosuite": "ecdsa-xi-2023",
    "proofPurpose": "assertionMethod",
    "proofValue": "z4g6G3dAZhhtPxPWgFvkiRv7krtCaeJxjokvL46fchAFCXEY3FeX2vn46MDgBaw779g1E1jswZJxxreZDCrtHg2qH"
  }
}
6.1.1.3 CBOR-LD 压缩和编码

现在,我们可以对该 VC 应用 CBOR-LD 压缩。这里,我们使用 最新版本的 CBOR-LD;不过,在本节末尾,我们提供了 使用旧版本 CBOR-LD 编码的 VCB,用于与 未保持最新的 CBOR-LD 实现进行互操作性测试。

对于本规范,我们已保留值为 100 的 CBOR-LD 注册表条目 (即,这些载荷将以标签 0x0664 开头)。随后, 使用 CBOR-LD 编码的参数可在 CBOR-LD 规范的注册表中找到, 如下所示:

示例 10:CBOR-LD 编码参数
registryEntryId: 100
typeTable:
{
  "context":
    {
      "https://www.w3.org/ns/credentials/v2": 32768,
      "https://w3id.org/vc-barcodes/v1": 32769,
      "https://w3id.org/utopia/v2": 32770
    },

  "https://w3id.org/security#cryptosuiteString":
    {
      "ecdsa-rdfc-2019": 1,
      "ecdsa-sd-2023": 2,
      "eddsa-rdfc-2022": 3,
      "ecdsa-xi-2023": 4
    }
}

处理上下文并为上下文术语分配整数值后, 应得到的术语到 ID 映射如下:

示例 11:CBOR-LD 在压缩乌托邦 DL 时 创建的术语到 ID 映射
Map(97) {
  '@context' => 0,
  '@type' => 2,
  '@id' => 4,
  '@value' => 6,
  '@direction' => 8,
  '@graph' => 10,
  '@included' => 12,
  '@index' => 14,
  '@json' => 16,
  '@language' => 18,
  '@list' => 20,
  '@nest' => 22,
  '@reverse' => 24,
  '@base' => 26,
  '@container' => 28,
  '@default' => 30,
  '@embed' => 32,
  '@explicit' => 34,
  '@none' => 36,
  '@omitDefault' => 38,
  '@prefix' => 40,
  '@preserve' => 42,
  '@protected' => 44,
  '@requireAll' => 46,
  '@set' => 48,
  '@version' => 50,
  '@vocab' => 52,
  '...' => 100,
  'BitstringStatusList' => 102,
  'BitstringStatusListCredential' => 104,
  'BitstringStatusListEntry' => 106,
  'DataIntegrityProof' => 108,
  'EnvelopedVerifiableCredential' => 110,
  'EnvelopedVerifiablePresentation' => 112,
  'JsonSchema' => 114,
  'JsonSchemaCredential' => 116,
  'VerifiableCredential' => 118,
  'VerifiablePresentation' => 120,
  '_sd' => 122,
  '_sd_alg' => 124,
  'aud' => 126,
  'cnf' => 128,
  'description' => 130,
  'digestMultibase' => 132,
  'digestSRI' => 134,
  'exp' => 136,
  'iat' => 138,
  'id' => 140,
  'iss' => 142,
  'jku' => 144,
  'kid' => 146,
  'mediaType' => 148,
  'name' => 150,
  'nbf' => 152,
  'sub' => 154,
  'type' => 156,
  'x5u' => 158,
  'AamvaDriversLicenseScannableInformation' => 160,
  'MachineReadableZone' => 162,
  'OpticalBarcodeCredential' => 164,
  'TerseBitstringStatusListEntry' => 166,
  'protectedComponentIndex' => 168,
  'did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj' => 170,
  'did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj#zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj' => 172,
  'did:key:zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj' => 174,
  'did:key:zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj#zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj' => 176,
  'https://sandbox.platform.veres.dev/statuses/z19rJ4oGrbFCqf3cNTVDHSbNd/status-lists' => 178,
  'confidenceMethod' => 180,
  'credentialSchema' => 182,
  'credentialStatus' => 184,
  'credentialSubject' => 186,
  'evidence' => 188,
  'issuer' => 190,
  'proof' => 192,
  'refreshService' => 194,
  'relatedResource' => 196,
  'renderMethod' => 198,
  'termsOfUse' => 200,
  'validFrom' => 202,
  'validUntil' => 204,
  'terseStatusListBaseUrl' => 206,
  'terseStatusListIndex' => 208,
  'challenge' => 210,
  'created' => 212,
  'cryptosuite' => 214,
  'domain' => 216,
  'expires' => 218,
  'nonce' => 220,
  'previousProof' => 222,
  'proofPurpose' => 224,
  'proofValue' => 226,
  'verificationMethod' => 228,
  'assertionMethod' => 230,
  'authentication' => 232,
  'capabilityDelegation' => 234,
  'capabilityInvocation' => 236,
  'keyAgreement' => 238
}

有关上述内容的更多信息,请参见6.3 实现说明

这会得到以下已编码凭证:

示例 12:CBOR-LD 压缩的乌托邦驾驶 证 VC
D9CB1D821864A60183198000198001198002189D82187618A418B8A3189C18A618CE18B218D01AE592208118BAA2189C18A018A8447582002018BE18AA18C0A5189C186C18D60418E018E618E258417AB7C2E56B49E2CCE62184CE26818E15A8B173164401B5D3BB93FFD6D2B5EB8F6AC0971502AE3DD49D17EC66528164034C912685B8111BC04CDC9EC13DBADD91CC18E418AC

diagnostic:
51997([
  100,
  {
    1: [32768, 32769, 32770],
    157: [118, 164],
    184: {156: 166, 206: 178, 208: 3851559041},
    186: {156: 160, 168: h'75820020'},
    190: 170,
    192: {
      156: 108,
      214: 4,
      224: 230,
      226: h'7AB7C2E56B49E2CCE62184CE26818E15A8B173164401B5D3BB93FFD6D2B5EB8F6AC0971502AE3DD49D17EC66528164034C912685B8111BC04CDC9EC13DBADD91CC',
      228: 172
    }
  }
])

将驾驶证 CBOR-LD 编码为 base64url,并将结果插入 PDF417 字节中 'ZZ' 子文件的 'ZZA' 字段:

示例 13:包含已编码 乌托邦驾驶证 VCB 的 PDF417 字节
bytes(@\n\x1e\rANSI 000000090002DL00410234ZZ02750202DLDAQF987654321\nDCSSMITH\nDDEN\nDACJOHN\nDDFN\nDADNONE\nDDGN\nDCAC\nDCBNONE\nDCDNONE\nDBD01012024\nDBB04191988\nDBA04192030\nDBC1\nDAU069 IN\nDAYBRO\nDAG123 MAIN ST\nDAIANYVILLE\nDAJUTO\nDAKF87P20000  \nDCFUTODOCDISCRIM\nDCGUTO\nDAW158\nDCK1234567890\nDDAN\rZZZZA2csdghhkpgGDGYAAGYABGYACGJ2CGHYYpBi4oxicGKYYzhiyGNAa5ZIggRi6ohicGKAYqER1ggAgGL4YqhjApRicGGwY1gQY4BjmGOJYQXq3wuVrSeLM5iGEziaBjhWosXMWRAG107uT/9bSteuPasCXFQKuPdSdF+xmUoFkA0yRJoW4ERvATNyewT263ZHMGOQYrA==\r)

上述内容现在可以转换为条形码:

来自乌托邦驾驶证的 VCB。
6 来自乌托邦驾驶证的 VCB。

6.1.2 乌托邦 就业许可文件

我们从将由 VCB 签名的数据开始(即 MRZ):

示例 14:可能出现在 乌托邦 EAD 上的机器可读区
IAUTO0000007010SRC0000000701<<
8804192M2601058NOT<<<<<<<<<<<5
SMITH<<JOHN<<<<<<<<<<<<<<<<<<<
6.1.2.1 创建 opticalDataBytes

对于 EAD,我们应用 3.2.4.4 创建 opticalDataBytes

示例 15:乌托邦 EAD MRZ 规范化所得的数据
canonicalizedData =
  'IAUTO0000007010SRC0000000701<<\n' +
  '8804192M2601058NOT<<<<<<<<<<<5\n' +
  'SMITH<<JOHN<<<<<<<<<<<<<<<<<<<\n'
opticalDataBytes:
[8, 198, 126, 183,  25, 160, 166, 112,
254, 184, 189,  47, 225, 211, 125, 210,
132, 137, 45,  86, 169,  28,  57, 165,
46, 253, 9, 137, 145,  42, 192, 113]

现在,我们可以将此哈希值与 3.2.4.3 哈希 (ecdsa-xi-2023) 一起使用,以签名该 VC。 不添加状态地执行 3.2.1 编码 OpticalBarcodeCredential,我们得到以下 JSON-LD VC:

6.1.2.2 示例 VC
示例 16:乌托邦 EAD VCB 的 JSON-LD VC
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/vc-barcodes/v1",
    "https://w3id.org/utopia/v2"
  ],
  "type": [
    "VerifiableCredential",
    "OpticalBarcodeCredential"
  ],
  "credentialSubject": {
    "type": "MachineReadableZone"
  },
  "issuer": "did:key:zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj",
  "proof": {
    "type": "DataIntegrityProof",
    "verificationMethod": "did:key:zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj#zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj",
    "cryptosuite": "ecdsa-xi-2023",
    "proofPurpose": "assertionMethod",
    "proofValue": "z4B8AQgjwgsEdcPEZkrkK2mTVKn7qufoDgDkv9Qitf9tjxQPMoJaGdXwDrThjp7LUdvzsDJ7UwYu6Xpm9fjbo6QnJ"
  }
}
6.1.2.3 CBOR-LD 压缩和编码

现在,我们可以对该 VC 应用 CBOR-LD 压缩。这里我们使用 最新版本的 CBOR-LD,不过在本节末尾,我们提供了 使用旧版本 CBOR-LD 编码的 VCB,用于与 未保持最新的 CBOR-LD 实现进行互操作性测试。

对于本规范,我们已保留值为 100 的 CBOR-LD 注册表条目 (即,这些载荷将以标签 0x0664 开头)。随后, 使用 CBOR-LD 编码的参数可在 CBOR-LD 规范的注册表中找到, 如下所示:

示例 17:CBOR-LD 编码参数
registryEntryId: 100
typeTable:
{
  "context":
    {
      "https://www.w3.org/ns/credentials/v2": 32768,
      "https://w3id.org/vc-barcodes/v1": 32769,
      "https://w3id.org/utopia/v2": 32770
    },

  "https://w3id.org/security#cryptosuiteString":
    {
      "ecdsa-rdfc-2019": 1,
      "ecdsa-sd-2023": 2,
      "eddsa-rdfc-2022": 3,
      "ecdsa-xi-2023": 4
    }
}

处理上下文并为上下文术语分配整数值后, 应得到的术语到 ID 映射如下:

示例 18:CBOR-LD 在压缩乌托邦 EAD 时 创建的术语到 ID 映射
Map(95) {
  '@context' => 0,
  '@type' => 2,
  '@id' => 4,
  '@value' => 6,
  '@direction' => 8,
  '@graph' => 10,
  '@included' => 12,
  '@index' => 14,
  '@json' => 16,
  '@language' => 18,
  '@list' => 20,
  '@nest' => 22,
  '@reverse' => 24,
  '@base' => 26,
  '@container' => 28,
  '@default' => 30,
  '@embed' => 32,
  '@explicit' => 34,
  '@none' => 36,
  '@omitDefault' => 38,
  '@prefix' => 40,
  '@preserve' => 42,
  '@protected' => 44,
  '@requireAll' => 46,
  '@set' => 48,
  '@version' => 50,
  '@vocab' => 52,
  '...' => 100,
  'BitstringStatusList' => 102,
  'BitstringStatusListCredential' => 104,
  'BitstringStatusListEntry' => 106,
  'DataIntegrityProof' => 108,
  'EnvelopedVerifiableCredential' => 110,
  'EnvelopedVerifiablePresentation' => 112,
  'JsonSchema' => 114,
  'JsonSchemaCredential' => 116,
  'VerifiableCredential' => 118,
  'VerifiablePresentation' => 120,
  '_sd' => 122,
  '_sd_alg' => 124,
  'aud' => 126,
  'cnf' => 128,
  'description' => 130,
  'digestMultibase' => 132,
  'digestSRI' => 134,
  'exp' => 136,
  'iat' => 138,
  'id' => 140,
  'iss' => 142,
  'jku' => 144,
  'kid' => 146,
  'mediaType' => 148,
  'name' => 150,
  'nbf' => 152,
  'sub' => 154,
  'type' => 156,
  'x5u' => 158,
  'AamvaDriversLicenseScannableInformation' => 160,
  'MachineReadableZone' => 162,
  'OpticalBarcodeCredential' => 164,
  'TerseBitstringStatusListEntry' => 166,
  'protectedComponentIndex' => 168,
  'did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj' => 170,
  'did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj#zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj' => 172,
  'did:key:zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj' => 174,
  'did:key:zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj#zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj' => 176,
  'https://sandbox.platform.veres.dev/statuses/z19rJ4oGrbFCqf3cNTVDHSbNd/status-lists' => 178,
  'confidenceMethod' => 180,
  'credentialSchema' => 182,
  'credentialStatus' => 184,
  'credentialSubject' => 186,
  'evidence' => 188,
  'issuer' => 190,
  'proof' => 192,
  'refreshService' => 194,
  'relatedResource' => 196,
  'renderMethod' => 198,
  'termsOfUse' => 200,
  'validFrom' => 202,
  'validUntil' => 204,
  'challenge' => 206,
  'created' => 208,
  'cryptosuite' => 210,
  'domain' => 212,
  'expires' => 214,
  'nonce' => 216,
  'previousProof' => 218,
  'proofPurpose' => 220,
  'proofValue' => 222,
  'verificationMethod' => 224,
  'assertionMethod' => 226,
  'authentication' => 228,
  'capabilityDelegation' => 230,
  'capabilityInvocation' => 232,
  'keyAgreement' => 234
}

有关上述内容的更多信息,请参见6.3 实现说明

随后,压缩会得到以下已编码凭证:

示例 19:CBOR-LD 压缩的乌托邦 EAD VC
D9CB1D821864A50183198000198001198002189D82187618A418BAA1189C18A218BE18AE18C0A5189C186C18D20418DC18E218DE58417A9EC7F688F60CAA8C757592250B3F6D6E18419941F186E1ED4245770E687502D51D01CD2C2295E4338178A51A35C2F044A85598E15DB9AEF00261BC5C95A744E718E018B0

diagnostic:
51997([
  100,
  {
    1: [32768, 32769, 32770],
    157: [118, 164],
    186: {156: 162},
    190: 174,
    192: {
      156: 108,
      210: 4,
      220: 226,
      222: h'7A9EC7F688F60CAA8C757592250B3F6D6E18419941F186E1ED4245770E687502D51D01CD2C2295E4338178A51A35C2F044A85598E15DB9AEF00261BC5C95A744E7',
      224: 176
    }
  }
])

将 EAD CBOR-LD 编码为 base45-multibase,并前置 'VC1-':

示例 20:已编码的乌托邦 EAD VCB
VC1-R0OR*W3Y33V%K PG88G3A3B60A8G1534KG$-ENXKWQN053653Y53I53 539*K0XJ.TDYOQJ63P63L6337BPMFPCP7EH2R12YH%%EXU4$08E-D8D86F8E2HX:T8Z8/ 1TZEH.QBA03Q5W.I0N6FBF4E3:SOQU8. A3MSELNHFU0GCVVBP6LU9T%ES-3

上述内容现在可以转换为二维码:

6.1.2.4 就业 许可文件
来自乌托邦 EAD 的 VCB。
7 来自乌托邦 EAD 的 VCB。

与以下 MRZ 一起使用:

乌托邦就业许可文件上的 MRZ。
8 乌托邦就业许可文件上的 MRZ。

6.2 验证 VCB

现在我们应用反向过程进行验证。

6.2.1 乌托邦驾驶证

6.2.1.1 解码和 解压缩

我们首先从 PDF417 读取数据:

示例 21:包含已编码 乌托邦驾驶证 VCB 的 PDF417 字节
bytes(@\n\x1e\rANSI 000000090002DL00410234ZZ02750202DLDAQF987654321\nDCSSMITH\nDDEN\nDACJOHN\nDDFN\nDADNONE\nDDGN\nDCAC\nDCBNONE\nDCDNONE\nDBD01012024\nDBB04191988\nDBA04192030\nDBC1\nDAU069 IN\nDAYBRO\nDAG123 MAIN ST\nDAIANYVILLE\nDAJUTO\nDAKF87P20000  \nDCFUTODOCDISCRIM\nDCGUTO\nDAW158\nDCK1234567890\nDDAN\rZZZZA2csdghhkpgGDGYAAGYABGYACGJ2CGHYYpBi4oxicGKYYzhiyGNAa5ZIggRi6ohicGKAYqER1ggAgGL4YqhjApRicGGwY1gQY4BjmGOJYQXq3wuVrSeLM5iGEziaBjhWosXMWRAG107uT_9bSteuPasCXFQKuPdSdF-xmUoFkA0yRJoW4ERvATNyewT263ZHMGOQYrA==\r)

我们提取 'ZZ' 子文件中 'ZZA' 字段的数据,并撤销 base 编码:

示例 22:使用 CBOR-LD 压缩的乌托邦驾驶证 VC
D9CB1D821864A60183198000198001198002189D82187618A418B8A3189C18A618CE18B218D01AE592208118BAA2189C18A018A8447582002018BE18AA18C0A5189C186C18D60418E018E618E258417AB7C2E56B49E2CCE62184CE26818E15A8B173164401B5D3BB93FFD6D2B5EB8F6AC0971502AE3DD49D17EC66528164034C912685B8111BC04CDC9EC13DBADD91CC18E418AC

现在,我们使用 CBOR-LD 解压缩,以得到将要验证的 原始 JSON-LD VC。同样,这些参数与 CBOR-LD 注册表条目 100 关联。

示例 23:CBOR-LD 解码参数
typeTable:
{
  "context":
    {
      "https://www.w3.org/ns/credentials/v2": 32768,
      "https://w3id.org/vc-barcodes/v1": 32769,
      "https://w3id.org/utopia/v2": 32770
    },

  "https://w3id.org/security#cryptosuiteString":
    {
      "ecdsa-rdfc-2019": 1,
      "ecdsa-sd-2023": 2,
      "eddsa-rdfc-2022": 3,
      "ecdsa-xi-2023": 4
    }
}

处理上下文并为上下文术语分配整数值后, 应得到的 ID 到术语映射如下。请注意,这是 压缩期间构造的映射的反向映射。

示例 24:CBOR-LD 在解压缩乌托邦 DL 时 创建的 ID 到术语映射
Map(97) {
  0 => '@context',
  2 => '@type',
  4 => '@id',
  6 => '@value',
  8 => '@direction',
  10 => '@graph',
  12 => '@included',
  14 => '@index',
  16 => '@json',
  18 => '@language',
  20 => '@list',
  22 => '@nest',
  24 => '@reverse',
  26 => '@base',
  28 => '@container',
  30 => '@default',
  32 => '@embed',
  34 => '@explicit',
  36 => '@none',
  38 => '@omitDefault',
  40 => '@prefix',
  42 => '@preserve',
  44 => '@protected',
  46 => '@requireAll',
  48 => '@set',
  50 => '@version',
  52 => '@vocab',
  100 => '...',
  102 => 'BitstringStatusList',
  104 => 'BitstringStatusListCredential',
  106 => 'BitstringStatusListEntry',
  108 => 'DataIntegrityProof',
  110 => 'EnvelopedVerifiableCredential',
  112 => 'EnvelopedVerifiablePresentation',
  114 => 'JsonSchema',
  116 => 'JsonSchemaCredential',
  118 => 'VerifiableCredential',
  120 => 'VerifiablePresentation',
  122 => '_sd',
  124 => '_sd_alg',
  126 => 'aud',
  128 => 'cnf',
  130 => 'description',
  132 => 'digestMultibase',
  134 => 'digestSRI',
  136 => 'exp',
  138 => 'iat',
  140 => 'id',
  142 => 'iss',
  144 => 'jku',
  146 => 'kid',
  148 => 'mediaType',
  150 => 'name',
  152 => 'nbf',
  154 => 'sub',
  156 => 'type',
  158 => 'x5u',
  160 => 'AamvaDriversLicenseScannableInformation',
  162 => 'MachineReadableZone',
  164 => 'OpticalBarcodeCredential',
  166 => 'TerseBitstringStatusListEntry',
  168 => 'protectedComponentIndex',
  170 => 'did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj',
  172 => 'did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj#zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj',
  174 => 'did:key:zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj',
  176 => 'did:key:zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj#zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj',
  178 => 'https://sandbox.platform.veres.dev/statuses/z19rJ4oGrbFCqf3cNTVDHSbNd/status-lists',
  180 => 'confidenceMethod',
  182 => 'credentialSchema',
  184 => 'credentialStatus',
  186 => 'credentialSubject',
  188 => 'evidence',
  190 => 'issuer',
  192 => 'proof',
  194 => 'refreshService',
  196 => 'relatedResource',
  198 => 'renderMethod',
  200 => 'termsOfUse',
  202 => 'validFrom',
  204 => 'validUntil',
  206 => 'terseStatusListBaseUrl',
  208 => 'terseStatusListIndex',
  210 => 'challenge',
  212 => 'created',
  214 => 'cryptosuite',
  216 => 'domain',
  218 => 'expires',
  220 => 'nonce',
  222 => 'previousProof',
  224 => 'proofPurpose',
  226 => 'proofValue',
  228 => 'verificationMethod',
  230 => 'assertionMethod',
  232 => 'authentication',
  234 => 'capabilityDelegation',
  236 => 'capabilityInvocation',
  238 => 'keyAgreement'
}

有关上述内容的更多信息,请参见6.3 实现说明

随后,解压缩会得到以下凭证:

示例 25:乌托邦驾驶证 VCB 的 JSON-LD VC
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/vc-barcodes/v1",
    "https://w3id.org/utopia/v2"
  ],
  "type": [
    "VerifiableCredential",
    "OpticalBarcodeCredential"
  ],
  "credentialSubject": {
    "type": "AamvaDriversLicenseScannableInformation",
    "protectedComponentIndex": "uggAg"
  },
  "issuer": "did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj",
  "credentialStatus": {
    "type": "TerseBitstringStatusListEntry",
    "terseStatusListBaseUrl": "https://sandbox.platform.veres.dev/statuses/z19rJ4oGrbFCqf3cNTVDHSbNd/status-lists",
    "terseStatusListIndex": 3851559041
  },
  "proof": {
    "type": "DataIntegrityProof",
    "verificationMethod": "did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj#zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj",
    "cryptosuite": "ecdsa-xi-2023",
    "proofPurpose": "assertionMethod",
    "proofValue": "z4g6G3dAZhhtPxPWgFvkiRv7krtCaeJxjokvL46fchAFCXEY3FeX2vn46MDgBaw779g1E1jswZJxxreZDCrtHg2qH"
  }
}
6.2.1.2 验证

我们应用 3.2.4.4 创建 opticalDataBytes 来创建 ecdsa-xi-2023 所需的 opticalDataBytes, 使用扫描得到的 PDF417 和 protectedComponentIndex 作为输入。

示例 26:乌托邦驾驶证 PDF417 的 规范化
canonicalizedData = 'DACJOHN\nDAQ987654321\nDCSSMITH\n'
opticalDataBytes:
  [188,  38, 200, 146, 227, 213,  90, 250,
  50,  18, 126, 254,  47, 177,  91,  23,
  64, 129, 104, 223, 136,  81, 116,  67,
  136, 125, 137, 165, 117,  63, 152, 207]

然后,我们应用 3.2.4.3 哈希 (ecdsa-xi-2023)3.2.4.2 验证 证明 (ecdsa-xi-2023) 来验证 该凭证。

6.2.1.3 状态检查

最后一步是检查驾驶证 凭证上的状态信息。我们应用 3.2.3 转换状态列表条目TerseBitstringStatusListEntry 转换为 BitstringStatusListEntry。 这里我们检查两种状态类型:'revocation' 和 'suspension',并将这些 字符串作为 statusPurpose 的值传入。

示例 27:状态目的为 revocation 的 BitstringStatusListEntry
{
  type: 'BitstringStatusListEntry',
  statusListCredential: 'https://sandbox.platform.veres.dev/statuses/z19rJ4oGrbFCqf3cNTVDHSbNd/status-lists/revocation/29385',
  statusListIndex: 8321,
  statusPurpose: 'revocation'
}
示例 28:状态目的为 suspension 的 BitstringStatusListEntry
{
  type: 'BitstringStatusListEntry',
  statusListCredential: 'https://sandbox.platform.veres.dev/statuses/z19rJ4oGrbFCqf3cNTVDHSbNd/status-lists/suspension/29385',
  statusListIndex: 8321,
  statusPurpose: 'suspension'
}

然后,可以按 Bitstring Status List v1.0:验证算法中的方式验证这些条目。

6.2.2 乌托邦 就业许可文件

6.2.2.1 解码和 解压缩

我们首先从二维码读取数据:

示例 29:已编码的乌托邦驾驶证 EAD
VC1-R0OR*W3Y33V%K PG88G3A3B60A8G1534KG$-ENXKWQN053653Y53I53 539*K0XJ.TDYOQJ63P63L6337BPMFPCP7EH2R12YH%%EXU4$08E-D8D86F8E2HX:T8Z8/ 1TZEH.QBA03Q5W.I0N6FBF4E3:SOQU8. A3MSELNHFU0GCVVBP6LU9T%ES-3

我们提取 'VC1-' 之后的数据,并撤销 base 编码:

示例 30:CBOR-LD 压缩的乌托邦 EAD VC
D9CB1D821864A50183198000198001198002189D82187618A418BAA1189C18A218BE18AE18C0A5189C186C18D20418DC18E218DE58417A9EC7F688F60CAA8C757592250B3F6D6E18419941F186E1ED4245770E687502D51D01CD2C2295E4338178A51A35C2F044A85598E15DB9AEF00261BC5C95A744E718E018B0

现在,我们使用 CBOR-LD 解压缩,以得到将要验证的 原始 JSON-LD VC。同样,这些参数与 CBOR-LD 注册表条目 100 关联。

示例 31:CBOR-LD 解码参数
typeTable:
{
  "context":
    {
      "https://www.w3.org/ns/credentials/v2": 32768,
      "https://w3id.org/vc-barcodes/v1": 32769,
      "https://w3id.org/utopia/v2": 32770
    },

  "https://w3id.org/security#cryptosuiteString":
    {
      "ecdsa-rdfc-2019": 1,
      "ecdsa-sd-2023": 2,
      "eddsa-rdfc-2022": 3,
      "ecdsa-xi-2023": 4
    }
}

处理上下文并为上下文术语分配整数值后, 应得到的 ID 到术语映射如下。请注意,这是 压缩期间构造的映射的反向映射。

示例 32:CBOR-LD 在解压缩乌托邦 EAD 时 创建的 ID 到术语映射
Map(95) {
  0 => '@context',
  2 => '@type',
  4 => '@id',
  6 => '@value',
  8 => '@direction',
  10 => '@graph',
  12 => '@included',
  14 => '@index',
  16 => '@json',
  18 => '@language',
  20 => '@list',
  22 => '@nest',
  24 => '@reverse',
  26 => '@base',
  28 => '@container',
  30 => '@default',
  32 => '@embed',
  34 => '@explicit',
  36 => '@none',
  38 => '@omitDefault',
  40 => '@prefix',
  42 => '@preserve',
  44 => '@protected',
  46 => '@requireAll',
  48 => '@set',
  50 => '@version',
  52 => '@vocab',
  100 => '...',
  102 => 'BitstringStatusList',
  104 => 'BitstringStatusListCredential',
  106 => 'BitstringStatusListEntry',
  108 => 'DataIntegrityProof',
  110 => 'EnvelopedVerifiableCredential',
  112 => 'EnvelopedVerifiablePresentation',
  114 => 'JsonSchema',
  116 => 'JsonSchemaCredential',
  118 => 'VerifiableCredential',
  120 => 'VerifiablePresentation',
  122 => '_sd',
  124 => '_sd_alg',
  126 => 'aud',
  128 => 'cnf',
  130 => 'description',
  132 => 'digestMultibase',
  134 => 'digestSRI',
  136 => 'exp',
  138 => 'iat',
  140 => 'id',
  142 => 'iss',
  144 => 'jku',
  146 => 'kid',
  148 => 'mediaType',
  150 => 'name',
  152 => 'nbf',
  154 => 'sub',
  156 => 'type',
  158 => 'x5u',
  160 => 'AamvaDriversLicenseScannableInformation',
  162 => 'MachineReadableZone',
  164 => 'OpticalBarcodeCredential',
  166 => 'TerseBitstringStatusListEntry',
  168 => 'protectedComponentIndex',
  170 => 'did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj',
  172 => 'did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj#zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj',
  174 => 'did:key:zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj',
  176 => 'did:key:zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj#zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj',
  178 => 'https://sandbox.platform.veres.dev/statuses/z19rJ4oGrbFCqf3cNTVDHSbNd/status-lists',
  180 => 'confidenceMethod',
  182 => 'credentialSchema',
  184 => 'credentialStatus',
  186 => 'credentialSubject',
  188 => 'evidence',
  190 => 'issuer',
  192 => 'proof',
  194 => 'refreshService',
  196 => 'relatedResource',
  198 => 'renderMethod',
  200 => 'termsOfUse',
  202 => 'validFrom',
  204 => 'validUntil',
  206 => 'challenge',
  208 => 'created',
  210 => 'cryptosuite',
  212 => 'domain',
  214 => 'expires',
  216 => 'nonce',
  218 => 'previousProof',
  220 => 'proofPurpose',
  222 => 'proofValue',
  224 => 'verificationMethod',
  226 => 'assertionMethod',
  228 => 'authentication',
  230 => 'capabilityDelegation',
  232 => 'capabilityInvocation',
  234 => 'keyAgreement'
}

有关上述内容的更多信息,请参见6.3 实现说明

随后,解压缩会得到以下凭证:

示例 33:乌托邦 EAD VCB 的 JSON-LD VC
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/vc-barcodes/v1",
    "https://w3id.org/utopia/v2"
  ],
  "type": [
    "VerifiableCredential",
    "OpticalBarcodeCredential"
  ],
  "credentialSubject": {
    "type": "MachineReadableZone"
  },
  "issuer": "did:key:zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj",
  "proof": {
    "type": "DataIntegrityProof",
    "verificationMethod": "did:key:zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj#zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj",
    "cryptosuite": "ecdsa-xi-2023",
    "proofPurpose": "assertionMethod",
    "proofValue": "z4B8AQgjwgsEdcPEZkrkK2mTVKn7qufoDgDkv9Qitf9tjxQPMoJaGdXwDrThjp7LUdvzsDJ7UwYu6Xpm9fjbo6QnJ"
  }
}
6.2.2.2 验证

我们应用 3.2.4.4 创建 opticalDataBytes 来创建 ecdsa-xi-2023 所需的 opticalDataBytes,使用 EAD 上的 MRZ 作为 EAD 的输入:

示例 34:乌托邦 EAD MRZ 的规范化
canonicalizedData =
  'IAUTO0000007010SRC0000000701<<\n' +
  '8804192M2601058NOT<<<<<<<<<<<5\n' +
  'SMITH<<JOHN<<<<<<<<<<<<<<<<<<<\n'
opticalDataBytes:
[8, 198, 126, 183,  25, 160, 166, 112,
254, 184, 189,  47, 225, 211, 125, 210,
132, 137, 45,  86, 169,  28,  57, 165,
46, 253, 9, 137, 145,  42, 192, 113]

然后,我们应用 3.2.4.3 哈希 (ecdsa-xi-2023)3.2.4.2 验证 证明 (ecdsa-xi-2023) 来验证 该凭证。

6.3 实现说明

6.3.1 CBOR-LD

在从上下文术语构建到 CBOR-LD 整数的映射时,请注意, 一些上下文在其内部包含其他上下文,并嵌套在特定 类型的对象下。这些嵌套上下文称为“类型作用域上下文”,并且它们只有 在数据中使用关联类型时才会变为活动状态。这对于术语 ID 分配非常重要,因为上下文中的术语只有在该上下文变为 活动状态后才会被分配 ID。在这些测试向量中,这就是为什么 为驾驶证和就业许可文件创建的映射不同,即便这两个凭证使用 相同上下文。

此外,请注意,在 CBOR-LD 中,当关联值为复数时, 使用奇数来表达术语。例如,在上面的 CBOR-LD 术语到 ID 和 ID 到术语映射中,"type" 映射到 156,但在 VC 中表达多个类型的位置,则使用 157。

6.4 旧版 CBOR-LD 编码凭证

此过程用于测试是否使用了未完全 保持最新的 CBOR-LD 实现。

6.4.1 CBOR-LD 版本 6.X

该过程保持 相同,但 CBOR-LD 解码步骤除外;对于该步骤,应使用以下 appContextMap
示例 35:状态目的为 suspension 的 BitstringStatusListEntry
appContextMap:
[['https://www.w3.org/ns/credentials/v2', 32768],
['https://w3id.org/vc-barcodes/v1', 32769],
['https://w3id.org/utopia/v2', 32770]]
6.4.1.1 乌托邦驾驶 证
使用旧版 CBOR-LD 编码的乌托邦驾驶证 VCB。
9 使用旧版 CBOR-LD 编码的乌托邦驾驶证 VCB。
6.4.1.2 乌托邦就业许可文件
使用旧版 CBOR-LD 编码的乌托邦 EAD VCB。
10 使用旧版 CBOR-LD 编码的乌托邦 EAD VCB。

与以下 MRZ 一起使用:

乌托邦就业许可文件上的 MRZ。
11 乌托邦就业许可文件上的 MRZ。

6.4.2 CBOR-LD 版本 7.X

6.4.2.1 乌托邦驾驶 证
使用旧版 CBOR-LD 编码的乌托邦驾驶证 VCB。
12 使用旧版 CBOR-LD 编码的乌托邦驾驶证 VCB。
6.4.2.2 乌托邦就业许可文件
使用旧版 CBOR-LD 编码的乌托邦 EAD VCB。
13 使用旧版 CBOR-LD 编码的乌托邦 EAD VCB。

与以下 MRZ 一起使用:

乌托邦就业许可文件上的 MRZ。
14 乌托邦就业许可文件上的 MRZ。

7. 修订历史

本节为非规范性内容。

本节包含随时间推移对本 规范所作的实质性更改。

议题 2:内容将在 标准轨道启动后填充

本规范的内容将在 标准轨道流程启动后填充。

A. 参考文献

A.1 规范性引用

[aamva-dl-id-card-design-standard]
AAMVA 驾驶证/身份证设计标准(2020)。美国机动车管理者协会。2020。URL:https://www.aamva.org/assets/best-practices,-guides,-standards,-manuals,-whitepapers/aamva-dl-id-card-design-standard-(2020)
[CBOR-LD]
链接数据的紧凑二进制对象表示 v1.0。URL:https://w3c.github.io/cbor-ld/
[CID]
受控标识符 v1.0。Michael Jones; Manu Sporny。W3C。2025年5月15日。W3C 推荐标准。URL:https://www.w3.org/TR/cid-1.0/
[ICAO9303-3]
机器可读 旅行证件第 3 部分:所有 MRTD 通用规范,第八版, 2021。ICAO。国际民用航空组织。2021。URL:https://www.icao.int/publications/Documents/9303_p3_cons_en.pdf
[infra]
Infra 标准。Anne van Kesteren; Domenic Denicola。WHATWG。现行标准。URL:https://infra.spec.whatwg.org/
[ISO15438-2015]
ISO/IEC 15438:2015:PDF417 条形码 符号规范。ISO/IEC JTC 1/SC 31。国际标准化 组织。2015。URL:https://www.iso.org/standard/65502.html
[RFC2119]
用于 RFC 中表示 要求级别的关键词。S. Bradner。IETF。1997年3月。当前最佳实践。URL:https://www.rfc-editor.org/rfc/rfc2119
[RFC8174]
RFC 2119 关键词中大写与小写的歧义。B. Leiba。IETF。2017年5月。当前最佳实践。URL:https://www.rfc-editor.org/rfc/rfc8174
[URL]
URL 标准。Anne van Kesteren。WHATWG。 现行标准。URL:https://url.spec.whatwg.org/
[VC-BITSTRING-STATUS-LIST]
位串状态列表 v1.0。Manu Sporny; Dave Longley; Mahmoud Alkhraishi; Michael Prorock。W3C。2025年5月15日。W3C 推荐标准。URL:https://www.w3.org/TR/vc-bitstring-status-list/
[VC-DATA-INTEGRITY]
可验证凭证数据完整性 1.0。Ivan Herman; Manu Sporny; Ted Thibodeau Jr; Dave Longley; Greg Bernstein。 W3C。2025年5月15日。W3C 推荐标准。URL:https://www.w3.org/TR/vc-data-integrity/
[VC-DATA-MODEL-2.0]
可验证凭证数据模型 v2.0。Ivan Herman; Michael Jones; Manu Sporny; Ted Thibodeau Jr; Gabe Cohen。W3C。 2025年5月15日。W3C 推荐标准。URL:https://www.w3.org/TR/vc-data-model-2.0/
[VC-DI-ECDSA]
数据完整性 ECDSA 密码套件 v1.0。Manu Sporny; Dave Longley; Greg Bernstein。W3C。2025年5月15日。W3C 推荐标准。URL:https://www.w3.org/TR/vc-di-ecdsa/
[XPATH-FUNCTIONS]
XQuery 1.0 和 XPath 2.0 函数与 操作符(第二版)。Ashok Malhotra; Jim Melton; Norman Walsh; Michael Kay。W3C。2010年12月14日。W3C 推荐标准。URL:https://www.w3.org/TR/xpath-functions/