diff --git a/index.html b/index.html index a58ac1e..181703a 100644 --- a/index.html +++ b/index.html @@ -1,2480 +1,2495 @@ - - -
--This specification describes a mechanism to protect optical barcodes, -such as those found on driver's licenses (PDF417) and travel documents (MRZ), -using Verifiable Credentials [[VC-DATA-MODEL-2.0]]. The Verifiable Credential -representations are compact enough such that they fit in under 150 bytes and -can thus be integrated with traditional two-dimensional barcodes that are -printed on physical cards using standard printing processes. -
--This specification is experimental. -
- --Physical credentials, such as driver's licenses, passports, and travel -credentials often include machine-readable data that can be used to quickly read -the information from the document. This information is encoded in formats such -as PDF417 [[ISO15438-2015]], machine-readable zone (MRZ) [[ICAO9303-3]], and -other optically scannable codes that are formatted in one-dimensional or -two-dimensional "bars"; thus the term "barcode". This information is often -not protected from tampering and the readily available barcode generation and -scanning libraries mean that it is fairly trivial for anyone to generate these -barcodes. -
--It is, therefore, useful for an issuer of these barcodes to protect -the information contained within the barcode as well as the entity that -generated the barcode. -
--The [[[VC-DATA-MODEL-2.0]]] specification provides a global standard for -expressing credential information, such as those in a driver's license or -travel document. The [[[VC-DATA-INTEGRITY]]] specification provides a global -standard for securing credential information. These two specifications, when -combined, provide a means of protecting credentials from tampering, -expressing authorship of the credential, and providing the current status of -a credential in a privacy-protecting manner. These data formats, however, tend -to be too large to express in an optical barcode. -
--The [[[CBOR-LD]]] specification provides a means of compressing secured -verifiable credentials to the point at which it becomes feasible to -express the information as an optical barcode, or embedded within an optical -barcode. -
--This specification describes a mechanism to protect optical barcodes, -such as those found on driver's licenses (PDF417) and travel documents (MRZ), -by using a verifiable credential [[VC-DATA-MODEL-2.0]] to express -information about the barcode, which is then secured using Data Integrity -[[VC-DATA-INTEGRITY]], and then compressed using CBOR-LD [[CBOR-LD]]. The -resulting verifiable credential representations are compact enough such -that they fit in under 140 bytes and can thus be integrated with traditional -two-dimensional barcodes that are printed on physical cards using standard -printing processes. This adds tamper resistance to the barcode while -optionally enhancing the barcode to provide information related to whether or -not the physical document has been revoked or suspended by the issuer. -
- --The following sections provide a few introductory examples of the ways this -specification can be used to enhance existing physical credentials with -digital signatures via [=verifiable credentials=]. -
- --This section provides an example on how the technology in this specification -can be utilized to secure the optical barcode on a driver's license that -uses a PDF417 barcode. We start off with an example driver's license: -
- -
- -The back of the driver's license contains a PDF417 barcode: -
- -
- -The PDF417 data contains information that is secured using the algorithms -described in this specification. Namely, the PDF417 barcode contains a -verifiable credential of the following form. -
- -
-{
- "@context": [
- "https://www.w3.org/ns/credentials/v2",
- "https://w3id.org/vdl/v2",
- "https://w3id.org/vdl/utopia/v1"
- ],
- "type": [
- "VerifiableCredential",
- "OpticalBarcodeCredential"
- ],
- // the issuer value below is defined as a URL in the 'utopia/v1' context above
- "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",
- // the public key below is defined as a URL in the 'utopia/v1' context above
- "verificationMethod": "did:web:dmv.utopia.example#key-1",
- "proofPurpose": "assertionMethod",
- "proofValue": "z4peo48uwK2EF4Fta8P...HzQMDYJ34r9gL"
- }
-}
-
-
- -The verifiable credential above is then compressed using [[CBOR-LD]] -to the following output (in CBOR Diagnostic Notation): -
- -
-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
- }
-}
-
-
- -This section provides an example on how the technology in this specification -can be utilized to secure the machine-readable zone on an employment -authorization document that uses a machine-readable zone (MRZ) on the back of -the card. We start off with an example employment authorization document: -
- -
- -The back of the employment authorization document contains a machine-readable -zone (MRZ) containing information designed to be read through optical character -recognition: -
- -
- -The MRZ data contains information that is secured using the algorithms -described in this specification. Namely, the QR Code on the front of the -card contains a verifiable credential of the following form, which secures -the information on the back of the card. -
- -
-{
- "@context": [
- "https://www.w3.org/ns/credentials/v2",
- "https://w3id.org/citizenship/v2",
- "https://w3id.org/citizenship/utopia/v1"
- ],
- "type": [
- "VerifiableCredential",
- "OpticalBarcodeCredential"
- ],
- // the value below is defined as a URL in the 'utopia/v1' context above
- "issuer": "did:web:immigration.utopia.example",
- "credentialSubject": {
- "type": "MachineReadableZone",
- },
- "proof": {
- "type": "DataIntegrity",
- "cryptosuite": "ecdsa-xi-2023",
- // the value below is defined as a URL in the 'utopia/v1' context above
- "verificationMethod": "did:web:immigration.utopia.example#key-4"
- "proofPurpose": "assertionMethod",
- "proofValue": "z4peo48uwK2EF4Fta8P...HzQMDYJ34r9gL"
- }
-}
-
-
- -Readers might note that the credential above does not contain the optional -`credentialStatus` property. Not every optical barcode credential issuer will -have the requirement to have revocable optical barcode credentials. -
- --The verifiable credential above is then compressed using [[CBOR-LD]] -to the following output (in CBOR Diagnostic Notation): -
- -
-{
- 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
- }
-}
-
-
- -This section provides an example on how the technology in this specification can -be utilized to secure a birth certificate as a [=verifiable credential=], which -is then expressed as a QR Code on the printed paper document: -
- -
- -The QR Code encodes the following [=verifiable credential=]. The details of -the encoding are available as separate tabs below: -
- -
-{
- "@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"
- }]
- }
- }
-}
-
-
- -The following are the design goals of the technology in this specification: -
--Terminology used throughout this document is defined in the -Terminology section of the -[[[VC-DATA-MODEL-2.0]]] specification as well as the [[[VC-DATA-INTEGRITY]]] -specification. -
- --A conforming document is any concrete expression of the data model -that complies with the normative statements in this specification. Specifically, -all relevant normative statements in Sections - and -of this document MUST be enforced. -
- --A conforming processor is any algorithm realized -as software and/or hardware that generates or consumes a -conforming document. Conforming processors MUST produce errors when -non-conforming documents are consumed. -
- --This document contains examples of JSON and JSON-LD data. Some of these examples -are invalid JSON, as they include features such as inline comments (`//`) -explaining certain portions and ellipses (`...`) indicating the omission of -information that is irrelevant to the example. Such parts need to be -removed if implementers want to treat the examples as valid JSON or JSON-LD. -
--The following sections outline the data model that is used by this specification -to express [=verifiable credentials=] that secure optically printed information -such as barcodes and machine-readable zones on travel documents. -
- --An `OpticalBarcodeCredential` is used to secure the contents of an optical -barcode in a way that provides 1) authorship information , 2) tamper -resistance, and 3) optionally, revocation and suspension status. In other words, -the credential can tell you who issued the optical barcode, if the -optical barcode has been tampered with since it was first issued, and -whether or not the issuer of the optical barcode still warrants that -the document is still valid or not. These features provide significant -anti-fraud protections for physical documents. -
- --The `credentialSubject` of an `OpticalBarcodeCredential` is either of type -`AamvaDriversLicenseScannableInformation` or a `MachineReadableZone`. A -`AamvaDriversLicenseScannableInformation` signifies that -the verifiable credential secures the PDF417 barcode on the physical -document as well as the information expressed in the -verifiable credential. A `MachineReadableZone` signifies that -the verifiable credential secures the machine-readable zone on the -physical document as well as the information expressed in the -verifiable credential. -
- --If an `OpticalBarcodeCredential` is of type `AamvaDriversLicenseScannableInformation`, -there is a REQUIRED additional field `protectedComponentIndex` that contains information about which fields -in the PDF417 are digitally signed. `protectedComponentIndex` MUST be a three byte/24 bit value that is -multibase-base64url encoded for a total of 5 characters in the JSON-LD credential. There are 22 -mandatory fields in an AAMVA compliant driver's license PDF417 [[aamva-dl-id-card-design-standard]], -and the first 22 bits of the `protectedComponentIndex` value correspond to these fields. Each AAMVA mandatory -field begins with a three character element ID (e.g., `DBA` for document expiration date). To construct -a mapping between bits in the `protectedComponentIndex` value and these fields, sort these element IDs -according to Unicode code point order. Then, if a bit in position `i` of `protectedComponentIndex` is `1`, the -AAMVA mandatory field in position `i` of the sorted element IDs is protected by the digital signature. The last two -bits in `protectedComponentIndex` MUST be `0`. For more information, see Section [[[#create-opticaldatabytes]]]. -
- --In order to achieve as much compression as possible, it is RECOMMENDED that the -`issuer` and `verificationMethod` fields utilize terms from a JSON-LD Context, -which can then be compressed down to a few bytes due to CBOR-LD's semantic -compression mechanism. -
- --An example of an optical barcode credential that utilizes the properties -specified in this section is provided below: -
- -
-{
- "@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"
- }
-}
-
- -A `TerseBitstringStatusListEntry` is a compact representation -of a `BitstringStatusListEntry` as defined in the [[[VC-BITSTRING-STATUS-LIST]]] -specification. -
- --An object of type `TerseBitstringStatusListEntry` MUST have two additional properties: -
--To process a `TerseBitstringStatusListEntry`, apply the algorithm in Section -[[[#convert-status-list-entries]]] to convert it to a `BitstringStatusListEntry`, -then process it as in [[[VC-BITSTRING-STATUS-LIST]]]. -
-Implementers need to set a value |listLength| for the length of an individual status list. This then yields -a number of status lists |listCount| = 2^32 / |listLength| for a 32-bit `terseStatusListIndex`. -|listLength| is needed to convert from a `TerseBitstringStatusListEntry` to a `BitstringStatusListEntry`. -Noting that some values of |listLength| will harm the privacy-preserving properties of these status lists, -implementations MUST use |listLength| = 2^26 and |listCount| = 2^6. -
- --It is RECOMMENDED that implementers character-encode CBOR-LD encoded `AamvaDriversLicenseScannableInformation` -credentials as base64url before encoding them in a PDF417. -
--It is REQUIRED that implementers re-encode CBOR-LD encoded `MachineReadableZone` credentials -as base45-multibase with the string 'VC1-' prepended before encoding them in a QR code. -
--The following section describes algorithms for adding and verifying digital -proofs that protect optical information, such as barcodes and machine-readable -zones, on physical media, such as driver's licenses and travel documents. -
- --This section contains algorithms that are general to encoding and decoding -[=verifiable credentials=]. -
- --This specification requires that an application-specific compression table is -provided to a CBOR-LD processor when encoding and decoding -verifiable credentials. A registry for all context URLs for various -issuers is -provided as a comma-separated value file and can be updated and modified via - -change requests to the file on an append-only and first-come-first-served -basis. Implementations SHOULD retrieve and utilize the latest file on a monthly -basis to ensure that compression and decompression supports the latest values. -
- --The following algorithm specifies how to encode a [=verifiable credential=] into -a text string that can be expressed in a QR Code. Required inputs are a -[=verifiable credential=] ([=map=] |inputDocument|), and a set of options -([=map=] |options|). The output is an encoded [=verifiable credential=] -([=string=]) or an error. Whenever this algorithm encodes strings, it MUST use -UTF-8 encoding. -
- --The following algorithm specifies how to decode a [=verifiable credential=] that -has been encoded into a QR Code. Required inputs are a text string ([=string=] -|inputDocument|), and a set of options ([=map=] |options|). The output is a -[=verifiable credential=] ([=map=]) or an error. Whenever this algorithm encodes -strings, it MUST use UTF-8 encoding. -
- --This section contains algorithms that are specific to encoding and decoding -[=verifiable credentials=] that have a `type` of `OpticalBarcodeCredential`. -
- --The algorithm in this section is used to convert the -`TerseBitstringStatusListEntry` to a `BitstringStatusListEntry`, which is used -after verification has been performed on the verifiable credential, -during the validation process. -
- --After verifiable credential verification has been performed, the -algorithm takes an `OpticalBarcodeCredential` verifiable credential -([=struct=] |vc|), an integer |listLength| containing the number of entries -in the `BitstringStatusListCredential` associated with |vc|, and a string -|statusPurpose| (e.g., 'revocation', 'suspension'...) as input and returns -a 'BitstringStatusListEntry' object. -
- --|result| can be used as input to the - -validation algorithm in the [[[VC-BITSTRING-STATUS-LIST]]] specification. -
- --Implementers are advised that not all issuers will publish status -list information for their verifiable credentials. Some issuers -might require authorization before allowing a verifier to access a -status list credential. -
- --The `ecdsa-xi-2023` cryptosuite is effectively the `ecdsa-rdfc-2019` -algorithm [[VC-DI-ECDSA]] with an added step that takes some "extra information" -(xi) as input, such as the original optical barcode data, and includes that data -in the information that is protected by the digital signature. The algorithms in -this section detail how such a signature is created and verified. -
- --To generate a proof, the algorithm in - -Section 4.1: Add Proof in the Data Integrity -[[VC-DATA-INTEGRITY]] specification MUST be executed. -For that algorithm, the cryptographic suite specific - -transformation algorithm is defined in the - -Transformation (ecdsa-rdfc-2019) section of the [[[VC-DI-ECDSA]]], the - -hashing algorithm is defined in Section -, and the - -proof serialization algorithm is defined in the - -Proof Serialization (ecdsa-rdfc-2019) section of the [[[VC-DI-ECDSA]]]. -
--To verify a proof, the algorithm in - -Section 4.2: Verify Proof in the Data Integrity [[VC-DATA-INTEGRITY]] -specification MUST be executed. For that algorithm, the cryptographic suite -specific - -transformation algorithm is defined in the - -Transformation (ecdsa-rdfc-2019) section of the [[[VC-DI-ECDSA]]], the - -hashing algorithm is defined in -Section , and the - -proof verification algorithm is defined in the - -Proof Verification (ecdsa-rdfc-2019) section of the [[[VC-DI-ECDSA]]]. -
--The hashing algorithm is what is defined in the - -Hashing (ecdsa-rdfc-2019) section of the [[[VC-DI-ECDSA]]] specification -with the addition of the hashing of the optical data, as described below. It is -presumed that the implementation makes the machine-readable optical data (PDF417 -or MRZ data) available to this hashing algorithm. -
- --The required inputs to this algorithm are a transformed data document -(transformedDocument), a canonical proof configuration -(canonicalProofConfig), and the optical data -(opticalDataBytes). A single hash data value represented as -series of bytes is produced as output. -
- --The hashing algorithm is what is defined in the - -Hashing (ecdsa-rdfc-2019) section of the [[[VC-DI-ECDSA]]] with step 3 -replaced with the following two steps: -
- --The proof configuration algorithm is what is defined in the - -Proof Configuration (ecdsa-rdfc-2019) section of the [[[VC-DI-ECDSA]]] with -step 4 replaced with the following step: -
- --Before reading this section, readers are urged to familiarize themselves -with general security advice provided in the - -Security Considerations section of the Data Integrity specification as -well as the specific security advice provided in the - -Security Considerations section of the ECDSA Cryptosuites specification. -
- --In the following sections, we review these important points and direct -the reader to additional information. -
- --One attack vector against `OpticalBarcodeCredentials` involves duplicating -an optical barcode containing a digital signature for use on a fraudulent document. -While a duplicated barcode will pass signature validation like the original, this attack -is mitigated by the document verifier checking the following three things: the signed data -matches the data visible on the document, the signed data matches the physical attributes of -the user, and the visible data matches the physical attributes of the user. When these -three are all equivalent, the only way the `OpticalBarcodeCredential` could be a -duplicate is if the fraudulent document creator had access to a real -`OpticalBarcodeCredential` where the signed physical attributes fully overlapped -with those of the user of the fraudulent document. The low likelihood of an undetected -stolen `OpticalBarcodeCredential` existing that completely matches the appearance -of an arbitrary person makes this attack unlikely to succeed. -
--It is possible that in some cases the digital signature cannot be created -over the entirety of the existing optical data. For example, consider a case -where a serial number is injected by a physical credential manufacturer such -that it is not known to the issuer at signature time. In this case, the verifier -will assume that any data not digitally signed could have been changed in -the optical barcode without impacting the `OpticalBarcodeCredential's` -ability to successfully validate. -
--When checking that data from the optical barcode matches the data visible on the -document as well as the characteristics of the document holder, implementers -are advised to only use the fields that are digitally signed. [=Verifiers=] are -advised to only use fields protected by the digital signature, no matter how -commonly the other fields are used for fraud detection on unsigned documents. For -example, if eye color and hair color are protected by the signature, but the -[=holder=]'s portrait is not, [=verifiers=] are advised to emphasize the eye -color and hair color when attempting to detect fraud over the portrait. -
--Implementers of software used by [=verifiers=] are advised to only display card data -that has been secured via digital signature during the verification process. Displaying -unsigned data, which could have been tampered with, could interfere with fraud detection. -
--[=Verifiers=] are advised to always use trusted programs and interfaces to check the validity -of the `OpticalBarcodeCredential`. Use of untrusted software to verify a document -could result in a fraudulent credential being accepted, or a genuine credential being stolen. -
--Before reading this section, readers are urged to familiarize themselves -with general security advice provided in the - -Security Considerations section of the Data Integrity specification as -well as the specific security advice provided in the - -Security Considerations section of the ECDSA Cryptosuites specification. -
- --The following section describes privacy considerations that developers -implementing this specification should be aware of in order to avoid violating -privacy assumptions. -
- --This section contains examples of Verifiable Credential Barcodes as well -as step-by-step processes for how they are generated and how they are verified. -
--In this section we will analyze two running examples: a VCB securing -the MRZ of a Utopia Employment Authorization Document, and a VCB securing -the PDF417 of a Utopia Driver's License. -
--We start with the data that will be signed by the VCB (i.e., mandatory AAMVA fields -from a 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 --
-Assume for simplicity that the only data in the PDF417 that you want to sign is first -name (`DAC`), last name (`DCS`), and license number (`DAQ`). The bitstring value for use in -`protectedComponentIndex` is then |100000100000000000100000|, and the value of -`protectedComponentIndex` is `"uggAg"`. Applying -, we get -
--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] --
-We can now use this hash value with - to sign the VC. -Executing with a -`BitstringStatusListCredential`, we get the following 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"
- }
-}
-
- -We can now apply CBOR-LD compression to this VC. Here, we use the newest -version of CBOR-LD; however, at the end of the section, we provide VCBs -encoded using older versions of CBOR-LD for interoperability testing -with CBOR-LD implementations that are not up to date. -
--For this specification, we have reserved the CBOR-LD registry entry -with value `100` (i.e., these payloads will begin with tag `0x0664`). The parameters -to encode using CBOR-LD, which can be found in the registry in the CBOR-LD -specification, are then as follows: -
-
-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
- }
-}
-
- -The term-to-ID mapping that should result from processing the contexts and assigning -integer values to context terms is as follows: -
-
-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
-}
-
- -For more information on the above, see . -
--This results in the following encoded credential: -
-
-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
- }
- }
-])
-
- -Encoding the Driver's License CBOR-LD as base64url and inserting the result into the -PDF417 bytes in the 'ZZA' field in the 'ZZ' subfile: -
--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) --
-The above can now be turned into a barcode: -
-
- -We start with the data that will be signed by the VCB (i.e an MRZ): -
--IAUTO0000007010SRC0000000701<< -8804192M2601058NOT<<<<<<<<<<<5 -SMITH<<JOHN<<<<<<<<<<<<<<<<<<< --
-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] --
-We can now use this hash value with - to sign the VC. -Executing without -adding status, we get the following 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"
- }
-}
-
- -We can now apply CBOR-LD compression to this VC. Here we use the newest -version of CBOR-LD, however at the end of the section we provide VCBs -encoded using older versions of CBOR-LD for interoperability testing -with CBOR-LD implementations that are not up to date. -
--For this specficiation, we have reserved the CBOR-LD registry entry -with value `100` (i.e., these payloads will begin with tag `0x0664`). The parameters -to encode using CBOR-LD, which can be found in the registry in the CBOR-LD -specification, are then as follows: -
-
-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
- }
-}
-
- -The term-to-ID mapping that should result from processing the contexts and assigning -integer values to context terms is as follows: -
-
-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
-}
-
- -For more information on the above, see . -
--Compression then results in the following encoded credential: -
-
-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
- }
- }
-])
-
- -Encoding the EAD CBOR-LD as base45-multibase and prepending 'VC1-': -
--VC1-R0OR*W3Y33V%K PG88G3A3B60A8G1534KG$-ENXKWQN053653Y53I53 539*K0XJ.TDYOQJ63P63L6337BPMFPCP7EH2R12YH%%EXU4$08E-D8D86F8E2HX:T8Z8/ 1TZEH.QBA03Q5W.I0N6FBF4E3:SOQU8. A3MSELNHFU0GCVVBP6LU9T%ES-3 --
-The above can now be turned into a QR code: -
-
- -For use with the following MRZ: -
-
- -We now apply the reverse process to verify. -
--We first read the data from the 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\rZZZZA2QZkpgGDGYAAGYABGYACGJ2CGHYYpBi4oxicGKYYzhiyGNAa5ZIggRi6ohicGKAYqER1ggAgGL4YqhjApRicGGwY1gQY4BjmGOJYQXq3wuVrSeLM5iGEziaBjhWosXMWRAG107uT_9bSteuPasCXFQKuPdSdF-xmUoFkA0yRJoW4ERvATNyewT263ZHMGOQYrA==\r) -- -
-We extract the data in field 'ZZA' in subfile 'ZZ', undoing the base encoding: -
--d90664a60183198000198001198002189d82187618a418b8a3189c18a618ce18b218d01ae592208118baa2189c18a018a8447582002018be18aa18c0a5189c186c18d60418e018e618e258417ab7c2e56b49e2cce62184ce26818e15a8b173164401b5d3bb93ffd6d2b5eb8f6ac0971502ae3dd49d17ec66528164034c912685b8111bc04cdc9ec13dbadd91cc18e418ac --
-We now decompress with CBOR-LD to get the original JSON-LD VC to be -verified. Again, the parameters are associated with CBOR-LD -registry entry `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
- }
-}
-
- -The ID-to-term mapping that should result from processing the contexts and assigning -integer values to context terms is as follows. Note that this is the inverse of the map -constructed during compression. -
-
-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'
-}
-
- -For more information on the above, see . -
--Decompression then yields the following credential: -
-
-{
- "@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"
- }
-}
-
- -We apply -to create the |opticalDataBytes| that `ecdsa-xi-2023` requires, using the -scanned PDF417 and `protectedComponentIndex` as input. -
--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] -- - -
-The last step is to check the status information on the Driver's License -credential. We apply -to convert the `TerseBitstringStatusListEntry` into a `BitstringStatusListEntry`. -Here we check two status types, 'revocation' and 'suspension', passing those -strings as values of |statusPurpose|. -
-
-{
- type: 'BitstringStatusListEntry',
- statusListCredential: 'https://sandbox.platform.veres.dev/statuses/z19rJ4oGrbFCqf3cNTVDHSbNd/status-lists/revocation/29385',
- statusListIndex: 8321,
- statusPurpose: 'revocation'
-}
-
-
-{
- type: 'BitstringStatusListEntry',
- statusListCredential: 'https://sandbox.platform.veres.dev/statuses/z19rJ4oGrbFCqf3cNTVDHSbNd/status-lists/suspension/29385',
- statusListIndex: 8321,
- statusPurpose: 'suspension'
-}
-
- -These can then be validated as in the - Bitstring Status List v1.0: Validate Algorithm. -
--We first read the data from the QR code: -
--VC1-RSJRPWCR803A3P0098G3A3-B02-J743853U53KGK0XJ6MKJ1OI0M.FO053.33963DN04$RAQS+4SMC8C3KM7VX4VAPL9%EILI:I1O$D:23%GJ0OUCPS0H8D2FB9D5G00U39.PXG49%SOGGB*K$Z6%GUSCLWEJ8%B95MOD0P NG-I:V8N63K53 --
-We extract the data after 'VC1-' undoing the base encoding: -
--d90664a50183198000198001198002189d82187618a418baa1189c18a218be18ae18c0a5189c186c18d20418dc18e218de58417a9ec7f688f60caa8c757592250b3f6d6e18419941f186e1ed4245770e687502d51d01cd2c2295e4338178a51a35c2f044a85598e15db9aef00261bc5c95a744e718e018b0 --
-We now decompress with CBOR-LD to get the original JSON-LD VC to be -verified. Again, the parameters are associated with CBOR-LD -registry entry `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
- }
-}
-
- -The ID-to-term mapping that should result from processing the contexts and assigning -integer values to context terms is as follows. Note that this is the inverse of the map -constructed during compression. -
-
-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'
-}
-
- -For more information on the above, see . -
--Decompression then yields the following credential: -
-
-{
- "@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"
- }
-}
-
- -We apply to create -the |opticalDataBytes| that `ecdsa-xi-2023` requires,using the MRZ -on the EAD as input for the EAD: -
--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] -- -
-When building maps from context terms to CBOR-LD integers, note that -some contexts include other contexts inside of them, nested under particular -types of objects. These nested contexts are called "type-scoped contexts" and they only -become active when the associated type is used in the data. This is important for term ID -assignment because the terms in a context are only assigned IDs once that context becomes -active. In these test vectors, this is why the maps created for the Driver's License and -the Employment Authorization Document are different even though the two credentials use -identical contexts. -
--In addition, note that odd numbers are used in CBOR-LD to express terms when the associated -value is plural. For example, in the CBOR-LD term-to-ID and ID-to-term maps above, "type" is -mapped to 156, but in places where multiple types are expressed in a VC, 157 is used instead. -
--appContextMap: -[['https://www.w3.org/ns/credentials/v2', 32768], -['https://w3id.org/vc-barcodes/v1', 32769], -['https://w3id.org/utopia/v2', 32770]] --
-
- - For use with the following MRZ: -
-
-
-
- - For use with the following MRZ: -
-
- -This section contains the substantive changes that have been made to this -specification over time. -
- --The content for this specification will be filled in after the -standards-track process has been started. -
- -+This specification describes a mechanism to protect optical barcodes, +such as those found on driver's licenses (PDF417) and travel documents (MRZ), +using Verifiable Credentials [[VC-DATA-MODEL-2.0]]. The Verifiable Credential +representations are compact enough such that they fit in under 150 bytes and +can thus be integrated with traditional two-dimensional barcodes that are +printed on physical cards using standard printing processes. +
++Physical credentials, such as driver's licenses, passports, and travel +credentials often include machine-readable data that can be used to quickly read +the information from the document. This information is encoded in formats such +as PDF417 [[ISO15438-2015]], machine-readable zone (MRZ) [[ICAO9303-3]], and +other optically scannable codes that are formatted in one-dimensional or +two-dimensional "bars"; thus the term "barcode". This information is often +not protected from tampering and the readily available barcode generation and +scanning libraries mean that it is fairly trivial for anyone to generate these +barcodes. +
++It is, therefore, useful for an issuer of these barcodes to protect +the information contained within the barcode as well as the entity that +generated the barcode. +
++The [[[VC-DATA-MODEL-2.0]]] specification provides a global standard for +expressing credential information, such as those in a driver's license or +travel document. The [[[VC-DATA-INTEGRITY]]] specification provides a global +standard for securing credential information. These two specifications, when +combined, provide a means of protecting credentials from tampering, +expressing authorship of the credential, and providing the current status of +a credential in a privacy-protecting manner. These data formats, however, tend +to be too large to express in an optical barcode. +
++The [[[CBOR-LD]]] specification provides a means of compressing secured +verifiable credentials to the point at which it becomes feasible to +express the information as an optical barcode, or embedded within an optical +barcode. +
++This specification describes a mechanism to protect optical barcodes, +such as those found on driver's licenses (PDF417) and travel documents (MRZ), +by using a verifiable credential [[VC-DATA-MODEL-2.0]] to express +information in the barcode or about other information in the barcode. +Next, this Verifiable Credential is secured using Data Integrity +[[VC-DATA-INTEGRITY]], and then compressed using CBOR-LD [[CBOR-LD]]. +
++There are two main mechanisms by which a Verifiable Credential can +be used to protect a barcode: +
+Both use cases achieve authenticity, integrity, and tamper resistance over the +data protected by the Verifiable Credential. Additionally, for use cases that +require it, these Verifiable Credentials can be revoked or suspended on a +per-barcode basis. +
++The following sections provide a few introductory examples of the ways this +specification can be used to enhance existing physical credentials with +digital signatures via [=verifiable credentials=]. +
+ ++This section provides an example on how the technology in this specification +can be utilized to secure the optical barcode on a driver's license that +uses a PDF417 barcode. We start off with an example driver's license: +
+ +
+ +The back of the driver's license contains a PDF417 barcode: +
+ +
+ +The PDF417 data contains information that is secured using the algorithms +described in this specification. Namely, the PDF417 barcode contains a +verifiable credential of the following form. +
+ +
+{
+ "@context": [
+ "https://www.w3.org/ns/credentials/v2",
+ "https://w3id.org/vdl/v2",
+ "https://w3id.org/vdl/utopia/v1"
+ ],
+ "type": [
+ "VerifiableCredential",
+ "OpticalBarcodeCredential"
+ ],
+ // the issuer value below is defined as a URL in the 'utopia/v1' context above
+ "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",
+ // the public key below is defined as a URL in the 'utopia/v1' context above
+ "verificationMethod": "did:web:dmv.utopia.example#key-1",
+ "proofPurpose": "assertionMethod",
+ "proofValue": "z4peo48uwK2EF4Fta8P...HzQMDYJ34r9gL"
+ }
+}
+
+
+ +The verifiable credential above is then compressed using [[CBOR-LD]] +to the following output (in CBOR Diagnostic Notation): +
+ +
+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
+ }
+}
+
+
+ +This section provides an example on how the technology in this specification +can be utilized to secure the machine-readable zone on an employment +authorization document that uses a machine-readable zone (MRZ) on the back of +the card. We start off with an example employment authorization document: +
+ +
+ +The back of the employment authorization document contains a machine-readable +zone (MRZ) containing information designed to be read through optical character +recognition: +
+ +
+ +The MRZ data contains information that is secured using the algorithms +described in this specification. Namely, the QR Code on the front of the +card contains a verifiable credential of the following form, which secures +the information on the back of the card. +
+ +
+{
+ "@context": [
+ "https://www.w3.org/ns/credentials/v2",
+ "https://w3id.org/citizenship/v2",
+ "https://w3id.org/citizenship/utopia/v1"
+ ],
+ "type": [
+ "VerifiableCredential",
+ "OpticalBarcodeCredential"
+ ],
+ // the value below is defined as a URL in the 'utopia/v1' context above
+ "issuer": "did:web:immigration.utopia.example",
+ "credentialSubject": {
+ "type": "MachineReadableZone",
+ },
+ "proof": {
+ "type": "DataIntegrity",
+ "cryptosuite": "ecdsa-xi-2023",
+ // the value below is defined as a URL in the 'utopia/v1' context above
+ "verificationMethod": "did:web:immigration.utopia.example#key-4"
+ "proofPurpose": "assertionMethod",
+ "proofValue": "z4peo48uwK2EF4Fta8P...HzQMDYJ34r9gL"
+ }
+}
+
+
+ +Readers might note that the credential above does not contain the optional +`credentialStatus` property. Not every optical barcode credential issuer will +have the requirement to have revocable optical barcode credentials. +
+ ++The verifiable credential above is then compressed using [[CBOR-LD]] +to the following output (in CBOR Diagnostic Notation): +
+ +
+{
+ 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
+ }
+}
+
+
+ +This section provides an example on how the technology in this specification can +be utilized to secure a birth certificate as a [=verifiable credential=], which +is then expressed as a QR Code on the printed paper document: +
+ +
+ +The QR Code encodes the following [=verifiable credential=]. The details of +the encoding are available as separate tabs below: +
+ +
+{
+ "@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"
+ }]
+ }
+ }
+}
+
+
+ +The following are the design goals of the technology in this specification: +
++Terminology used throughout this document is defined in the +Terminology section of the +[[[VC-DATA-MODEL-2.0]]] specification as well as the [[[VC-DATA-INTEGRITY]]] +specification. +
+ ++A conforming document is any concrete expression of the data model +that complies with the normative statements in this specification. Specifically, +all relevant normative statements in Sections + and +of this document MUST be enforced. +
+ ++A conforming processor is any algorithm realized +as software and/or hardware that generates or consumes a +conforming document. Conforming processors MUST produce errors when +non-conforming documents are consumed. +
+ ++This document contains examples of JSON and JSON-LD data. Some of these examples +are invalid JSON, as they include features such as inline comments (`//`) +explaining certain portions and ellipses (`...`) indicating the omission of +information that is irrelevant to the example. Such parts need to be +removed if implementers want to treat the examples as valid JSON or JSON-LD. +
++The following sections outline the data model that is used by this specification +to express [=verifiable credentials=] that secure optically printed information +such as barcodes and machine-readable zones on travel documents. +
+ ++An `OpticalBarcodeCredential` is used to secure the contents of an optical +barcode in a way that provides 1) authorship information , 2) tamper +resistance, and 3) optionally, revocation and suspension status. In other words, +the credential can tell you who issued the optical barcode, if the +optical barcode has been tampered with since it was first issued, and +whether or not the issuer of the optical barcode still warrants that +the document is still valid or not. These features provide significant +anti-fraud protections for physical documents. +
+ ++The `credentialSubject` of an `OpticalBarcodeCredential` is either of type +`AamvaDriversLicenseScannableInformation` or a `MachineReadableZone`. A +`AamvaDriversLicenseScannableInformation` signifies that +the verifiable credential secures the PDF417 barcode on the physical +document as well as the information expressed in the +verifiable credential. A `MachineReadableZone` signifies that +the verifiable credential secures the machine-readable zone on the +physical document as well as the information expressed in the +verifiable credential. +
+ ++If an `OpticalBarcodeCredential` is of type `AamvaDriversLicenseScannableInformation`, +there is a REQUIRED additional field `protectedComponentIndex` that contains information about which fields +in the PDF417 are digitally signed. `protectedComponentIndex` MUST be a three byte/24 bit value that is +multibase-base64url encoded for a total of 5 characters in the JSON-LD credential. There are 22 +mandatory fields in an AAMVA compliant driver's license PDF417 [[aamva-dl-id-card-design-standard]], +and the first 22 bits of the `protectedComponentIndex` value correspond to these fields. Each AAMVA mandatory +field begins with a three character element ID (e.g., `DBA` for document expiration date). To construct +a mapping between bits in the `protectedComponentIndex` value and these fields, sort these element IDs +according to Unicode code point order. Then, if a bit in position `i` of `protectedComponentIndex` is `1`, the +AAMVA mandatory field in position `i` of the sorted element IDs is protected by the digital signature. The last two +bits in `protectedComponentIndex` MUST be `0`. For more information, see Section [[[#create-opticaldatabytes]]]. +
+ ++In order to achieve as much compression as possible, it is RECOMMENDED that the +`issuer` and `verificationMethod` fields utilize terms from a JSON-LD Context, +which can then be compressed down to a few bytes due to CBOR-LD's semantic +compression mechanism. +
+ ++An example of an optical barcode credential that utilizes the properties +specified in this section is provided below: +
+ +
+{
+ "@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"
+ }
+}
+
+ +A `TerseBitstringStatusListEntry` is a compact representation +of a `BitstringStatusListEntry` as defined in the [[[VC-BITSTRING-STATUS-LIST]]] +specification. +
+ ++An object of type `TerseBitstringStatusListEntry` MUST have two additional properties: +
++To process a `TerseBitstringStatusListEntry`, apply the algorithm in Section +[[[#convert-status-list-entries]]] to convert it to a `BitstringStatusListEntry`, +then process it as in [[[VC-BITSTRING-STATUS-LIST]]]. +
+Implementers need to set a value |listLength| for the length of an individual status list. This then yields +a number of status lists |listCount| = 2^32 / |listLength| for a 32-bit `terseStatusListIndex`. +|listLength| is needed to convert from a `TerseBitstringStatusListEntry` to a `BitstringStatusListEntry`. +Noting that some values of |listLength| will harm the privacy-preserving properties of these status lists, +implementations MUST use |listLength| = 2^26 and |listCount| = 2^6. +
+ ++It is RECOMMENDED that implementers character-encode CBOR-LD encoded `AamvaDriversLicenseScannableInformation` +credentials as base64url before encoding them in a PDF417. +
++It is REQUIRED that implementers re-encode CBOR-LD encoded `MachineReadableZone` credentials +as base45-multibase with the string 'VC1-' prepended before encoding them in a QR code. +
++The following section describes algorithms for adding and verifying digital +proofs that protect optical information, such as barcodes and machine-readable +zones, on physical media, such as driver's licenses and travel documents. +
+ ++This section contains algorithms that are general to encoding and decoding +[=verifiable credentials=]. +
+ ++This specification requires that an application-specific compression table is +provided to a CBOR-LD processor when encoding and decoding +verifiable credentials. A registry for all context URLs for various +issuers is +provided as a comma-separated value file and can be updated and modified via + +change requests to the file on an append-only and first-come-first-served +basis. Implementations SHOULD retrieve and utilize the latest file on a monthly +basis to ensure that compression and decompression supports the latest values. +
+ ++The following algorithm specifies how to encode a [=verifiable credential=] into +a text string that can be expressed in a QR Code. Required inputs are a +[=verifiable credential=] ([=map=] |inputDocument|), and a set of options +([=map=] |options|). The output is an encoded [=verifiable credential=] +([=string=]) or an error. Whenever this algorithm encodes strings, it MUST use +UTF-8 encoding. +
+ ++The following algorithm specifies how to decode a [=verifiable credential=] that +has been encoded into a QR Code. Required inputs are a text string ([=string=] +|inputDocument|), and a set of options ([=map=] |options|). The output is a +[=verifiable credential=] ([=map=]) or an error. Whenever this algorithm encodes +strings, it MUST use UTF-8 encoding. +
+ ++This section contains algorithms that are specific to encoding and decoding +[=verifiable credentials=] that have a `type` of `OpticalBarcodeCredential`. +
+ ++The algorithm in this section is used to convert the +`TerseBitstringStatusListEntry` to a `BitstringStatusListEntry`, which is used +after verification has been performed on the verifiable credential, +during the validation process. +
+ ++After verifiable credential verification has been performed, the +algorithm takes an `OpticalBarcodeCredential` verifiable credential +([=struct=] |vc|), an integer |listLength| containing the number of entries +in the `BitstringStatusListCredential` associated with |vc|, and a string +|statusPurpose| (e.g., 'revocation', 'suspension'...) as input and returns +a 'BitstringStatusListEntry' object. +
+ ++|result| can be used as input to the + +validation algorithm in the [[[VC-BITSTRING-STATUS-LIST]]] specification. +
+ ++Implementers are advised that not all issuers will publish status +list information for their verifiable credentials. Some issuers +might require authorization before allowing a verifier to access a +status list credential. +
+ ++The `ecdsa-xi-2023` cryptosuite is effectively the `ecdsa-rdfc-2019` +algorithm [[VC-DI-ECDSA]] with an added step that takes some "extra information" +(xi) as input, such as the original optical barcode data, and includes that data +in the information that is protected by the digital signature. The algorithms in +this section detail how such a signature is created and verified. +
+ ++To generate a proof, the algorithm in + +Section 4.1: Add Proof in the Data Integrity +[[VC-DATA-INTEGRITY]] specification MUST be executed. +For that algorithm, the cryptographic suite specific + +transformation algorithm is defined in the + +Transformation (ecdsa-rdfc-2019) section of the [[[VC-DI-ECDSA]]], the + +hashing algorithm is defined in Section +, and the + +proof serialization algorithm is defined in the + +Proof Serialization (ecdsa-rdfc-2019) section of the [[[VC-DI-ECDSA]]]. +
++To verify a proof, the algorithm in + +Section 4.2: Verify Proof in the Data Integrity [[VC-DATA-INTEGRITY]] +specification MUST be executed. For that algorithm, the cryptographic suite +specific + +transformation algorithm is defined in the + +Transformation (ecdsa-rdfc-2019) section of the [[[VC-DI-ECDSA]]], the + +hashing algorithm is defined in +Section , and the + +proof verification algorithm is defined in the + +Proof Verification (ecdsa-rdfc-2019) section of the [[[VC-DI-ECDSA]]]. +
++The hashing algorithm is what is defined in the + +Hashing (ecdsa-rdfc-2019) section of the [[[VC-DI-ECDSA]]] specification +with the addition of the hashing of the optical data, as described below. It is +presumed that the implementation makes the machine-readable optical data (PDF417 +or MRZ data) available to this hashing algorithm. +
+ ++The required inputs to this algorithm are a transformed data document +(transformedDocument), a canonical proof configuration +(canonicalProofConfig), and the optical data +(opticalDataBytes). A single hash data value represented as +series of bytes is produced as output. +
+ ++The hashing algorithm is what is defined in the + +Hashing (ecdsa-rdfc-2019) section of the [[[VC-DI-ECDSA]]] with step 3 +replaced with the following two steps: +
+ ++The proof configuration algorithm is what is defined in the + +Proof Configuration (ecdsa-rdfc-2019) section of the [[[VC-DI-ECDSA]]] with +step 4 replaced with the following step: +
+ ++Before reading this section, readers are urged to familiarize themselves +with general security advice provided in the + +Security Considerations section of the Data Integrity specification as +well as the specific security advice provided in the + +Security Considerations section of the ECDSA Cryptosuites specification. +
+ ++In the following sections, we review these important points and direct +the reader to additional information. +
+ ++One attack vector against `OpticalBarcodeCredentials` involves duplicating +an optical barcode containing a digital signature for use on a fraudulent document. +While a duplicated barcode will pass signature validation like the original, this attack +is mitigated by the document verifier checking the following three things: the signed data +matches the data visible on the document, the signed data matches the physical attributes of +the user, and the visible data matches the physical attributes of the user. When these +three are all equivalent, the only way the `OpticalBarcodeCredential` could be a +duplicate is if the fraudulent document creator had access to a real +`OpticalBarcodeCredential` where the signed physical attributes fully overlapped +with those of the user of the fraudulent document. The low likelihood of an undetected +stolen `OpticalBarcodeCredential` existing that completely matches the appearance +of an arbitrary person makes this attack unlikely to succeed. +
++It is possible that in some cases the digital signature cannot be created +over the entirety of the existing optical data. For example, consider a case +where a serial number is injected by a physical credential manufacturer such +that it is not known to the issuer at signature time. In this case, the verifier +will assume that any data not digitally signed could have been changed in +the optical barcode without impacting the `OpticalBarcodeCredential's` +ability to successfully validate. +
++When checking that data from the optical barcode matches the data visible on the +document as well as the characteristics of the document holder, implementers +are advised to only use the fields that are digitally signed. [=Verifiers=] are +advised to only use fields protected by the digital signature, no matter how +commonly the other fields are used for fraud detection on unsigned documents. For +example, if eye color and hair color are protected by the signature, but the +[=holder=]'s portrait is not, [=verifiers=] are advised to emphasize the eye +color and hair color when attempting to detect fraud over the portrait. +
++Implementers of software used by [=verifiers=] are advised to only display card data +that has been secured via digital signature during the verification process. Displaying +unsigned data, which could have been tampered with, could interfere with fraud detection. +
++[=Verifiers=] are advised to always use trusted programs and interfaces to check the validity +of the `OpticalBarcodeCredential`. Use of untrusted software to verify a document +could result in a fraudulent credential being accepted, or a genuine credential being stolen. +
++Before reading this section, readers are urged to familiarize themselves +with general security advice provided in the + +Security Considerations section of the Data Integrity specification as +well as the specific security advice provided in the + +Security Considerations section of the ECDSA Cryptosuites specification. +
+ ++The following section describes privacy considerations that developers +implementing this specification should be aware of in order to avoid violating +privacy assumptions. +
+ ++This section contains examples of Verifiable Credential Barcodes as well +as step-by-step processes for how they are generated and how they are verified. +
++In this section we will analyze two running examples: a VCB securing +the MRZ of a Utopia Employment Authorization Document, and a VCB securing +the PDF417 of a Utopia Driver's License. +
++We start with the data that will be signed by the VCB (i.e., mandatory AAMVA fields +from a 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 ++
+Assume for simplicity that the only data in the PDF417 that you want to sign is first +name (`DAC`), last name (`DCS`), and license number (`DAQ`). The bitstring value for use in +`protectedComponentIndex` is then |100000100000000000100000|, and the value of +`protectedComponentIndex` is `"uggAg"`. Applying +, we get +
++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] ++
+We can now use this hash value with + to sign the VC. +Executing with a +`BitstringStatusListCredential`, we get the following 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"
+ }
+}
+
+ +We can now apply CBOR-LD compression to this VC. Here, we use the newest +version of CBOR-LD; however, at the end of the section, we provide VCBs +encoded using older versions of CBOR-LD for interoperability testing +with CBOR-LD implementations that are not up to date. +
++For this specification, we have reserved the CBOR-LD registry entry +with value `100` (i.e., these payloads will begin with tag `0x0664`). The parameters +to encode using CBOR-LD, which can be found in the registry in the CBOR-LD +specification, are then as follows: +
+
+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
+ }
+}
+
+ +The term-to-ID mapping that should result from processing the contexts and assigning +integer values to context terms is as follows: +
+
+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
+}
+
+ +For more information on the above, see . +
++This results in the following encoded credential: +
+
+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
+ }
+ }
+])
+
+ +Encoding the Driver's License CBOR-LD as base64url and inserting the result into the +PDF417 bytes in the 'ZZA' field in the 'ZZ' subfile: +
++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) ++
+The above can now be turned into a barcode: +
+
+ +We start with the data that will be signed by the VCB (i.e an MRZ): +
++IAUTO0000007010SRC0000000701<< +8804192M2601058NOT<<<<<<<<<<<5 +SMITH<<JOHN<<<<<<<<<<<<<<<<<<< ++
+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] ++
+We can now use this hash value with + to sign the VC. +Executing without +adding status, we get the following 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"
+ }
+}
+
+ +We can now apply CBOR-LD compression to this VC. Here we use the newest +version of CBOR-LD, however at the end of the section we provide VCBs +encoded using older versions of CBOR-LD for interoperability testing +with CBOR-LD implementations that are not up to date. +
++For this specficiation, we have reserved the CBOR-LD registry entry +with value `100` (i.e., these payloads will begin with tag `0x0664`). The parameters +to encode using CBOR-LD, which can be found in the registry in the CBOR-LD +specification, are then as follows: +
+
+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
+ }
+}
+
+ +The term-to-ID mapping that should result from processing the contexts and assigning +integer values to context terms is as follows: +
+
+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
+}
+
+ +For more information on the above, see . +
++Compression then results in the following encoded credential: +
+
+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
+ }
+ }
+])
+
+ +Encoding the EAD CBOR-LD as base45-multibase and prepending 'VC1-': +
++VC1-R0OR*W3Y33V%K PG88G3A3B60A8G1534KG$-ENXKWQN053653Y53I53 539*K0XJ.TDYOQJ63P63L6337BPMFPCP7EH2R12YH%%EXU4$08E-D8D86F8E2HX:T8Z8/ 1TZEH.QBA03Q5W.I0N6FBF4E3:SOQU8. A3MSELNHFU0GCVVBP6LU9T%ES-3 ++
+The above can now be turned into a QR code: +
+
+ +For use with the following MRZ: +
+
+ +We now apply the reverse process to verify. +
++We first read the data from the 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\rZZZZA2QZkpgGDGYAAGYABGYACGJ2CGHYYpBi4oxicGKYYzhiyGNAa5ZIggRi6ohicGKAYqER1ggAgGL4YqhjApRicGGwY1gQY4BjmGOJYQXq3wuVrSeLM5iGEziaBjhWosXMWRAG107uT_9bSteuPasCXFQKuPdSdF-xmUoFkA0yRJoW4ERvATNyewT263ZHMGOQYrA==\r) ++ +
+We extract the data in field 'ZZA' in subfile 'ZZ', undoing the base encoding: +
++d90664a60183198000198001198002189d82187618a418b8a3189c18a618ce18b218d01ae592208118baa2189c18a018a8447582002018be18aa18c0a5189c186c18d60418e018e618e258417ab7c2e56b49e2cce62184ce26818e15a8b173164401b5d3bb93ffd6d2b5eb8f6ac0971502ae3dd49d17ec66528164034c912685b8111bc04cdc9ec13dbadd91cc18e418ac ++
+We now decompress with CBOR-LD to get the original JSON-LD VC to be +verified. Again, the parameters are associated with CBOR-LD +registry entry `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
+ }
+}
+
+ +The ID-to-term mapping that should result from processing the contexts and assigning +integer values to context terms is as follows. Note that this is the inverse of the map +constructed during compression. +
+
+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'
+}
+
+ +For more information on the above, see . +
++Decompression then yields the following credential: +
+
+{
+ "@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"
+ }
+}
+
+ +We apply +to create the |opticalDataBytes| that `ecdsa-xi-2023` requires, using the +scanned PDF417 and `protectedComponentIndex` as input. +
++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] ++ + +
+The last step is to check the status information on the Driver's License +credential. We apply +to convert the `TerseBitstringStatusListEntry` into a `BitstringStatusListEntry`. +Here we check two status types, 'revocation' and 'suspension', passing those +strings as values of |statusPurpose|. +
+
+{
+ type: 'BitstringStatusListEntry',
+ statusListCredential: 'https://sandbox.platform.veres.dev/statuses/z19rJ4oGrbFCqf3cNTVDHSbNd/status-lists/revocation/29385',
+ statusListIndex: 8321,
+ statusPurpose: 'revocation'
+}
+
+
+{
+ type: 'BitstringStatusListEntry',
+ statusListCredential: 'https://sandbox.platform.veres.dev/statuses/z19rJ4oGrbFCqf3cNTVDHSbNd/status-lists/suspension/29385',
+ statusListIndex: 8321,
+ statusPurpose: 'suspension'
+}
+
+ +These can then be validated as in the + Bitstring Status List v1.0: Validate Algorithm. +
++We first read the data from the QR code: +
++VC1-RSJRPWCR803A3P0098G3A3-B02-J743853U53KGK0XJ6MKJ1OI0M.FO053.33963DN04$RAQS+4SMC8C3KM7VX4VAPL9%EILI:I1O$D:23%GJ0OUCPS0H8D2FB9D5G00U39.PXG49%SOGGB*K$Z6%GUSCLWEJ8%B95MOD0P NG-I:V8N63K53 ++
+We extract the data after 'VC1-' undoing the base encoding: +
++d90664a50183198000198001198002189d82187618a418baa1189c18a218be18ae18c0a5189c186c18d20418dc18e218de58417a9ec7f688f60caa8c757592250b3f6d6e18419941f186e1ed4245770e687502d51d01cd2c2295e4338178a51a35c2f044a85598e15db9aef00261bc5c95a744e718e018b0 ++
+We now decompress with CBOR-LD to get the original JSON-LD VC to be +verified. Again, the parameters are associated with CBOR-LD +registry entry `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
+ }
+}
+
+ +The ID-to-term mapping that should result from processing the contexts and assigning +integer values to context terms is as follows. Note that this is the inverse of the map +constructed during compression. +
+
+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'
+}
+
+ +For more information on the above, see . +
++Decompression then yields the following credential: +
+
+{
+ "@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"
+ }
+}
+
+ +We apply to create +the |opticalDataBytes| that `ecdsa-xi-2023` requires,using the MRZ +on the EAD as input for the EAD: +
++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] ++ +
+When building maps from context terms to CBOR-LD integers, note that +some contexts include other contexts inside of them, nested under particular +types of objects. These nested contexts are called "type-scoped contexts" and they only +become active when the associated type is used in the data. This is important for term ID +assignment because the terms in a context are only assigned IDs once that context becomes +active. In these test vectors, this is why the maps created for the Driver's License and +the Employment Authorization Document are different even though the two credentials use +identical contexts. +
++In addition, note that odd numbers are used in CBOR-LD to express terms when the associated +value is plural. For example, in the CBOR-LD term-to-ID and ID-to-term maps above, "type" is +mapped to 156, but in places where multiple types are expressed in a VC, 157 is used instead. +
++appContextMap: +[['https://www.w3.org/ns/credentials/v2', 32768], +['https://w3id.org/vc-barcodes/v1', 32769], +['https://w3id.org/utopia/v2', 32770]] ++
+
+ + For use with the following MRZ: +
+
+
+
+ + For use with the following MRZ: +
+
+ +This section contains the substantive changes that have been made to this +specification over time. +
+ ++The content for this specification will be filled in after the +standards-track process has been started. +
+ +