diff --git a/index.html b/index.html index a58ac1e..181703a 100644 --- a/index.html +++ b/index.html @@ -1,2480 +1,2495 @@ - - - - Verifiable Credential Barcodes v1.0 - - - - - - - - -
-

-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. -

- -
- -
-

Introduction

-

-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. -

- -
-

Introductory Examples

- -

-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=]. -

- -
-

Driver's License

- -

-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: -

- -
- Picture of the front of a driver's license issued by the state of Utopia which contains a picture of the individual that is the subject of the driver's license along with their attributes, such as name, address, height, weight, eye color, and driving privileges. -
- The front of a driver's license issued by the state of Utopia. -
-
- -

-The back of the driver's license contains a PDF417 barcode: -

- -
- Picture of the back of a driver's license issued by the state of Utopia, containing usage rules as well as a PDF417 barcode that encodes much of the information displayed on the front of the card. -
-A back of a driver's license issued by the state of Utopia. -
-
- -

-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
-  }
-}
-          
- -
- -
-

Employment Authorization

- -

-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: -

- -
- Picture of the front of an employment authorization document issued by the state of Utopia which contains a picture of the individual that is the subject of the document along with their attributes, such as name, address, height, weight, eye color, and employment privileges. -
-The front of an employment authorization document issued by the state of Utopia. -
-
- -

-The back of the employment authorization document contains a machine-readable -zone (MRZ) containing information designed to be read through optical character -recognition: -

- -
- Picture of the back of a employment authorization document issued by the state of Utopia, containing usage rules as well as machine-readable zone data that encodes much of the information displayed on the front of the card. -
-A back of an employment authorization document issued by the state of Utopia. -
-
- -

-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
-  }
-}
-          
- -
- -
-

Birth Certificate

- -

-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: -

- -
- A picture of the front of a birth certificate containing information such as the newborn's name, parent's names, information about the hospital, attendees, and person responsible for the registration. -
-The front of a birth certificate issued by a hospital in the state of Utopia. -
-
- -

-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"
-      }]
-    }
-  }
-}
-          
- -
- -
- -
-

Design Goals

-

-The following are the design goals of the technology in this specification: -

- -
- -
-

Terminology

- -

-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. -

- -
-
Unicode code point order
-
-This refers to determining the order of two Unicode strings (`A` and `B`), -using Unicode Codepoint Collation, -as defined in [[XPATH-FUNCTIONS]], -which defines a -total ordering -of strings comparing code points. -Note that for UTF-8 encoded strings, comparing the byte sequences gives the same result as code point order. -
-
- -
- -
-

-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. -

-
-
- -
-

Data Model

- -

-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. -

- -
-

OpticalBarcodeCredential

- -

-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"
-  }
-}
-        
-
- -
-

TerseBitstringStatusListEntry

- -

-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. -

- -
- -
-

Encoding to and from barcodes

-While the credentials in this specification use CBOR-LD to efficiently encode [=verifiable credentials=] -in a binary format, binary data is often inefficient or incompatible to turn into standard barcode -image formats directly. To that end, we provide requirements here for implementations. -

-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. -

-
- -
- -
-

Algorithms

- -

-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. -

- -
-

General Algorithms

- -

-This section contains algorithms that are general to encoding and decoding -[=verifiable credentials=]. -

- -
-

CBOR-LD Compression Tables

- -

-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. -

- -
- -
-

Encode VC to QR Code

- -

-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. -

- -
    -
  1. -Let |typeTable| be the value of |options|.|typeTable|. -
  2. -
  3. -Let |registryEntryId| be the value of |options|.|registryEntryId|. -
  4. -
  5. -Let |cborldDocument| be the result of the - -JSON-LD to CBOR-LD Compression Algorithm, passing |inputDocument|, -|typeTable|, and |registryEntryId| as inputs. If an encoding error occurs, an -error MUST be raised. -
  6. -
  7. -Let |base45Value| be the result of the -Base Encoding algorithm, passing -|cborldDocument| as |bytes|, the integer `45` as |targetBase|, and -`0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:` as the |baseAlphabet|. -
  8. -
  9. -Let |qrCodeText| be the result of concatenating the following values: `VC1-`, -`R` (the Multibase prefix for base45), and -|base45Value|. -
  10. -
  11. -Return |qrCodeText| as the encoded [=verifiable credential=], which can then be -provided to any QR Code library as text to be encoded as a QR Code image. -
  12. -
- -
- -
-

Decode QR Code to VC

- -

-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. -

- -
    -
  1. -Ensure that the |inputDocument| starts with the text `VC1-R`. If it does not an -error MUST be raised. -
  2. -
  3. -Let |base45Value| be |inputDocument| with the first five characters (`VC1-R`) -removed. -
  4. -
  5. -Let |cborldDocument| be the result of the -Base Decoding algorithm, passing -|base45Value| as |sourceEncoding|, the integer `45` as |sourceBase|, and -`0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:` as the |baseAlphabet|. -
  6. -
  7. -Let |jsonldDocument| be the result of - -CBOR-LD to JSON-LD Decompression Algorithm, passing |cborldDocument| as -the input. If a decoding error occurs, an error MUST be raised. -
  8. -
  9. -Return |jsonldDocument| as the decoded [=verifiable credential=]. -
  10. -
- -
- -
- - -
-

`OpticalBarcodeCredential` Algorithms

- -

-This section contains algorithms that are specific to encoding and decoding -[=verifiable credentials=] that have a `type` of `OpticalBarcodeCredential`. -

- -
-

Encode `OpticalBarcodeCredential`

- -
    -
  1. -Set |opticalData| to the data in the optical barcode to be secured. -
  2. -
  3. -Set |statusListEntryVerbose| to the `BitstringStatusListCredential` -(as defined in the [[[VC-BITSTRING-STATUS-LIST]]] specification) that the issuer -wishes to add to the `OpticalBarcodeCredential`. -
  4. -
  5. -Let |statusListEntryTerse| be an empty [=map=]. Set |statusListEntryTerse|.|type| to `TerseBitstringStatusListEntry` and |statusListEntryTerse|.|index| to the integer representation of |statusListEntryVerbose|.|statusListIndex|. -
  6. -
  7. -Set |issuerUrl| to the URL the issuer wishes to use for credential verification. -
  8. -
  9. -Set |unsignedStatus| to an `OpticalBarcodeCredential` with -|unsignedStatus|.|issuer| set to |issuerUrl| and |unsignedStatus|.|credentialStatus| -set to |statusListEntryTerse|. -
  10. -
  11. -Set |signedStatusVc| to the result of using the algorithm in - to sign |opticalData| -and |unsignedStatus|. -
  12. -
  13. -Encode |signedStatusVc| using CBOR-LD [[CBOR-LD]] and add it to the designated area of the |opticalData|. -
  14. -
  15. -Generate the machine-readable credential (MRZ or PDF417). -
  16. -
-
- -
-

Decode `OpticalBarcodeCredential`

- -
    -
  1. -Set |securedDocument| to the data in the PDF417 or MRZ. -
  2. -
  3. -Set |verificationResult| to the result of applying the algorithm in Section -[[[#verify-proof-ecdsa-xi-2023]]]to |securedDocument|. -
  4. -
  5. -Set |credential| to the `OpticalBarcodeCredential` in |securedDocument|. -
  6. -
  7. -Set |statusListEntry| to the result of applying the algorithm in Section -[[[#convert-status-list-entries]]] to |credential|. -
  8. -
  9. -Set |statusResult| to the result of applying the algorithm in - -Bitstring Status List v1.0: Validate Algorithm to |statusListEntry|. -
  10. -
  11. -Return (|validationResult|, |statusResult|). -
  12. -
-
- -
-

Convert Status List Entries

- -

-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. -

- -
    -
  1. -Set |result| to be an empty [=map=]. -
  2. -
  3. -Set |listIndex| to |vc|.|credentialStatus|.|terseStatusListIndex|/|listLength| rounded down -to the next lowest integer (i.e., apply the `floor()` operation). -
  4. -
  5. -Set |statusListIndex| to |vc|.|credentialStatus|.|terseStatusListIndex| % |listLength|. -
  6. -
  7. -Set |result|.|statusListCredential| to the concatenation of the following values: -|vc|.|credentialStatus|.|terseStatusListBaseUrl|, '/', |statusPurpose|, '/', |listIndex|. -
  8. -
  9. -Set |result|.|type| to 'BitstringStatusListEntry'. -
  10. -
  11. -Set |result|.|statusListIndex| to |statusListIndex|. -
  12. -
  13. -Set |result|.|statusPurpose| to |statusPurpose|. -
  14. -
  15. -Return |result|. -
  16. -
- -

-|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. -

- -
- -
-

ecdsa-xi-2023

- -

-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. -

- -
-

Add Proof (ecdsa-xi-2023)

- -

-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]]]. -

-
- -
-

Verify Proof (ecdsa-xi-2023)

- -

-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]]]. -

-
- -
-

Hashing (ecdsa-xi-2023)

- -

-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: -

- -
    -
  1. -Let opticalDataHash be the result of applying the same hash algorithm -that was applied to hashData to the opticalDataBytes -value. -
  2. -
  3. -Let hashData be the result of joining proofConfigHash (the -first hash), transformedDocumentHash (the second hash), and -opticalDataHash (the third hash). -
  4. -
- -
- -
-

Create opticalDataBytes

- -
-
`AamvaDriversLicenseScannableInformation` Credentials
-
    -
  1. -Set |dataToCanonicalize| to an empty array. -
  2. -
  3. -Set |bitfieldDecoded| to be first 22 bits of the length 24 bitstring resulting from decoding - `credentialSubject.protectedComponentIndex` from multibase-base64url to binary. -
  4. -
  5. -Set |fieldsAlphabetized| to be an array containing the 22 AAMVA mandatory PDF417 Element IDs - [[aamva-dl-id-card-design-standard]] sorted in Unicode code point order (i.e., ['DAC', 'DAD' ... 'DDG']). -
  6. -
  7. -For each bit with value `1` in |bitfieldDecoded|: -
      -
    1. -Set the string |fieldName| to |fieldsAlphabetized|[|i|], where |i| is the index of the bit in |bitfieldDecoded|. -
    2. -
    3. -Set the string |fieldData| to the data that will be in the PDF417 associated with that field name. -
    4. -
    5. -Concatenate |fieldData| to the end of |fieldName|, concatenate a newline character (`\n`, `U+000A`) to the end, -and append the result to |dataToCanonicalize|. -
    6. -
    -
  8. -
  9. -Set |canonicalizedData| to the result of sorting |dataToCanonicalize| in Unicode code point order and then applying a join operation -to create a single string from the array. -
  10. -
  11. -Hash |canonicalizedData| and return the result. -
  12. -
-
- -
-
`MachineReadableZone` Credentials
-
    -
  1. -Set |dataToCanonicalize| to an empty array. -
  2. -
  3. -For each line in the Machine Readable Zone on the credential: -
      -
    1. -Set |mrzLine| to a string containing the data in that line. -
    2. -
    3. -Append a newline character to the end of |mrzLine| and append |mrzLine| to |dataToCanonicalize|. -
    4. -
    -
  4. -
  5. -Set |canonicalizedData| to the result of ordering the elements of |dataToCanonicalize| to match the order they appear -on the credential and then applying a join operation to create a single string from the array. -
  6. -
  7. -Hash |canonicalizedData| and return the result. -
  8. -
-
-
-
-

Proof Configuration (ecdsa-xi-2023)

- -

-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: -

- -
    -
  1. -If options.type is not set to `DataIntegrityProof` and -proofConfig.cryptosuite is not set to `ecdsa-xi-2023`, an -`INVALID_PROOF_CONFIGURATION` error MUST be raised. -
  2. -
- -
-
-
-
- -
-

Security Considerations

- -

-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. -

- -
-

Optical Data Duplication

-

-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. -

-
-
-

Partially Signed Optical Data

-

-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. -

-
-
-

Safe Verification

-

-[=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. -

-
-
- -
-

Privacy Considerations

- -

-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. -

- -
-Add more privacy considerations including at least the following: - -
- -
- -
-

Test Vectors

-

-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. -

-
-

Creating VCBs

-
-

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
-          
-
-
-Creating `opticalDataBytes` -
- -

-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: -

-
-
-Example 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"
-  }
-}
-            
-
- -
-

CBOR-LD Compression and Encoding

-

-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: -

-
- A VCB from a Utopia driver's license. -
-A VCB from a Utopia driver's license. -
-
-
-
-
-

Utopia Employment Authorization Document

- -

-We start with the data that will be signed by the VCB (i.e an MRZ): -

-
-IAUTO0000007010SRC0000000701<<
-8804192M2601058NOT<<<<<<<<<<<5
-SMITH<<JOHN<<<<<<<<<<<<<<<<<<<
-          
-
-
-Creating `opticalDataBytes` -
-

-For the EAD, we apply : -

-
-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: -

-
-
-
-Example 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"
-  }
-}
-            
-
-
-

CBOR-LD Compression and Encoding

-

-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: -

-
-
-
Employment Authorization Document
-
- A VCB from a Utopia EAD. -
-A VCB from a Utopia EAD. -
-
-

-For use with the following MRZ: -

-
- An MRZ on a Utopia Employment Authorization Document. -
-An MRZ on a Utopia Employment Authorization Document. -
-
-
-
-
-
-

Verifying VCBs

-

-We now apply the reverse process to verify. -

-
-

Utopia Driver's License

-
-

Decoding and Decompressing

-

-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"
-  }
-}
-            
-
-
-

Verifying

-

-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]
-            
- -

-We then apply and - to verify -the credential. -

-
-
-

Status Checking

-

-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. -

-
-
-
-

Utopia Employment Authorization Document

-
-

Decoding and Decompressing

-

-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"
-  }
-}
-            
-
-
-

Verifying

-

-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]
-            
-

-We then apply and - to verify -the credential. -

-
-
-
-
-

-Implementation Notes -

-
-

-CBOR-LD -

-

-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. -

-
-
-
-

-Legacy CBOR-LD encoded credentials -

-This process is used to test whether a CBOR-LD implementation that is not fully -up to date has been used. - -
-

-CBOR-LD Version 6.X -

-The process remains -the same, with the exception of the CBOR-LD decoding step, for which the following |appContextMap| -should be used: -
-appContextMap:
-[['https://www.w3.org/ns/credentials/v2', 32768],
-['https://w3id.org/vc-barcodes/v1', 32769],
-['https://w3id.org/utopia/v2', 32770]]
-          
-
-

Utopia Driver's License

-
- A VCB from a Utopia driver's license encoded with legacy CBOR-LD. -
- A VCB from a Utopia driver's license encoded with legacy CBOR-LD. -
-
-
-
-
Utopia Employment Authorization Document
-
- A VCB from a Utopia EAD encoded with legacy CBOR-LD. -
- A VCB from a Utopia EAD encoded with legacy CBOR-LD. -
-
-

- For use with the following MRZ: -

-
- An MRZ on a Utopia Employment Authorization Document. -
- An MRZ on a Utopia Employment Authorization Document. -
-
-
-
-
-

-CBOR-LD Version 7.X -

-
-

Utopia Driver's License

-
- A VCB from a Utopia driver's license encoded with legacy CBOR-LD. -
- A VCB from a Utopia driver's license encoded with legacy CBOR-LD. -
-
-
-
-
Utopia Employment Authorization Document
-
- A VCB from a Utopia EAD encoded with legacy CBOR-LD. -
- A VCB from a Utopia EAD encoded with legacy CBOR-LD. -
-
-

- For use with the following MRZ: -

-
- An MRZ on a Utopia Employment Authorization Document. -
- An MRZ on a Utopia Employment Authorization Document. -
-
-
-
-
-
-
-

Revision History

-

-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. -

- -
- - - + + + + Verifiable Credential Barcodes v1.0 + + + + + + + + +
+

+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. +

+
+ +
+
+ +
+

Introduction

+

+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. +

+
+

Introductory Examples

+ +

+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=]. +

+ +
+

Driver's License

+ +

+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: +

+ +
+ Picture of the front of a driver's license issued by the state of Utopia which contains a picture of the individual that is the subject of the driver's license along with their attributes, such as name, address, height, weight, eye color, and driving privileges. +
+ The front of a driver's license issued by the state of Utopia. +
+
+ +

+The back of the driver's license contains a PDF417 barcode: +

+ +
+ Picture of the back of a driver's license issued by the state of Utopia, containing usage rules as well as a PDF417 barcode that encodes much of the information displayed on the front of the card. +
+A back of a driver's license issued by the state of Utopia. +
+
+ +

+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
+  }
+}
+          
+ +
+ +
+

Employment Authorization

+ +

+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: +

+ +
+ Picture of the front of an employment authorization document issued by the state of Utopia which contains a picture of the individual that is the subject of the document along with their attributes, such as name, address, height, weight, eye color, and employment privileges. +
+The front of an employment authorization document issued by the state of Utopia. +
+
+ +

+The back of the employment authorization document contains a machine-readable +zone (MRZ) containing information designed to be read through optical character +recognition: +

+ +
+ Picture of the back of a employment authorization document issued by the state of Utopia, containing usage rules as well as machine-readable zone data that encodes much of the information displayed on the front of the card. +
+A back of an employment authorization document issued by the state of Utopia. +
+
+ +

+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
+  }
+}
+          
+ +
+ +
+

Birth Certificate

+ +

+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: +

+ +
+ A picture of the front of a birth certificate containing information such as the newborn's name, parent's names, information about the hospital, attendees, and person responsible for the registration. +
+The front of a birth certificate issued by a hospital in the state of Utopia. +
+
+ +

+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"
+      }]
+    }
+  }
+}
+          
+ +
+ +
+ +
+

Design Goals

+

+The following are the design goals of the technology in this specification: +

+ +
+ +
+

Terminology

+ +

+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. +

+ +
+
Unicode code point order
+
+This refers to determining the order of two Unicode strings (`A` and `B`), +using Unicode Codepoint Collation, +as defined in [[XPATH-FUNCTIONS]], +which defines a +total ordering +of strings comparing code points. +Note that for UTF-8 encoded strings, comparing the byte sequences gives the same result as code point order. +
+
+ +
+ +
+

+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. +

+
+
+ +
+

Data Model

+ +

+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. +

+ +
+

OpticalBarcodeCredential

+ +

+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"
+  }
+}
+        
+
+ +
+

TerseBitstringStatusListEntry

+ +

+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. +

+ +
+ +
+

Encoding to and from barcodes

+While the credentials in this specification use CBOR-LD to efficiently encode [=verifiable credentials=] +in a binary format, binary data is often inefficient or incompatible to turn into standard barcode +image formats directly. To that end, we provide requirements here for implementations. +

+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. +

+
+ +
+ +
+

Algorithms

+ +

+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. +

+ +
+

General Algorithms

+ +

+This section contains algorithms that are general to encoding and decoding +[=verifiable credentials=]. +

+ +
+

CBOR-LD Compression Tables

+ +

+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. +

+ +
+ +
+

Encode VC to QR Code

+ +

+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. +

+ +
    +
  1. +Let |typeTable| be the value of |options|.|typeTable|. +
  2. +
  3. +Let |registryEntryId| be the value of |options|.|registryEntryId|. +
  4. +
  5. +Let |cborldDocument| be the result of the + +JSON-LD to CBOR-LD Compression Algorithm, passing |inputDocument|, +|typeTable|, and |registryEntryId| as inputs. If an encoding error occurs, an +error MUST be raised. +
  6. +
  7. +Let |base45Value| be the result of the +Base Encoding algorithm, passing +|cborldDocument| as |bytes|, the integer `45` as |targetBase|, and +`0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:` as the |baseAlphabet|. +
  8. +
  9. +Let |qrCodeText| be the result of concatenating the following values: `VC1-`, +`R` (the Multibase prefix for base45), and +|base45Value|. +
  10. +
  11. +Return |qrCodeText| as the encoded [=verifiable credential=], which can then be +provided to any QR Code library as text to be encoded as a QR Code image. +
  12. +
+ +
+ +
+

Decode QR Code to VC

+ +

+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. +

+ +
    +
  1. +Ensure that the |inputDocument| starts with the text `VC1-R`. If it does not an +error MUST be raised. +
  2. +
  3. +Let |base45Value| be |inputDocument| with the first five characters (`VC1-R`) +removed. +
  4. +
  5. +Let |cborldDocument| be the result of the +Base Decoding algorithm, passing +|base45Value| as |sourceEncoding|, the integer `45` as |sourceBase|, and +`0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:` as the |baseAlphabet|. +
  6. +
  7. +Let |jsonldDocument| be the result of + +CBOR-LD to JSON-LD Decompression Algorithm, passing |cborldDocument| as +the input. If a decoding error occurs, an error MUST be raised. +
  8. +
  9. +Return |jsonldDocument| as the decoded [=verifiable credential=]. +
  10. +
+ +
+ +
+ + +
+

`OpticalBarcodeCredential` Algorithms

+ +

+This section contains algorithms that are specific to encoding and decoding +[=verifiable credentials=] that have a `type` of `OpticalBarcodeCredential`. +

+ +
+

Encode `OpticalBarcodeCredential`

+ +
    +
  1. +Set |opticalData| to the data in the optical barcode to be secured. +
  2. +
  3. +Set |statusListEntryVerbose| to the `BitstringStatusListCredential` +(as defined in the [[[VC-BITSTRING-STATUS-LIST]]] specification) that the issuer +wishes to add to the `OpticalBarcodeCredential`. +
  4. +
  5. +Let |statusListEntryTerse| be an empty [=map=]. Set |statusListEntryTerse|.|type| to `TerseBitstringStatusListEntry` and |statusListEntryTerse|.|index| to the integer representation of |statusListEntryVerbose|.|statusListIndex|. +
  6. +
  7. +Set |issuerUrl| to the URL the issuer wishes to use for credential verification. +
  8. +
  9. +Set |unsignedStatus| to an `OpticalBarcodeCredential` with +|unsignedStatus|.|issuer| set to |issuerUrl| and |unsignedStatus|.|credentialStatus| +set to |statusListEntryTerse|. +
  10. +
  11. +Set |signedStatusVc| to the result of using the algorithm in + to sign |opticalData| +and |unsignedStatus|. +
  12. +
  13. +Encode |signedStatusVc| using CBOR-LD [[CBOR-LD]] and add it to the designated area of the |opticalData|. +
  14. +
  15. +Generate the machine-readable credential (MRZ or PDF417). +
  16. +
+
+ +
+

Decode `OpticalBarcodeCredential`

+ +
    +
  1. +Set |securedDocument| to the data in the PDF417 or MRZ. +
  2. +
  3. +Set |verificationResult| to the result of applying the algorithm in Section +[[[#verify-proof-ecdsa-xi-2023]]]to |securedDocument|. +
  4. +
  5. +Set |credential| to the `OpticalBarcodeCredential` in |securedDocument|. +
  6. +
  7. +Set |statusListEntry| to the result of applying the algorithm in Section +[[[#convert-status-list-entries]]] to |credential|. +
  8. +
  9. +Set |statusResult| to the result of applying the algorithm in + +Bitstring Status List v1.0: Validate Algorithm to |statusListEntry|. +
  10. +
  11. +Return (|validationResult|, |statusResult|). +
  12. +
+
+ +
+

Convert Status List Entries

+ +

+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. +

+ +
    +
  1. +Set |result| to be an empty [=map=]. +
  2. +
  3. +Set |listIndex| to |vc|.|credentialStatus|.|terseStatusListIndex|/|listLength| rounded down +to the next lowest integer (i.e., apply the `floor()` operation). +
  4. +
  5. +Set |statusListIndex| to |vc|.|credentialStatus|.|terseStatusListIndex| % |listLength|. +
  6. +
  7. +Set |result|.|statusListCredential| to the concatenation of the following values: +|vc|.|credentialStatus|.|terseStatusListBaseUrl|, '/', |statusPurpose|, '/', |listIndex|. +
  8. +
  9. +Set |result|.|type| to 'BitstringStatusListEntry'. +
  10. +
  11. +Set |result|.|statusListIndex| to |statusListIndex|. +
  12. +
  13. +Set |result|.|statusPurpose| to |statusPurpose|. +
  14. +
  15. +Return |result|. +
  16. +
+ +

+|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. +

+ +
+ +
+

ecdsa-xi-2023

+ +

+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. +

+ +
+

Add Proof (ecdsa-xi-2023)

+ +

+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]]]. +

+
+ +
+

Verify Proof (ecdsa-xi-2023)

+ +

+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]]]. +

+
+ +
+

Hashing (ecdsa-xi-2023)

+ +

+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: +

+ +
    +
  1. +Let opticalDataHash be the result of applying the same hash algorithm +that was applied to hashData to the opticalDataBytes +value. +
  2. +
  3. +Let hashData be the result of joining proofConfigHash (the +first hash), transformedDocumentHash (the second hash), and +opticalDataHash (the third hash). +
  4. +
+ +
+ +
+

Create opticalDataBytes

+ +
+
`AamvaDriversLicenseScannableInformation` Credentials
+
    +
  1. +Set |dataToCanonicalize| to an empty array. +
  2. +
  3. +Set |bitfieldDecoded| to be first 22 bits of the length 24 bitstring resulting from decoding + `credentialSubject.protectedComponentIndex` from multibase-base64url to binary. +
  4. +
  5. +Set |fieldsAlphabetized| to be an array containing the 22 AAMVA mandatory PDF417 Element IDs + [[aamva-dl-id-card-design-standard]] sorted in Unicode code point order (i.e., ['DAC', 'DAD' ... 'DDG']). +
  6. +
  7. +For each bit with value `1` in |bitfieldDecoded|: +
      +
    1. +Set the string |fieldName| to |fieldsAlphabetized|[|i|], where |i| is the index of the bit in |bitfieldDecoded|. +
    2. +
    3. +Set the string |fieldData| to the data that will be in the PDF417 associated with that field name. +
    4. +
    5. +Concatenate |fieldData| to the end of |fieldName|, concatenate a newline character (`\n`, `U+000A`) to the end, +and append the result to |dataToCanonicalize|. +
    6. +
    +
  8. +
  9. +Set |canonicalizedData| to the result of sorting |dataToCanonicalize| in Unicode code point order and then applying a join operation +to create a single string from the array. +
  10. +
  11. +Hash |canonicalizedData| and return the result. +
  12. +
+
+ +
+
`MachineReadableZone` Credentials
+
    +
  1. +Set |dataToCanonicalize| to an empty array. +
  2. +
  3. +For each line in the Machine Readable Zone on the credential: +
      +
    1. +Set |mrzLine| to a string containing the data in that line. +
    2. +
    3. +Append a newline character to the end of |mrzLine| and append |mrzLine| to |dataToCanonicalize|. +
    4. +
    +
  4. +
  5. +Set |canonicalizedData| to the result of ordering the elements of |dataToCanonicalize| to match the order they appear +on the credential and then applying a join operation to create a single string from the array. +
  6. +
  7. +Hash |canonicalizedData| and return the result. +
  8. +
+
+
+
+

Proof Configuration (ecdsa-xi-2023)

+ +

+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: +

+ +
    +
  1. +If options.type is not set to `DataIntegrityProof` and +proofConfig.cryptosuite is not set to `ecdsa-xi-2023`, an +`INVALID_PROOF_CONFIGURATION` error MUST be raised. +
  2. +
+ +
+
+
+
+ +
+

Security Considerations

+ +

+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. +

+ +
+

Optical Data Duplication

+

+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. +

+
+
+

Partially Signed Optical Data

+

+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. +

+
+
+

Safe Verification

+

+[=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. +

+
+
+ +
+

Privacy Considerations

+ +

+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. +

+ +
+Add more privacy considerations including at least the following: + +
+ +
+ +
+

Test Vectors

+

+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. +

+
+

Creating VCBs

+
+

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
+          
+
+
+Creating `opticalDataBytes` +
+ +

+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: +

+
+
+Example 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"
+  }
+}
+            
+
+ +
+

CBOR-LD Compression and Encoding

+

+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: +

+
+ A VCB from a Utopia driver's license. +
+A VCB from a Utopia driver's license. +
+
+
+
+
+

Utopia Employment Authorization Document

+ +

+We start with the data that will be signed by the VCB (i.e an MRZ): +

+
+IAUTO0000007010SRC0000000701<<
+8804192M2601058NOT<<<<<<<<<<<5
+SMITH<<JOHN<<<<<<<<<<<<<<<<<<<
+          
+
+
+Creating `opticalDataBytes` +
+

+For the EAD, we apply : +

+
+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: +

+
+
+
+Example 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"
+  }
+}
+            
+
+
+

CBOR-LD Compression and Encoding

+

+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: +

+
+
+
Employment Authorization Document
+
+ A VCB from a Utopia EAD. +
+A VCB from a Utopia EAD. +
+
+

+For use with the following MRZ: +

+
+ An MRZ on a Utopia Employment Authorization Document. +
+An MRZ on a Utopia Employment Authorization Document. +
+
+
+
+
+
+

Verifying VCBs

+

+We now apply the reverse process to verify. +

+
+

Utopia Driver's License

+
+

Decoding and Decompressing

+

+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"
+  }
+}
+            
+
+
+

Verifying

+

+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]
+            
+ +

+We then apply and + to verify +the credential. +

+
+
+

Status Checking

+

+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. +

+
+
+
+

Utopia Employment Authorization Document

+
+

Decoding and Decompressing

+

+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"
+  }
+}
+            
+
+
+

Verifying

+

+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]
+            
+

+We then apply and + to verify +the credential. +

+
+
+
+
+

+Implementation Notes +

+
+

+CBOR-LD +

+

+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. +

+
+
+
+

+Legacy CBOR-LD encoded credentials +

+This process is used to test whether a CBOR-LD implementation that is not fully +up to date has been used. + +
+

+CBOR-LD Version 6.X +

+The process remains +the same, with the exception of the CBOR-LD decoding step, for which the following |appContextMap| +should be used: +
+appContextMap:
+[['https://www.w3.org/ns/credentials/v2', 32768],
+['https://w3id.org/vc-barcodes/v1', 32769],
+['https://w3id.org/utopia/v2', 32770]]
+          
+
+

Utopia Driver's License

+
+ A VCB from a Utopia driver's license encoded with legacy CBOR-LD. +
+ A VCB from a Utopia driver's license encoded with legacy CBOR-LD. +
+
+
+
+
Utopia Employment Authorization Document
+
+ A VCB from a Utopia EAD encoded with legacy CBOR-LD. +
+ A VCB from a Utopia EAD encoded with legacy CBOR-LD. +
+
+

+ For use with the following MRZ: +

+
+ An MRZ on a Utopia Employment Authorization Document. +
+ An MRZ on a Utopia Employment Authorization Document. +
+
+
+
+
+

+CBOR-LD Version 7.X +

+
+

Utopia Driver's License

+
+ A VCB from a Utopia driver's license encoded with legacy CBOR-LD. +
+ A VCB from a Utopia driver's license encoded with legacy CBOR-LD. +
+
+
+
+
Utopia Employment Authorization Document
+
+ A VCB from a Utopia EAD encoded with legacy CBOR-LD. +
+ A VCB from a Utopia EAD encoded with legacy CBOR-LD. +
+
+

+ For use with the following MRZ: +

+
+ An MRZ on a Utopia Employment Authorization Document. +
+ An MRZ on a Utopia Employment Authorization Document. +
+
+
+
+
+
+
+

Revision History

+

+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. +

+ +
+ + +