W3C First Public Working Draft
Copyright © 2026 World Wide Web Consortium . W3C ® liability , trademark and permissive document license rules apply.
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 section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C standards and drafts index .
This specification is experimental.
This document was published by the Verifiable Credentials Working Group as a First Public Working Draft using the Recommendation track .
Publication as a First Public Working Draft does not imply endorsement by W3C and its Members.
This is a draft document and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to cite this document as other than a work in progress.
This document was produced by a group operating under the W3C Patent Policy . W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent that the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy .
This document is governed by the 18 August 2025 W3C Process Document .
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 Verifiable Credentials Data Model v2.0 specification provides a global standard for expressing credential information, such as those in a driver's license or travel document. The Verifiable Credential Data Integrity 1.0 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 Compact Binary Object Representation for Linked Data v0.7 specification provides a means of compressing secured verifiable credentials to the point at which it becomes feasible to express the information as an optical barcode, or embedded within an optical barcode.
This specification describes a mechanism to protect optical barcodes, such as those found on driver's licenses (PDF417) and travel documents (MRZ), by using a verifiable credential [ VC-DATA-MODEL-2.0 ] to express information about the barcode, which is then secured using Data Integrity [ VC-DATA-INTEGRITY ], and then compressed using CBOR-LD [ CBOR-LD ]. The resulting verifiable credential representations are compact enough such that they fit in under 140 bytes and can thus be integrated with traditional two-dimensional barcodes that are printed on physical cards using standard printing processes. This adds tamper resistance to the barcode while optionally enhancing the barcode to provide information related to whether or not the physical document has been revoked or suspended by the issuer .
The following sections provide a few introductory examples of the ways this specification can be used to enhance existing physical credentials with digital signatures via verifiable credentials .
This section provides an example on how the technology in this specification can be utilized to secure the optical barcode on a driver's license that uses a PDF417 barcode. We start off with an example driver's license:
The back of the driver's license contains a PDF417 barcode:
The PDF417 data contains information that is secured using the algorithms described in this specification. Namely, the PDF417 barcode contains a verifiable credential of the following form.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/vdl/v2",
"https://w3id.org/vdl/utopia/v1"
],
"type": [
"VerifiableCredential",
"OpticalBarcodeCredential"
],
// the issuer value below is defined as a URL in the 'utopia/v1' context above
"issuer": "did:web:dmv.utopia.example",
"credentialStatus": {
"type": "TerseBitstringStatusListEntry",
"terseStatusListBaseUrl": "https://dmv.utopia.gov/statuses/12345/status-lists"
"terseStatusListIndex": 123567890
},
"credentialSubject": {
"type": "AamvaDriversLicenseScannableInformation",
"protectedComponentIndex": "uP_BA"
},
"proof": {
"type": "DataIntegrity",
"cryptosuite": "ecdsa-xi-2023",
// the public key below is defined as a URL in the 'utopia/v1' context above
"verificationMethod": "did:web:dmv.utopia.example#key-1",
"proofPurpose": "assertionMethod",
"proofValue": "z4peo48uwK2EF4Fta8P...HzQMDYJ34r9gL"
}
}
The verifiable credential above is then compressed using [ CBOR-LD ] to the following output (in CBOR Diagnostic Notation):
1281{
1 => [ 32768, 32769, 32770], // @context
155 => [ 116, 164 ], // type
192 => 174, // issuer
186 => { 154 => 166, 206 => 178, 208 => 1234567890 }, // credentialStatus
188 => { 154 => 172, 180 => h'753FF040 }, // credentialSubject
194 => { // proof
154 => 108, // type
214 => 4, // cryptosuite
224 => 230 // verificationMethod
228 => 176, // proofPurpose
210 => Uint8Array(65) [ ... ], // proofValue
}
}
This section provides an example on how the technology in this specification can be utilized to secure a birth certificate as a verifiable credential , which is then expressed as a QR Code on the printed paper document:
The QR Code encodes the following verifiable credential . The details of the encoding are available as separate tabs below:
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/vital-records/v1rc1"
],
"type": [
"VerifiableCredential",
"BirthCertificateCredential"
],
"issuer": "https://hospital.example/issuer",
"validFrom": "2023-09-30T11:30:00Z",
"credentialSubject": {
"type": "BirthCertificate",
"certificationDate": "2023-09-30T13:44:52Z",
"newborn": {
"type": "Newborn",
"name": "Tim Doe",
"gender": "Male",
"birthDate": "2023-10-05T14:29:00Z",
"birthPlace": {
"type": "PostalAddress",
"streetAddress": "123 Hospital Rd",
"addressLocality": "Utopia Town",
"addressRegion": "Utopolis",
"postalCode": "12345",
"addressCountry": "Utopia"
},
"parent": [{
"type": "Mother",
"name": "Jane Doe",
"namePriorToMarriage": "Jane Smith"
}, {
"type": "Father",
"name": "John Doe"
}]
}
}
}
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/vital-records/v1rc1"
],
"type": [
"VerifiableCredential",
"BirthCertificateCredential"
],
"issuer": "https://hospital.example/issuer",
"validFrom": "2023-09-30T11:30:00Z",
"credentialSubject": {
"type": "BirthCertificate",
"certificationDate": "2023-09-30T13:44:52Z",
"newborn": {
"type": "Newborn",
"name": "Tim Doe",
"gender": "Male",
"birthDate": "2023-10-05T14:29:00Z",
"birthPlace": {
"type": "PostalAddress",
"streetAddress": "123 Hospital Rd",
"addressLocality": "Utopia Town",
"addressRegion": "Utopolis",
"postalCode": "12345",
"addressCountry": "Utopia"
},
"parent": [
{
"type": "Mother",
"name": "Jane Doe",
"namePriorToMarriage": "Jane Smith"
},
{
"type": "Father",
"name": "John Doe"
}
]
}
},
"proof": {
"type": "DataIntegrityProof",
"created": "2026-04-10T16:33:15Z",
"verificationMethod": "did:key:zDnaeS3nL9GyPpdr3YoCg8Hpb3U5F8S8XZhrYnZYbvttqGGdR",
"verificationMethod": "did:key:zDnaehu9u1f4ChH2UdYySo3WtoKAQoPjhawCALsXDLjfmEhGj",
"cryptosuite": "ecdsa-rdfc-2019",
"proofPurpose": "assertionMethod",
"proofValue": "zZXD7UAPW17m1VhfRwQwtiFEXyiZaUmKMgbS6LHtHRmfWk4Tbv4vvEdLfGpPuSpKVYJ6X2bjHqxUaGJyG
B4yCzBs"
"proofValue": "z5ZqGwTGwddp3bD1aN3TfN6mMJBYoyqbc8zQehd2yikrCbRBvoSRXJh6Yw7hKh3H6HDAbpfnRiZEFS6Sr
4oRwXzhw"
}
}
51997(
[
1,
{
1: [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/vital-records/v1rc1"
],
157: [
118,
164
],
304: {
156: 162,
204: "2023-09-30T13:44:52Z",
260: {
150: "Tim Doe",
156: 174,
188: "2023-10-05T14:29:00Z",
196: {
156: 178,
324: "Utopia",
326: "Utopia Town",
328: "Utopolis",
330: "12345",
332: "123 Hospital Rd"
},
226: "Male",
267: [
{
150: "Jane Doe",
156: 172,
258: "Jane Smith"
},
{
150: "John Doe",
156: 170
}
]
}
},
308: [
2,
"hospital.example/issuer"
],
310: {
156: 108,
336: 1775838795,
338: "ecdsa-rdfc-2019",
348: 354,
350: h'7a1c0b740b366f2477618e6b832eb73abd1fb8a9ac36efe5409a1b2ca4a55d99a3fae2ac8b428f785d99b
4081c06135a44d77f36d3375f6d89f79fc5e03de2cd92',
350: h'7ae4619fbdbbb3ab3250ba1e88b84ceac109dc3d209eab986e5ce5356c21bf2017a0e7cec9bca4c1f0599
70dcb0bd04860019b01b0c518347f117e28a3ba91055a',
352: [
1025,
h'80240218087aee9640b1ac1450c98e076cd4837879517ee5dbecdb3b2386fc31f1c2d4'
h'802403038da1191710cbd2ff13d5566a456b912f9638cedb5275d6df9a1da1154cafb8'
]
},
320: 1696073400
}
])}
VC1-R0OR*W3H90Q80L8FA9DIWENPEJ/5S4F03F53F7*5$KE$:5CPEXPC C1$CBWEAECCPEI.EL8FA9DIWENPEJ/553FPED7*5$K E006-EDAECOX5Z C04EKVC006DB6DOC1534KG$-EOXKY60$RK0XJ6MK5%PNF6QF63W5CA79L6/SAJL6:Q66G7KG6B73KQ0*43$2D YEDP34W3E053I53W531VE8466L6$963W5HX6-963G7PA7646OHBW%O053M53B735T86 A/3EMEDB73R+86 A/3EMED-3454EF-DD 70O8DHWES9EXVDZOEF70UZCQF60R6B73$T9*96%K6379WQE-EDAEC*34JTC-RS9Z9TVDB73LK1$RKT0J6I91/DP34W3E053G53B7 3XD06I91/D+34J$DAWE6MKT0JKI949DP34W3E053E53B73WS61E059DWQE-EDAEC.%5$9FQ$DTVDW:5ZQE%$E4JE+60+:K0XJ/TDL70BF3FKRAM9N70W3EJPCHQEOX57VC9OCNF61A6B73.SB*70B73W-BMC80XE.YVB.GSWCJIIB0GNPVFYFY9U2K1DC4:L0:S3N2KC LO5E5W8GPQ29M7E50ABG-OHCDMGUCQNOKI1M93/ H/XJXMADTQ0BNB7319CE73T70/L4%O4W13FOFY:IYKMPP2SLPA.0/%QGAFRD AS2TK.TJL7-2H5E6GSOB73U485ZCA%0L70BF3FKRAM9N70W3EJPCHQEOX57VC9OCNF61A6B73.SB*70B73W-BMC8RRRKRAY4KH21QYO*8TSIT2%Q0IBHGQ0:2VWGY1GG/4H 3U:UH5XNS+D%ID7JT3JB352R%R::KZJ5U+K7TFI2M4S9/WEU:MM%GB7319CE73T70/L4*O49K0LGK9-2NYP4BWT/QPJD.QDW0678 7VWRG+E2CSPX37V2T9MB73U485ZCA%0
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/vital-records/v1rc1"
],
"type": [
"VerifiableCredential",
"BirthCertificateCredential"
],
"issuer": "https://hospital.example/issuer",
"validFrom": "2023-09-30T11:30:00Z",
"credentialSubject": {
"type": "BirthCertificate",
"certificationDate": "2023-09-30T13:44:52Z",
"newborn": {
"type": "Newborn",
"name": "Tim Doe",
"gender": "Male",
"birthDate": "2023-10-05T14:29:00Z",
"birthPlace": {
"type": "PostalAddress",
"streetAddress": "123 Hospital Rd",
"addressLocality": "Utopia Town",
"addressRegion": "Utopolis",
"postalCode": "12345",
"addressCountry": "Utopia"
},
"parent": [
{
"type": "Mother",
"name": "Jane Doe",
"namePriorToMarriage": "Jane Smith"
},
{
"type": "Father",
"name": "John Doe"
}
]
}
},
"proof": {
"type": "DataIntegrityProof",
"created": "2026-04-10T16:33:15Z",
"verificationMethod": "did:key:zDnaeS3nL9GyPpdr3YoCg8Hpb3U5F8S8XZhrYnZYbvttqGGdR",
"verificationMethod": "did:key:zDnaehu9u1f4ChH2UdYySo3WtoKAQoPjhawCALsXDLjfmEhGj",
"cryptosuite": "ecdsa-rdfc-2019",
"proofPurpose": "assertionMethod",
"proofValue": "z3L9c3EVdcbEkrcR58jhCHa8wpDpmLHrxrJDRmfxUnxrL6AHSVZvj4yT1iKXDjAezN3XKPQt1aPZWbheU
gSCEycff"
"proofValue": "z5NHn9KPGCveNgXSNcfvaHK7mbMQUa1cToARUebEGU5KoDtRH6VeThqcGiA2vzsr3MadnUUss1mteDYn1
XVfojJMy"
}
}}
The following are the design goals of the technology in this specification:
Terminology used throughout this document is defined in the Terminology section of the Verifiable Credentials Data Model v2.0 specification as well as the Verifiable Credential Data Integrity 1.0 specification.
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
.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MUST , RECOMMENDED , REQUIRED , and SHOULD in this document are to be interpreted as described in BCP 14 [ RFC2119 ] [ RFC8174 ] when, and only when, they appear in all capitals, as shown here.
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 2. Data Model and 3. Algorithms of this document MUST be enforced.
A conforming processor is any algorithm realized as software and/or hardware that generates or consumes a conforming document . Conforming processors MUST produce errors when non-conforming documents are consumed.
This
document
contains
examples
of
JSON
and
JSON-LD
data.
Some
of
these
examples
are
invalid
JSON,
as
they
include
features
such
as
inline
comments
(
//
)
explaining
certain
portions
and
ellipses
(
...
)
indicating
the
omission
of
information
that
is
irrelevant
to
the
example.
Such
parts
need
to
be
removed
if
implementers
want
to
treat
the
examples
as
valid
JSON
or
JSON-LD.
The following sections outline the data model that is used by this specification to express verifiable credentials that secure optically printed information such as barcodes and machine-readable zones on travel documents.
An
OpticalBarcodeCredential
is
used
to
secure
the
contents
of
an
optical
barcode
in
a
way
that
provides
1)
authorship
information
,
2)
tamper
resistance,
and
3)
optionally,
revocation
and
suspension
status.
In
other
words,
the
credential
can
tell
you
who
issued
the
optical
barcode,
if
the
optical
barcode
has
been
tampered
with
since
it
was
first
issued,
and
whether
or
not
the
issuer
of
the
optical
barcode
still
warrants
that
the
document
is
still
valid
or
not.
These
features
provide
significant
anti-fraud
protections
for
physical
documents.
The
credentialSubject
of
an
OpticalBarcodeCredential
is
either
of
type
AamvaDriversLicenseScannableInformation
or
a
MachineReadableZone
.
A
AamvaDriversLicenseScannableInformation
signifies
that
the
verifiable
credential
secures
the
PDF417
barcode
on
the
physical
document
as
well
as
the
information
expressed
in
the
verifiable
credential
.
A
MachineReadableZone
signifies
that
the
verifiable
credential
secures
the
machine-readable
zone
on
the
physical
document
as
well
as
the
information
expressed
in
the
verifiable
credential
.
If
an
OpticalBarcodeCredential
is
of
type
AamvaDriversLicenseScannableInformation
,
there
is
a
REQUIRED
additional
field
protectedComponentIndex
that
contains
information
about
which
fields
in
the
PDF417
are
digitally
signed.
protectedComponentIndex
MUST
be
a
three
byte/24
bit
value
that
is
multibase-base64url
encoded
for
a
total
of
5
characters
in
the
JSON-LD
credential.
There
are
22
mandatory
fields
in
an
AAMVA
compliant
driver's
license
PDF417
[
aamva-dl-id-card-design-standard
],
and
the
first
22
bits
of
the
protectedComponentIndex
value
correspond
to
these
fields.
Each
AAMVA
mandatory
field
begins
with
a
three
character
element
ID
(e.g.,
DBA
for
document
expiration
date).
To
construct
a
mapping
between
bits
in
the
protectedComponentIndex
value
and
these
fields,
sort
these
element
IDs
according
to
Unicode
code
point
order.
Then,
if
a
bit
in
position
i
of
protectedComponentIndex
is
1
,
the
AAMVA
mandatory
field
in
position
i
of
the
sorted
element
IDs
is
protected
by
the
digital
signature.
The
last
two
bits
in
protectedComponentIndex
MUST
be
0
.
For
more
information,
see
Section
3.2.4.4
Create
opticalDataBytes
.
In
order
to
achieve
as
much
compression
as
possible,
it
is
RECOMMENDED
that
the
issuer
and
verificationMethod
fields
utilize
terms
from
a
JSON-LD
Context,
which
can
then
be
compressed
down
to
a
few
bytes
due
to
CBOR-LD's
semantic
compression
mechanism.
An example of an optical barcode credential that utilizes the properties specified in this section is provided below:
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/vdl/v2",
"https://w3id.org/vdl/utopia/v1"
],
"type": [
"VerifiableCredential",
"OpticalBarcodeCredential"
],
"issuer": "did:web:dmv.utopia.example",
"credentialStatus": {
"type": "TerseBitstringStatusListEntry",
"terseStatusListBaseUrl": "dmv.utopia.gov/statuses/12345/status-lists"
"terseStatusListIndex": 123567890
},
"credentialSubject": {
"type": "AamvaDriversLicenseScannableInformation",
"protectedComponentIndex": "uP_BA"
}
}
A
TerseBitstringStatusListEntry
is
a
compact
representation
of
a
BitstringStatusListEntry
as
defined
in
the
Bitstring
Status
List
v1.0
specification.
An
object
of
type
TerseBitstringStatusListEntry
MUST
have
two
additional
properties:
terseStatusListBaseUrl
,
which
identifies
the
location
of
the
status
lists
associated
with
this
credential.
terseStatusListBaseUrl
MUST
be
a
URL
[
URL
].
terseStatusListIndex
,
which
specifies
an
individual
status
at
the
above
URL.
terseStatusListIndex
MUST
be
representable
as
a
32
bit
unsigned
integer.
To
process
a
TerseBitstringStatusListEntry
,
apply
the
algorithm
in
Section
3.2.3
Convert
Status
List
Entries
to
convert
it
to
a
BitstringStatusListEntry
,
then
process
it
as
in
Bitstring
Status
List
v1.0
.
Implementers
need
to
set
a
value
listLength
for
the
length
of
an
individual
status
list.
This
then
yields
a
number
of
status
lists
listCount
=
2^32
/
listLength
for
a
32-bit
terseStatusListIndex
.
listLength
is
needed
to
convert
from
a
TerseBitstringStatusListEntry
to
a
BitstringStatusListEntry
.
Noting
that
some
values
of
listLength
will
harm
the
privacy-preserving
properties
of
these
status
lists,
implementations
MUST
use
listLength
=
2^26
and
listCount
=
2^6.
It
is
RECOMMENDED
that
implementers
character-encode
CBOR-LD
encoded
AamvaDriversLicenseScannableInformation
credentials
as
base64url
before
encoding
them
in
a
PDF417.
It
is
REQUIRED
that
implementers
re-encode
CBOR-LD
encoded
MachineReadableZone
credentials
as
base45-multibase
with
the
string
'VC1-'
prepended
before
encoding
them
in
a
QR
code.
The following section describes algorithms for adding and verifying digital proofs that protect optical information, such as barcodes and machine-readable zones, on physical media, such as driver's licenses and travel documents.
This section contains algorithms that are general to encoding and decoding verifiable credentials .
This specification requires that an application-specific compression table is provided to a CBOR-LD processor when encoding and decoding verifiable credentials . A registry for all context URLs for various issuers is provided as a comma-separated value file and can be updated and modified via change requests to the file on an append-only and first-come-first-served basis. Implementations SHOULD retrieve and utilize the latest file on a monthly basis to ensure that compression and decompression supports the latest values.
The following algorithm specifies how to encode a verifiable credential into a text string that can be expressed in a QR Code. Required inputs are a verifiable credential ( map inputDocument ), and a set of options ( map options ). The output is an encoded verifiable credential ( string ) or an error. Whenever this algorithm encodes strings, it MUST use UTF-8 encoding.
45
as
targetBase
,
and
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
$%*+-./:
as
the
baseAlphabet
.
VC1-
,
R
(the
Multibase
prefix
for
base45),
and
base45Value
.
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.
VC1-R
.
If
it
does
not
an
error
MUST
be
raised.
VC1-R
)
removed.
45
as
sourceBase
,
and
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
$%*+-./:
as
the
baseAlphabet
.
This
section
contains
algorithms
that
are
specific
to
encoding
and
decoding
verifiable
credentials
that
have
a
type
of
OpticalBarcodeCredential
.
BitstringStatusListCredential
(as
defined
in
the
Bitstring
Status
List
v1.0
specification)
that
the
issuer
wishes
to
add
to
the
OpticalBarcodeCredential
.
TerseBitstringStatusListEntry
and
statusListEntryTerse
.
index
to
the
integer
representation
of
statusListEntryVerbose
.
statusListIndex
.
OpticalBarcodeCredential
with
unsignedStatus
.
issuer
set
to
issuerUrl
and
unsignedStatus
.
credentialStatus
set
to
statusListEntryTerse
.
OpticalBarcodeCredential
in
securedDocument
.
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.
floor()
operation).
result can be used as input to the validation algorithm in the Bitstring Status List v1.0 specification.
Implementers are advised that not all issuers will publish status list information for their verifiable credentials . Some issuers might require authorization before allowing a verifier to access a status list credential.
The
ecdsa-xi-2023
cryptosuite
is
effectively
the
ecdsa-rdfc-2019
algorithm
[
VC-DI-ECDSA
]
with
an
added
step
that
takes
some
"extra
information"
(xi)
as
input,
such
as
the
original
optical
barcode
data,
and
includes
that
data
in
the
information
that
is
protected
by
the
digital
signature.
The
algorithms
in
this
section
detail
how
such
a
signature
is
created
and
verified.
To generate a proof, the algorithm in Section 4.1: Add Proof in the Data Integrity [ VC-DATA-INTEGRITY ] specification MUST be executed. For that algorithm, the cryptographic suite specific transformation algorithm is defined in the Transformation (ecdsa-rdfc-2019) section of the Data Integrity ECDSA Cryptosuites v1.0 , the hashing algorithm is defined in Section 3.2.4.3 Hashing (ecdsa-xi-2023) , and the proof serialization algorithm is defined in the Proof Serialization (ecdsa-rdfc-2019) section of the Data Integrity ECDSA Cryptosuites v1.0 .
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 Data Integrity ECDSA Cryptosuites v1.0 , the hashing algorithm is defined in Section 3.2.4.3 Hashing (ecdsa-xi-2023) , and the proof verification algorithm is defined in the Proof Verification (ecdsa-rdfc-2019) section of the Data Integrity ECDSA Cryptosuites v1.0 .
The hashing algorithm is what is defined in the Hashing (ecdsa-rdfc-2019) section of the Data Integrity ECDSA Cryptosuites v1.0 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 Data Integrity ECDSA Cryptosuites v1.0 with step 3 replaced with the following two steps:
credentialSubject.protectedComponentIndex
from
multibase-base64url
to
binary.
1
in
bitfieldDecoded
:
\n
,
U+000A
)
to
the
end,
and
append
the
result
to
dataToCanonicalize
.
The proof configuration algorithm is what is defined in the Proof Configuration (ecdsa-rdfc-2019) section of the Data Integrity ECDSA Cryptosuites v1.0 with step 4 replaced with the following step:
DataIntegrityProof
and
proofConfig
.
cryptosuite
is
not
set
to
ecdsa-xi-2023
,
an
INVALID_PROOF_CONFIGURATION
error
MUST
be
raised.
This section is non-normative.
Before reading this section, readers are urged to familiarize themselves with general security advice provided in the Security Considerations section of the Data Integrity specification as well as the specific security advice provided in the Security Considerations section of the ECDSA Cryptosuites specification .
In the following sections, we review these important points and direct the reader to additional information.
One
attack
vector
against
OpticalBarcodeCredentials
involves
duplicating
an
optical
barcode
containing
a
digital
signature
for
use
on
a
fraudulent
document.
While
a
duplicated
barcode
will
pass
signature
validation
like
the
original,
this
attack
is
mitigated
by
the
document
verifier
checking
the
following
three
things:
the
signed
data
matches
the
data
visible
on
the
document,
the
signed
data
matches
the
physical
attributes
of
the
user,
and
the
visible
data
matches
the
physical
attributes
of
the
user.
When
these
three
are
all
equivalent,
the
only
way
the
OpticalBarcodeCredential
could
be
a
duplicate
is
if
the
fraudulent
document
creator
had
access
to
a
real
OpticalBarcodeCredential
where
the
signed
physical
attributes
fully
overlapped
with
those
of
the
user
of
the
fraudulent
document.
The
low
likelihood
of
an
undetected
stolen
OpticalBarcodeCredential
existing
that
completely
matches
the
appearance
of
an
arbitrary
person
makes
this
attack
unlikely
to
succeed.
It
is
possible
that
in
some
cases
the
digital
signature
cannot
be
created
over
the
entirety
of
the
existing
optical
data.
For
example,
consider
a
case
where
a
serial
number
is
injected
by
a
physical
credential
manufacturer
such
that
it
is
not
known
to
the
issuer
at
signature
time.
In
this
case,
the
verifier
will
assume
that
any
data
not
digitally
signed
could
have
been
changed
in
the
optical
barcode
without
impacting
the
OpticalBarcodeCredential's
ability
to
successfully
validate.
When checking that data from the optical barcode matches the data visible on the document as well as the characteristics of the document holder, implementers are advised to only use the fields that are digitally signed. Verifiers are advised to only use fields protected by the digital signature, no matter how commonly the other fields are used for fraud detection on unsigned documents. For example, if eye color and hair color are protected by the signature, but the holder 's portrait is not, verifiers are advised to emphasize the eye color and hair color when attempting to detect fraud over the portrait.
Implementers of software used by verifiers are advised to only display card data that has been secured via digital signature during the verification process. Displaying unsigned data, which could have been tampered with, could interfere with fraud detection.
Verifiers
are
advised
to
always
use
trusted
programs
and
interfaces
to
check
the
validity
of
the
OpticalBarcodeCredential
.
Use
of
untrusted
software
to
verify
a
document
could
result
in
a
fraudulent
credential
being
accepted,
or
a
genuine
credential
being
stolen.
Before reading this section, readers are urged to familiarize themselves with general security advice provided in the Security Considerations section of the Data Integrity specification as well as the specific security advice provided in the Security Considerations section of the ECDSA Cryptosuites specification .
The following section describes privacy considerations that developers implementing this specification should be aware of in order to avoid violating privacy assumptions.
This section is non-normative.
This section contains examples of Verifiable Credential Barcodes as well as step-by-step processes for how they are generated and how they are verified.
In this section we will analyze two running examples: a VCB securing the MRZ of a Utopia Employment Authorization Document, and a VCB securing the PDF417 of a Utopia Driver's License.
We start with the data that will be signed by the VCB (i.e., mandatory AAMVA fields from a PDF417):
DACJOHN DADNONE DAG123 MAIN ST DAIANYVILLE DAJUTO DAKF87P20000 DAQF987654321 DAU069 IN DAYBRO DBA04192030 DBB04191988 DBC1 DBD01012024 DCAC DCBNONE DCDNONE DCFUTODOCDISCRIM DCGUTO DCSSMITH DDEN DDFN DDGN
Assume
for
simplicity
that
the
only
data
in
the
PDF417
that
you
want
to
sign
is
first
name
(
DAC
),
last
name
(
DCS
),
and
license
number
(
DAQ
).
The
bitstring
value
for
use
in
protectedComponentIndex
is
then
100000100000000000100000
,
and
the
value
of
protectedComponentIndex
is
"uggAg"
.
Applying
3.2.4.4
Create
opticalDataBytes
,
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
3.2.4.3
Hashing
(ecdsa-xi-2023)
to
sign
the
VC.
Executing
3.2.1
Encode
OpticalBarcodeCredential
with
a
BitstringStatusListCredential
,
we
get
the
following
JSON-LD
VC:
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/vc-barcodes/v1",
"https://w3id.org/utopia/v2"
],
"type": [
"VerifiableCredential",
"OpticalBarcodeCredential"
],
"credentialSubject": {
"type": "AamvaDriversLicenseScannableInformation",
"protectedComponentIndex": "uggAg"
},
"issuer": "did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj",
"credentialStatus": {
"type": "TerseBitstringStatusListEntry",
"terseStatusListBaseUrl": "https://sandbox.platform.veres.dev/statuses/z19rJ4oGrbFCqf3cNTVDHSbNd/status-lists",
"terseStatusListIndex": 3851559041
},
"proof": {
"type": "DataIntegrityProof",
"verificationMethod": "did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj#zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj",
"cryptosuite": "ecdsa-xi-2023",
"proofPurpose": "assertionMethod",
"proofValue": "z4g6G3dAZhhtPxPWgFvkiRv7krtCaeJxjokvL46fchAFCXEY3FeX2vn46MDgBaw779g1E1jswZJxxreZDCrtHg2qH"
}
}
We can now apply CBOR-LD compression to this VC. Here, we use the newest version of CBOR-LD; however, at the end of the section, we provide VCBs encoded using older versions of CBOR-LD for interoperability testing with CBOR-LD implementations that are not up to date.
For
this
specification,
we
have
reserved
the
CBOR-LD
registry
entry
with
value
100
(i.e.,
these
payloads
will
begin
with
tag
0x0664
).
The
parameters
to
encode
using
CBOR-LD,
which
can
be
found
in
the
registry
in
the
CBOR-LD
specification,
are
then
as
follows:
registryEntryId: 100
typeTable:
{
"context":
{
"https://www.w3.org/ns/credentials/v2": 32768,
"https://w3id.org/vc-barcodes/v1": 32769,
"https://w3id.org/utopia/v2": 32770
},
"https://w3id.org/security#cryptosuiteString":
{
"ecdsa-rdfc-2019": 1,
"ecdsa-sd-2023": 2,
"eddsa-rdfc-2022": 3,
"ecdsa-xi-2023": 4
}
}
The term-to-ID mapping that should result from processing the contexts and assigning integer values to context terms is as follows:
Map(97) {
'@context' => 0,
'@type' => 2,
'@id' => 4,
'@value' => 6,
'@direction' => 8,
'@graph' => 10,
'@included' => 12,
'@index' => 14,
'@json' => 16,
'@language' => 18,
'@list' => 20,
'@nest' => 22,
'@reverse' => 24,
'@base' => 26,
'@container' => 28,
'@default' => 30,
'@embed' => 32,
'@explicit' => 34,
'@none' => 36,
'@omitDefault' => 38,
'@prefix' => 40,
'@preserve' => 42,
'@protected' => 44,
'@requireAll' => 46,
'@set' => 48,
'@version' => 50,
'@vocab' => 52,
'...' => 100,
'BitstringStatusList' => 102,
'BitstringStatusListCredential' => 104,
'BitstringStatusListEntry' => 106,
'DataIntegrityProof' => 108,
'EnvelopedVerifiableCredential' => 110,
'EnvelopedVerifiablePresentation' => 112,
'JsonSchema' => 114,
'JsonSchemaCredential' => 116,
'VerifiableCredential' => 118,
'VerifiablePresentation' => 120,
'_sd' => 122,
'_sd_alg' => 124,
'aud' => 126,
'cnf' => 128,
'description' => 130,
'digestMultibase' => 132,
'digestSRI' => 134,
'exp' => 136,
'iat' => 138,
'id' => 140,
'iss' => 142,
'jku' => 144,
'kid' => 146,
'mediaType' => 148,
'name' => 150,
'nbf' => 152,
'sub' => 154,
'type' => 156,
'x5u' => 158,
'AamvaDriversLicenseScannableInformation' => 160,
'MachineReadableZone' => 162,
'OpticalBarcodeCredential' => 164,
'TerseBitstringStatusListEntry' => 166,
'protectedComponentIndex' => 168,
'did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj' => 170,
'did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj#zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj' => 172,
'did:key:zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj' => 174,
'did:key:zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj#zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj' => 176,
'https://sandbox.platform.veres.dev/statuses/z19rJ4oGrbFCqf3cNTVDHSbNd/status-lists' => 178,
'confidenceMethod' => 180,
'credentialSchema' => 182,
'credentialStatus' => 184,
'credentialSubject' => 186,
'evidence' => 188,
'issuer' => 190,
'proof' => 192,
'refreshService' => 194,
'relatedResource' => 196,
'renderMethod' => 198,
'termsOfUse' => 200,
'validFrom' => 202,
'validUntil' => 204,
'terseStatusListBaseUrl' => 206,
'terseStatusListIndex' => 208,
'challenge' => 210,
'created' => 212,
'cryptosuite' => 214,
'domain' => 216,
'expires' => 218,
'nonce' => 220,
'previousProof' => 222,
'proofPurpose' => 224,
'proofValue' => 226,
'verificationMethod' => 228,
'assertionMethod' => 230,
'authentication' => 232,
'capabilityDelegation' => 234,
'capabilityInvocation' => 236,
'keyAgreement' => 238
}
For more information on the above, see 6.3 Implementation Notes .
This results in the following encoded credential:
D9CB1D821864A60183198000198001198002189D82187618A418B8A3189C18A618CE18B218D01AE592208118BAA2189C18A018A8447582002018BE18AA18C0A5189C186C18D60418E018E618E258417AB7C2E56B49E2CCE62184CE26818E15A8B173164401B5D3BB93FFD6D2B5EB8F6AC0971502AE3DD49D17EC66528164034C912685B8111BC04CDC9EC13DBADD91CC18E418AC
diagnostic:
51997([
100,
{
1: [32768, 32769, 32770],
157: [118, 164],
184: {156: 166, 206: 178, 208: 3851559041},
186: {156: 160, 168: h'75820020'},
190: 170,
192: {
156: 108,
214: 4,
224: 230,
226: h'7AB7C2E56B49E2CCE62184CE26818E15A8B173164401B5D3BB93FFD6D2B5EB8F6AC0971502AE3DD49D17EC66528164034C912685B8111BC04CDC9EC13DBADD91CC',
228: 172
}
}
])
Encoding the Driver's License CBOR-LD as base64url and inserting the result into the PDF417 bytes in the 'ZZA' field in the 'ZZ' subfile:
bytes(@\n\x1e\rANSI 000000090002DL00410234ZZ02750202DLDAQF987654321\nDCSSMITH\nDDEN\nDACJOHN\nDDFN\nDADNONE\nDDGN\nDCAC\nDCBNONE\nDCDNONE\nDBD01012024\nDBB04191988\nDBA04192030\nDBC1\nDAU069 IN\nDAYBRO\nDAG123 MAIN ST\nDAIANYVILLE\nDAJUTO\nDAKF87P20000 \nDCFUTODOCDISCRIM\nDCGUTO\nDAW158\nDCK1234567890\nDDAN\rZZZZA2csdghhkpgGDGYAAGYABGYACGJ2CGHYYpBi4oxicGKYYzhiyGNAa5ZIggRi6ohicGKAYqER1ggAgGL4YqhjApRicGGwY1gQY4BjmGOJYQXq3wuVrSeLM5iGEziaBjhWosXMWRAG107uT/9bSteuPasCXFQKuPdSdF+xmUoFkA0yRJoW4ERvATNyewT263ZHMGOQYrA==\r)
The above can now be turned into a barcode:
We now apply the reverse process to verify.
We first read the data from the PDF417:
bytes(@\n\x1e\rANSI 000000090002DL00410234ZZ02750202DLDAQF987654321\nDCSSMITH\nDDEN\nDACJOHN\nDDFN\nDADNONE\nDDGN\nDCAC\nDCBNONE\nDCDNONE\nDBD01012024\nDBB04191988\nDBA04192030\nDBC1\nDAU069 IN\nDAYBRO\nDAG123 MAIN ST\nDAIANYVILLE\nDAJUTO\nDAKF87P20000 \nDCFUTODOCDISCRIM\nDCGUTO\nDAW158\nDCK1234567890\nDDAN\rZZZZA2QZkpgGDGYAAGYABGYACGJ2CGHYYpBi4oxicGKYYzhiyGNAa5ZIggRi6ohicGKAYqER1ggAgGL4YqhjApRicGGwY1gQY4BjmGOJYQXq3wuVrSeLM5iGEziaBjhWosXMWRAG107uT_9bSteuPasCXFQKuPdSdF-xmUoFkA0yRJoW4ERvATNyewT263ZHMGOQYrA==\r)
We extract the data in field 'ZZA' in subfile 'ZZ', undoing the base encoding:
d90664a60183198000198001198002189d82187618a418b8a3189c18a618ce18b218d01ae592208118baa2189c18a018a8447582002018be18aa18c0a5189c186c18d60418e018e618e258417ab7c2e56b49e2cce62184ce26818e15a8b173164401b5d3bb93ffd6d2b5eb8f6ac0971502ae3dd49d17ec66528164034c912685b8111bc04cdc9ec13dbadd91cc18e418ac
We
now
decompress
with
CBOR-LD
to
get
the
original
JSON-LD
VC
to
be
verified.
Again,
the
parameters
are
associated
with
CBOR-LD
registry
entry
100
.
typeTable:
{
"context":
{
"https://www.w3.org/ns/credentials/v2": 32768,
"https://w3id.org/vc-barcodes/v1": 32769,
"https://w3id.org/utopia/v2": 32770
},
"https://w3id.org/security#cryptosuiteString":
{
"ecdsa-rdfc-2019": 1,
"ecdsa-sd-2023": 2,
"eddsa-rdfc-2022": 3,
"ecdsa-xi-2023": 4
}
}
The ID-to-term mapping that should result from processing the contexts and assigning integer values to context terms is as follows. Note that this is the inverse of the map constructed during compression.
Map(97) {
0 => '@context',
2 => '@type',
4 => '@id',
6 => '@value',
8 => '@direction',
10 => '@graph',
12 => '@included',
14 => '@index',
16 => '@json',
18 => '@language',
20 => '@list',
22 => '@nest',
24 => '@reverse',
26 => '@base',
28 => '@container',
30 => '@default',
32 => '@embed',
34 => '@explicit',
36 => '@none',
38 => '@omitDefault',
40 => '@prefix',
42 => '@preserve',
44 => '@protected',
46 => '@requireAll',
48 => '@set',
50 => '@version',
52 => '@vocab',
100 => '...',
102 => 'BitstringStatusList',
104 => 'BitstringStatusListCredential',
106 => 'BitstringStatusListEntry',
108 => 'DataIntegrityProof',
110 => 'EnvelopedVerifiableCredential',
112 => 'EnvelopedVerifiablePresentation',
114 => 'JsonSchema',
116 => 'JsonSchemaCredential',
118 => 'VerifiableCredential',
120 => 'VerifiablePresentation',
122 => '_sd',
124 => '_sd_alg',
126 => 'aud',
128 => 'cnf',
130 => 'description',
132 => 'digestMultibase',
134 => 'digestSRI',
136 => 'exp',
138 => 'iat',
140 => 'id',
142 => 'iss',
144 => 'jku',
146 => 'kid',
148 => 'mediaType',
150 => 'name',
152 => 'nbf',
154 => 'sub',
156 => 'type',
158 => 'x5u',
160 => 'AamvaDriversLicenseScannableInformation',
162 => 'MachineReadableZone',
164 => 'OpticalBarcodeCredential',
166 => 'TerseBitstringStatusListEntry',
168 => 'protectedComponentIndex',
170 => 'did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj',
172 => 'did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj#zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj',
174 => 'did:key:zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj',
176 => 'did:key:zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj#zDnaeZSD9XcuULaS8qmgDUa6TMg2QjF9xABnZK42awDH3BEzj',
178 => 'https://sandbox.platform.veres.dev/statuses/z19rJ4oGrbFCqf3cNTVDHSbNd/status-lists',
180 => 'confidenceMethod',
182 => 'credentialSchema',
184 => 'credentialStatus',
186 => 'credentialSubject',
188 => 'evidence',
190 => 'issuer',
192 => 'proof',
194 => 'refreshService',
196 => 'relatedResource',
198 => 'renderMethod',
200 => 'termsOfUse',
202 => 'validFrom',
204 => 'validUntil',
206 => 'terseStatusListBaseUrl',
208 => 'terseStatusListIndex',
210 => 'challenge',
212 => 'created',
214 => 'cryptosuite',
216 => 'domain',
218 => 'expires',
220 => 'nonce',
222 => 'previousProof',
224 => 'proofPurpose',
226 => 'proofValue',
228 => 'verificationMethod',
230 => 'assertionMethod',
232 => 'authentication',
234 => 'capabilityDelegation',
236 => 'capabilityInvocation',
238 => 'keyAgreement'
}
For more information on the above, see 6.3 Implementation Notes .
Decompression then yields the following credential:
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/vc-barcodes/v1",
"https://w3id.org/utopia/v2"
],
"type": [
"VerifiableCredential",
"OpticalBarcodeCredential"
],
"credentialSubject": {
"type": "AamvaDriversLicenseScannableInformation",
"protectedComponentIndex": "uggAg"
},
"issuer": "did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj",
"credentialStatus": {
"type": "TerseBitstringStatusListEntry",
"terseStatusListBaseUrl": "https://sandbox.platform.veres.dev/statuses/z19rJ4oGrbFCqf3cNTVDHSbNd/status-lists",
"terseStatusListIndex": 3851559041
},
"proof": {
"type": "DataIntegrityProof",
"verificationMethod": "did:key:zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj#zDnaeWjKfs1ob9QcgasjYSPEMkwq31hmvSAWPVAgnrt1e9GKj",
"cryptosuite": "ecdsa-xi-2023",
"proofPurpose": "assertionMethod",
"proofValue": "z4g6G3dAZhhtPxPWgFvkiRv7krtCaeJxjokvL46fchAFCXEY3FeX2vn46MDgBaw779g1E1jswZJxxreZDCrtHg2qH"
}
}
We
apply
3.2.4.4
Create
opticalDataBytes
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 3.2.4.3 Hashing (ecdsa-xi-2023) and 3.2.4.2 Verify Proof (ecdsa-xi-2023) to verify the credential.
The
last
step
is
to
check
the
status
information
on
the
Driver's
License
credential.
We
apply
3.2.3
Convert
Status
List
Entries
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 .
When building maps from context terms to CBOR-LD integers, note that some contexts include other contexts inside of them, nested under particular types of objects. These nested contexts are called "type-scoped contexts" and they only become active when the associated type is used in the data. This is important for term ID assignment because the terms in a context are only assigned IDs once that context becomes active. In these test vectors, this is why the maps created for the Driver's License and the Employment Authorization Document are different even though the two credentials use identical contexts.
In addition, note that odd numbers are used in CBOR-LD to express terms when the associated value is plural. For example, in the CBOR-LD term-to-ID and ID-to-term maps above, "type" is mapped to 156, but in places where multiple types are expressed in a VC, 157 is used instead.
appContextMap: [['https://www.w3.org/ns/credentials/v2', 32768], ['https://w3id.org/vc-barcodes/v1', 32769], ['https://w3id.org/utopia/v2', 32770]]
This section is non-normative.
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.