W3C
Candidate
Recommendation
Snapshot
15
March
Copyright © 2024 World Wide Web Consortium . W3C ® liability , trademark and permissive document license rules apply.
This specification describes a Data Integrity Cryptosuite for use when generating digital signatures using the BBS signature scheme. The Signature Suite utilizes BBS signatures to provide selective disclosure and unlinkable derived proofs.
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 technical reports index at https://www.w3.org/TR/.
The Working Group is actively seeking implementation feedback for this specification. In order to exit the Candidate Recommendation phase, the Working Group has set the requirement of at least two independent implementations for each mandatory feature in the specification. For details on the conformance testing process, see the test suites listed in the implementation report .
This document was published by the Verifiable Credentials Working Group as a Candidate Recommendation Snapshot using the Recommendation track .
Publication as a Candidate Recommendation does not imply endorsement by W3C and its Members. A Candidate Recommendation Snapshot has received wide review , is intended to gather implementation experience , and has commitments from Working Group members to royalty-free licensing for implementations.
This Candidate Recommendation is not expected to advance to Proposed Recommendation any earlier than 30 April 2024.
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 which 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 03 November 2023 W3C Process Document .
This
specification
defines
a
cryptographic
suite
for
the
purpose
of
creating,
verifying,
and
deriving
proofs
using
the
BBS
Signature
Scheme
in
conformance
with
the
Data
Integrity
[
VC-DATA-INTEGRITY
]
specification.
The
BBS
signature
scheme
directly
provides
for
selective
disclosure
and
unlinkable
proofs.
It
provides
four
high-level
functions
that
work
within
the
issuer,
holder,
verifier
model.
Specifically,
an
issuer
uses
the
BBS
Sign
function
to
create
a
cryptographic
value
known
as
a
"BBS
signature"
which
is
used
in
signing
the
original
credential.
A
holder,
on
receipt
of
a
credential
signed
with
BBS,
then
verifies
the
credential
with
the
BBS
Verify
function.
The
holder
then
chooses
information
to
selectively
disclose
from
the
received
credential
and
uses
the
BBS
ProofGen
function
to
generate
a
cryptographic
value,
known
as
a
"BBS
proof",
which
is
used
in
creating
a
proof
for
this
"derived
credential".
The
cryptographic
"BBS
proof"
value
is
not
linkable
to
the
original
"BBS
signature"
and
a
different,
unlinkable
"BBS
proof"
can
be
generated
by
the
holder
for
additional
"derived
credentials",
including
any
containing
the
exact
same
information.
Finally,
a
verifier
uses
the
BBS
ProofVerify
function
to
verify
the
derived
credential
received
from
the
holder.
Applying
the
BBS
signature
scheme
to
verifiable
credentials
involves
the
processing
specified
in
this
document.
In
general
the
suite
uses
the
RDF
Dataset
Canonicalization
Algorithm
[
RDF-CANON
]
to
transform
an
input
document
into
its
canonical
form.
An
issuer
then
uses
selective
disclosure
primitives
to
separate
the
canonical
form
into
mandatory
and
non-mandatory
statements.
These
are
processed
separately
with
other
information
to
serve
as
the
inputs
to
the
BBS
Sign
function
along
with
appropriate
key
material.
This
output
is
used
to
generate
a
secured
credential.
A
holder
uses
a
set
of
selective
disclosure
functions
and
the
BBS
Verify
function
on
receipt
of
the
credential
to
ascertain
validity.
Similarly,
on
receipt
of
a
BBS
signed
credential,
a
holder
uses
the
RDF
Dataset
Canonicalization
Algorithm
[
RDF-CANON
]
to
transform
an
input
document
into
its
canonical
form,
and
then
applies
selective
disclosure
primitives
to
separate
the
canonical
form
into
mandatory
and
selectively
disclosed
statements,
which
are
appropriately
processed
and
serve
as
inputs
to
the
BBS
ProofGen
function.
Suitably
processed,
the
output
of
this
function
becomes
the
signed
selectively
disclosed
credential
sent
to
a
verifier.
Using
canonicalization
and
selective
disclosure
primitives,
the
verifier
can
then
use
the
BBS
verifyProof
function
to
validate
the
credential.
Terminology used throughout this document is defined in the Terminology section of the Verifiable Credential Data Integrity 1.0 specification.
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 MAY , MUST , MUST NOT , OPTIONAL , 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 proof 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 proof . 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 for verification methods and data integrity proof formats.
These verification methods are used to verify Data Integrity Proofs [ VC-DATA-INTEGRITY ] produced using BLS12-381 cryptographic key material that is compliant with [ CFRG-BBS-SIGNATURE ]. The encoding formats for these key types are provided in this section. Lossless cryptographic key transformation processes that result in equivalent cryptographic key material MAY be used during the processing of digital signatures.
The Multikey format , as defined in [ VC-DATA-INTEGRITY ], is used to express public keys for the cryptographic suites defined in this specification.
The
publicKeyMultibase
property
represents
a
Multibase-encoded
Multikey
expression
of
a
BLS12-381
public
key
in
the
G2
group.
The
encoding
of
this
field
is
the
two-byte
prefix
0xeb01
followed
by
the
96-byte
compressed
public
key
data.
The
98-byte
value
is
then
encoded
using
base58-btc
(
z
)
as
the
prefix.
Any
other
encodings
MUST
NOT
be
allowed.
Developers
are
advised
to
not
accidentally
publish
a
representation
of
a
private
key.
Implementations
of
this
specification
will
raise
errors
in
the
event
of
a
[
MULTICODEC
]
value
other
than
0xeb01
being
used
in
a
publicKeyMultibase
value.
{
"id": "https://example.com/issuer/123#key-0",
"type": "Multikey",
"controller": "https://example.com/issuer/123",
"publicKeyMultibase": "zUC7EK3ZakmukHhuncwkbySmomv3FmrkmS36E4Ks5rsb6VQSRpoCrx6
Hb8e2Nk6UvJFSdyw9NK1scFXJp21gNNYFjVWNgaqyGnkyhtagagCpQb5B7tagJu3HDbjQ8h
5ypoHjwBb"
}
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/data-integrity/v1"
"https://w3id.org/security/multikey/v1"
],
"id": "https://example.com/issuer/123",
"verificationMethod": [{
"id": "https://example.com/issuer/123#key-1",
"type": "Multikey",
"controller": "https://example.com/issuer/123",
"publicKeyMultibase": "zUC7EK3ZakmukHhuncwkbySmomv3FmrkmS36E4Ks5rsb6VQSRpoCr
x6Hb8e2Nk6UvJFSdyw9NK1scFXJp21gNNYFjVWNgaqyGnkyhtagagCpQb5B7tagJu3HDbjQ8h
5ypoHjwBb"
}]
}
A proof contains the attributes specified in the Proofs section of [ VC-DATA-INTEGRITY ] with the following restrictions.
The
verificationMethod
property
of
the
proof
MUST
be
a
URL.
Dereferencing
the
verificationMethod
MUST
result
in
an
object
containing
a
type
property
with
the
value
set
to
Multikey
.
The
type
property
of
the
proof
MUST
be
DataIntegrityProof
.
The
cryptosuite
property
of
the
proof
MUST
be
bbs-2023
.
The
value
of
the
proofValue
property
of
the
proof
MUST
be
a
BBS
signature
or
BBS
proof
produced
according
to
[
CFRG-BBS-SIGNATURE
]
that
is
serialized
and
encoded
according
to
procedures
in
section
3.
Algorithms
.
The following algorithms describe how to use verifiable credentials with the BBS Signature Scheme [ CFRG-BBS-SIGNATURE ]. When using the BBS signature scheme the SHA-256 variant SHOULD be used.
Implementations SHOULD fetch and cache verification method information as early as possible when adding or verifying proofs. Parameters passed to functions in this section use information from the verification method — such as the public key size — to determine function parameters — such as the cryptographic hashing algorithm.
When the RDF Dataset Canonicalization Algorithm [ RDF-CANON ] is used, implementations of that algorithm will detect dataset poisoning by default, and abort processing upon detection.
This algorithm is used to configure a cryptographic suite to be used by the Add Proof and Verify Proof functions in Verifiable Credential Data Integrity 1.0 . The algorithm takes an options object ( map options ) as input and returns a cryptosuite instance ( struct cryptosuite ).
DataIntegrityProof
,
return
cryptosuite
.
bbs-2023
then:
The following algorithm creates a label map factory function that uses an HMAC to shuffle canonical blank node identifiers. The required input is an HMAC (previously initialized with a secret key), HMAC . A function, labelMapFactoryFunction , is produced as output.
bnodeIdMap
as
follows:
hmacIds
to
be
the
sorted
array
of
values
from
the
bnodeIdMap
,
and
set
bnodeKeys
to
be
the
ordered
array
of
keys
from
the
bnodeIdMap
.
bnodeKeys
,
replace
the
bnodeIdMap
value
for
that
key
with
the
index
position
of
the
value
in
the
hmacIds
array
prefixed
by
"b",
i.e.,
bnodeIdMap.set(bkey,
'b'
+
hmacIds.indexOf(bnodeIdMap.get(bkey)))
.
It
should
be
noted
that
step
1.2
in
the
above
algorithm
is
identical
to
step
1.2
in
Section
3.3.4
createHmacIdLabelMapFunction
of
[
DI-ECDSA
],
so
developers
might
be
able
to
reuse
the
code
or
call
the
function
if
implementing
both.
The following algorithm serializes the base proof value, including the BBS signature, HMAC key, and mandatory pointers. The required inputs are a base signature bbsSignature , an HMAC key hmacKey , and an array of mandatoryPointers . A single base proof string value is produced as output.
proofValue
,
that
starts
with
the
BBS
base
proof
header
bytes
0xd9
,
0x5d
,
and
0x02
.
proofValue
.
That
is,
return
a
string
starting
with
"
u
"
and
ending
with
the
base64url-no-pad-encoded
value
of
proofValue
.
The
following
algorithm
parses
the
components
of
a
bbs-2023
selective
disclosure
base
proof
value.
The
required
input
is
a
proof
value
(
proofValue
).
A
single
object,
parsed
base
proof
,
containing
five
or
seven
elements,
using
the
names
"bbsSignature",
"bbsHeader",
"publicKey",
"hmacKey",
"mandatoryPointers",
and
optional
feature
parameters
"pid"
and
"signer_blind"
is
produced
as
output.
proofValue
string
starts
with
u
(
U+0075
LATIN
SMALL
LETTER
U
)
,
indicating
that
it
is
a
multibase-base64url-no-pad-encoded
value,
and
throw
an
error
if
it
does
not.
decodedProofValue
to
the
result
of
base64url-no-pad-decoding
the
substring
following
the
leading
u
in
proofValue
.
decodedProofValue
starts
with
the
BBS
base
proof
header
bytes
0xd9
,
0x5d
,
and
0x02
,
and
throw
an
error
if
it
does
not.
components
to
an
array
that
is
the
result
of
CBOR-decoding
the
bytes
that
follow
the
three-byte
BBS
base
proof
header.
The
following
algorithm
creates
data
to
be
used
to
generate
a
derived
proof.
The
inputs
include
a
JSON-LD
document
(
document
),
a
BBS
base
proof
(
proof
),
an
array
of
JSON
pointers
to
use
to
selectively
disclose
statements
(
selectivePointers
),
an
OPTIONAL
BBS
presentationHeader
(byte
array
that
defaults
to
an
empty
byte
array
if
not
present),
an
OPTIONAL
commitment_with_proof
(a
byte
array),
an
OPTIONAL
pid
value
(a
byte
array),
and
any
custom
JSON-LD
API
options
(such
as
a
document
loader).
A
single
object,
disclosure
data
,
is
produced
as
output,
which
contains
the
bbsProof
,
labelMap
,
mandatoryIndexes
,
selectiveIndexes
,
presentationHeader
,
and
revealDocument
fields.
bbsSignature
,
bbsHeader
,
publicKey
,
hmacKey
,
mandatoryPointers
,
and
the
optional
feature
parameters
pid
and
signer_blind
to
the
values
of
the
associated
properties
in
the
object
returned
when
calling
the
algorithm
in
Section
3.3.2
parseBaseProofValue
,
passing
the
proofValue
from
proof
.
hmac
to
an
HMAC
API
using
hmacKey
.
The
HMAC
uses
the
same
hash
algorithm
used
in
the
signature
algorithm,
i.e.,
SHA-256.
labelMapFactoryFunction
to
the
result
of
calling
the
createShuffledIdLabelMapFunction
algorithm
passing
hmac
as
HMAC
.
combinedPointers
to
the
concatenation
of
mandatoryPointers
and
selectivePointers
.
groupDefinitions
to
a
map
with
the
following
entries:
key
of
the
string
"mandatory"
and
value
of
mandatoryPointers
;
key
of
the
string
"selective"
and
value
of
selectivePointers
;
and
key
of
the
string
"combined"
and
value
of
combinedPointers
.
groups
and
labelMap
to
the
result
of
calling
the
algorithm
in
Section
3.3.16
canonicalizeAndGroup
of
the
[
DI-ECDSA
]
specification,
passing
document
labelMapFactoryFunction
,
groupDefinitions
,
and
any
custom
JSON-LD
API
options.
Note:
This
step
transforms
the
document
into
an
array
of
canonical
N-Quads
whose
order
has
been
shuffled
based
on
'hmac'
applied
blank
node
identifiers,
and
groups
the
N-Quad
strings
according
to
selections
based
on
JSON
pointers.
mandatoryIndexes
to
an
empty
array.
Set
mandatoryMatch
to
groups.mandatory.matching
map;
set
combinedMatch
to
groups.combined.matching
;
and
set
combinedIndexes
to
the
ordered
array
of
just
the
keys
of
the
combinedMatch
map.
mandatoryMatch
map,
find
its
index
in
the
combinedIndexes
array
(e.g.,
combinedIndexes.indexOf(key)
),
and
add
this
value
to
the
mandatoryIndexes
array.
selectiveIndexes
to
an
empty
array.
Set
selectiveMatch
to
the
groups.selective.matching
map;
set
mandatoryNonMatch
to
the
map
groups.mandatory.nonMatching
;
and
nonMandatoryIndexes
to
to
the
ordered
array
of
just
the
keys
of
the
mandatoryNonMatch
map.
selectiveMatch
map,
find
its
index
in
the
nonMandatoryIndexes
array
(e.g.,
nonMandatoryIndexes.indexOf(key)
),
and
add
this
value
to
the
selectiveIndexes
array.
bbsMessages
to
an
array
of
byte
arrays
containing
the
values
in
the
nonMandatory
array
of
strings
encoded
using
the
UTF-8
character
encoding
.
bbsProof
to
the
value
computed
by
the
appropriate
procedure
given
below
based
on
the
values
of
the
commitment_with_proof
and
pid
options.
bbsProof
to
the
value
computed
by
the
ProofGen
procedure
from
[
CFRG-BBS-SIGNATURE
],
i.e.,
ProofGen(PK,
signature,
header,
ph,
messages,
disclosed_indexes)
,
where
PK
is
the
original
issuers
public
key,
signature
is
the
bbsSignature
,
header
is
the
bbsHeader
,
ph
is
the
presentationHeader
messages
is
bbsMessages
,
and
disclosed_indexes
is
selectiveIndexes
.
bbsProof
to
the
value
computed
by
the
ProofGen
procedure
from
[
CFRG-Blind-BBS-Signature
],
where
PK
is
the
original
issuers
public
key,
signature
is
the
bbsSignature
,
header
is
the
bbsHeader
,
ph
is
the
presentationHeader
messages
is
bbsMessages
,
disclosed_indexes
is
selectiveIndexes
,
commitment_with_proof
,
and
signer_blind
.
The
holder
will
also
furnish
its
"secret
value"
that
was
used
to
compute
the
commitment_with_proof
.
This
is
the
"anonymous
holder
binding"
option.
bbsProof
to
the
value
computed
by
the
ProofGen
procedure
from
[
CFRG-Pseudonym-BBS-Signature
],
where
PK
is
the
original
issuers
public
key,
signature
is
the
bbsSignature
,
header
is
the
bbsHeader
,
ph
is
the
presentationHeader
messages
is
bbsMessages
,
disclosed_indexes
is
selectiveIndexes
,
and
pseudonym
is
the
pseudonym
.
This
is
for
both
"pseudonym
with
issuer
known
pid"
and
"pseudonym
with
hidden
pid"
cases.
document
,
and
combinedPointers
as
pointers
.
inputLabel
)
and
value
(
verifierLabel
)
in
`canonicalIdMap:
verifierLabelMap
,
using
verifierLabel
as
the
key,
and
the
value
associated
with
inputLabel
as
a
key
in
labelMap
as
the
value.
bbsProof
,
"verifierLabelMap"
for
labelMap
,
mandatoryIndexes
,
selectiveIndexes
,
revealDocument
,
and
pseudonym
,
if
computed.
The following algorithm compresses a label map. The required input is label map ( labelMap ). The output is a compressed label map .
map
to
an
empty
map.
k
,
v
)
in
labelMap
:
map
,
with
a
key
that
is
a
base-10
integer
parsed
from
the
characters
following
the
"c14n"
prefix
in
k
,
and
a
value
that
is
a
base-10
integer
parsed
from
the
characters
following
the
"b"
prefix
in
v
.
map
as
compressed
label
map
.
The following algorithm decompresses a label map. The required input is a compressed label map ( compressedLabelMap ). The output is a decompressed label map .
map
to
an
empty
map.
k
,
v
)
in
compressedLabelMap
:
map
,
with
a
key
that
adds
the
prefix
"c14n"
to
k
,
and
a
value
that
adds
a
prefix
of
"b"
to
v
.
map
as
decompressed
label
map
.
The following algorithm serializes a derived proof value. The required inputs are a BBS proof ( bbsProof ), a label map ( labelMap ), an array of mandatory indexes ( mandatoryIndexes ), an array of selective indexes ( selectiveIndexes ), and a BBS presentation header ( presentationHeader ). Optional input is pseudonym . A single derived proof value, serialized as a byte string, is produced as output.
compressedLabelMap
to
the
result
of
calling
the
algorithm
in
Section
3.3.4
compressLabelMap
,
passing
labelMap
as
the
parameter.
proofValue
,
that
starts
with
the
BBS
disclosure
proof
header
bytes
0xd9
,
0x5d
,
and
0x03
.
u
"
and
ending
with
the
base64url-no-pad-encoded
value
of
proofValue
.
The
following
algorithm
parses
the
components
of
the
derived
proof
value.
The
required
input
is
a
derived
proof
value
(
proofValue
).
A
single
derived
proof
value
object
is
produced
as
output,
which
contains
a
set
of
five
or
six
elements,
having
the
names
bbsProof
,
labelMap
,
mandatoryIndexes
,
selectiveIndexes
,
presentationHeader
,
and
the
optional
pseudonym
parameter.
proofValue
string
starts
with
u
(
U+0075
,
LATIN
SMALL
LETTER
U
)
,
indicating
that
it
is
a
multibase-base64url-no-pad-encoded
value,
and
throw
an
error
if
it
does
not.
decodedProofValue
to
the
result
of
base64url-no-pad-decoding
the
substring
that
follows
the
leading
u
in
proofValue
.
decodedProofValue
starts
with
the
BBS
disclosure
proof
header
bytes
0xd9
,
0x5d
,
and
0x03
,
and
throw
an
error
if
it
does
not.
components
to
an
array
that
is
the
result
of
CBOR-decoding
the
bytes
that
follow
the
three-byte
BBS
disclosure
proof
header.
Ensure
the
result
is
an
array
of
five
or
six
elements
—
a
byte
array,
a
map
of
integers
to
integers,
an
array
of
integers,
another
array
of
integers,
and
a
byte
array;
otherwise,
throw
an
error.
components
using
the
result
of
calling
the
algorithm
in
Section
3.3.5
decompressLabelMap
,
passing
the
existing
second
element
of
components
as
compressedLabelMap
.
bbsProof
,
labelMap
,
mandatoryIndexes
,
selectiveIndexes
,
presentationHeader
,
and
optional
pseudonym
,
respectively.
The
following
algorithm
creates
the
data
needed
to
perform
verification
of
a
BBS-protected
verifiable
credential
.
The
inputs
include
a
JSON-LD
document
(
document
),
a
BBS
disclosure
proof
(
proof
),
and
any
custom
JSON-LD
API
options
(such
as
a
document
loader).
A
single
verify
data
object
value
is
produced
as
output
containing
the
following
fields:
bbsProof
,
proofHash
,
mandatoryHash
,
selectedIndexes
,
presentationHeader
,
and
nonMandatory
.
proofHash
to
the
result
of
performing
RDF
Dataset
Canonicalization
[
RDF-CANON
]
on
the
proof
options,
i.e.,
the
proof
portion
of
the
document
with
the
proofValue
removed.
The
hash
used
is
the
same
as
that
used
in
the
signature
algorithm,
i.e.,
SHA-256.
Note:
This
step
can
be
performed
in
parallel;
it
only
needs
to
be
completed
before
this
algorithm
needs
to
use
the
proofHash
value.
bbsProof
,
labelMap
,
mandatoryIndexes
,
selectiveIndexes
,
presentationHeader
,
and
pseudonym
to
the
values
associated
with
their
property
names
in
the
object
returned
when
calling
the
algorithm
in
Section
3.3.7
parseDerivedProofValue
,
passing
proofValue
from
proof
.
labelMapFactoryFunction
to
the
result
of
calling
the
"
createLabelMapFunction
"
algorithm.
nquads
to
the
result
of
calling
the
"
labelReplacementCanonicalize
"
algorithm
of
[
DI-ECDSA
],
passing
document
,
labelMapFactoryFunction
,
and
any
custom
JSON-LD
API
options.
Note:
This
step
transforms
the
document
into
an
array
of
canonical
N-Quads
with
pseudorandom
blank
node
identifiers
based
on
labelMap
.
mandatory
to
an
empty
array.
nonMandatory
to
an
empty
array.
index
,
nq
)
in
nquads
,
separate
the
N-Quads
into
mandatory
and
non-mandatory
categories:
mandatoryIndexes
includes
index
,
add
nq
to
mandatory
.
nq
to
nonMandatory
.
mandatoryHash
to
the
result
of
calling
the
"
hashMandatory
"
primitive,
passing
mandatory
.
baseSignature
,
proofHash
,
nonMandatory
,
mandatoryHash
,
selectiveIndexes
,
and
pseudonym
.
The
bbs-2023
cryptographic
suite
takes
an
input
document,
canonicalizes
the
document
using
the
Universal
RDF
Dataset
Canonicalization
Algorithm
[
RDF-CANON
],
and
then
applies
a
number
of
transformations
and
cryptographic
operations
resulting
in
the
production
of
a
data
integrity
proof.
The
algorithms
in
this
section
also
include
the
verification
of
such
a
data
integrity
proof.
The following algorithm specifies how to create a data integrity proof given an unsecured data document . Required inputs are an unsecured data document ( map unsecuredDocument ), and a set of proof options ( map options ). A data integrity proof ( map ), or an error, is produced as output.
The following algorithm specifies how to transform an unsecured input document into a transformed document that is ready to be provided as input to the hashing algorithm in Section 3.4.3 Base Proof Hashing (bbs-2023) .
Required inputs to this algorithm are an unsecured data document ( unsecuredDocument ) and transformation options ( options ). The transformation options MUST contain a type identifier for the cryptographic suite ( type ), a cryptosuite identifier ( cryptosuite ), and a verification method ( verificationMethod ). The transformation options MUST contain an array of mandatory JSON pointers ( mandatoryPointers ) and MAY contain additional options, such as a JSON-LD document loader. A transformed data document is produced as output. Whenever this algorithm encodes strings, it MUST use UTF-8 encoding.
labelMapFactoryFunction
to
the
result
of
calling
the
createShuffledIdLabelMapFunction
algorithm
passing
hmac
as
HMAC
.
groupDefinitions
to
a
map
with
an
entry
with
a
key
of
the
string
"
mandatory
"
and
a
value
of
mandatoryPointers
.
groups
to
the
result
of
calling
the
algorithm
in
Section
3.3.16
canonicalizeAndGroup
of
the
[
DI-ECDSA
]
specification,
passing
labelMapFactoryFunction
,
groupDefinitions
,
unsecuredDocument
as
document
,
and
any
custom
JSON-LD
API
options.
Note:
This
step
transforms
the
document
into
an
array
of
canonical
N-Quads
whose
order
has
been
shuffled
based
on
'hmac'
applied
blank
node
identifiers,
and
groups
the
N-Quad
strings
according
to
selections
based
on
JSON
pointers.
mandatory
to
the
values
in
the
groups.mandatory.matching
map.
nonMandatory
to
the
values
in
the
groups.mandatory.nonMatching
map.
hmacKey
to
the
result
of
exporting
the
HMAC
key
from
hmac
.
mandatoryPointers
"
set
to
mandatoryPointers
,
"
mandatory
"
set
to
mandatory
,
"
nonMandatory
"
set
to
nonMandatory
,
and
"
hmacKey
"
set
to
hmacKey
.
The following algorithm specifies how to cryptographically hash a transformed data document and proof configuration into cryptographic hash data that is ready to be provided as input to the algorithms in Section 3.4.5 Base Proof Serialization (bbs-2023) .
The required inputs to this algorithm are a transformed data document ( transformedDocument ) and canonical proof configuration ( canonicalProofConfig ). A hash data value represented as an object is produced as output.
proofHash
to
the
result
of
calling
the
RDF
Dataset
Canonicalization
algorithm
[
RDF-CANON
]
on
canonicalProofConfig
and
then
cryptographically
hashing
the
result
using
the
same
hash
that
is
used
by
the
signature
algorithm,
i.e.,
SHA-256.
Note:
This
step
can
be
performed
in
parallel;
it
only
needs
to
be
completed
before
this
algorithm
terminates,
as
the
result
is
part
of
the
return
value.
mandatoryHash
to
the
result
of
calling
the
the
algorithm
in
Section
3.3.17
hashMandatoryNQuads
of
the
[
DI-ECDSA
]
specification,
passing
transformedDocument
.
mandatory
and
using
the
SHA-256
algorithm.
hashData
as
a
deep
copy
of
transformedDocument
,
and
add
proofHash
as
"
proofHash
"
and
mandatoryHash
as
"
mandatoryHash
"
to
that
object.
hashData
as
hash
data
.
The following algorithm specifies how to generate a proof configuration from a set of proof options that is used as input to the base proof hashing algorithm .
The required inputs to this algorithm are proof options ( options ). The proof options MUST contain a type identifier for the cryptographic suite ( type ) and MUST contain a cryptosuite identifier ( cryptosuite ). A proof configuration object is produced as output.
DataIntegirtyProof
and/or
proofConfig
.
cryptosuite
is
not
set
to
bbs-2023
,
an
INVALID_PROOF_CONFIGURATION
error
MUST
be
raised.
INVALID_PROOF_DATETIME
error
MUST
be
raised.
The following algorithm, to be called by an issuer of a BBS-protected Verifiable Credential, specifies how to create a base proof. The base proof is to be given only to the holder, who is responsible for generating a derived proof from it, exposing only selectively disclosed details in the proof to a verifier. This algorithm is designed to be used in conjunction with the algorithms defined in the Data Integrity [ VC-DATA-INTEGRITY ] specification, Section 4: Algorithms . Required inputs are cryptographic hash data ( hashData ) and proof options ( options ). Optional inputs include a commitment_with_proof byte array and/or a use_pseudonyms boolean. The proof options MUST contain a type identifier for the cryptographic suite ( type ) and MAY contain a cryptosuite identifier ( cryptosuite ). A single digital proof value represented as series of bytes is produced as output.
proofHash
,
mandatoryPointers
,
mandatoryHash
,
nonMandatory
,
and
hmacKey
to
the
values
associated
with
their
property
names
in
hashData
.
bbsHeader
to
the
concatenation
of
proofHash
and
mandatoryHash
in
that
order.
bbsMessages
to
an
array
of
byte
arrays
containing
the
values
in
the
nonMandatory
array
of
strings
encoded
using
the
UTF-8
character
encoding
.
bbsSignature
using
the
procedures
below,
dependent
on
the
values
of
commitment_with_proof
and
use_pseudonyms
options.
bbsSignature
using
the
Sign
procedure
of
[
CFRG-BBS-Signature
],
with
appropriate
key
material,
bbsHeader
for
the
header
,
and
bbsMessages
for
the
messages
.
bbsSignature
using
the
Sign
procedure
of
[
CFRG-Blind-BBS-Signature
],
with
appropriate
key
material,
bbsHeader
for
the
header
,
and
bbsMessages
for
the
messages
.
If
the
signing
procedure
uses
the
optional
signer_blind
parameter,
retain
this
value
for
use
when
calling
3.3.1
serializeBaseProofValue
(below).
This
provides
for
the
"anonymous
holder
binding"
feature.
bbsSignature
using
the
Sign
procedure
of
[
CFRG-Pseudonym-BBS-Signature
],
with
appropriate
key
material,
bbsHeader
for
the
header
,
bbsMessages
for
the
messages
,
and
pid
for
the
pid
.
Retain
the
pid
value
for
use
when
calling
3.3.1
serializeBaseProofValue
below.
This
provides
for
"pseudonym
with
issuer
known
pid".
bbsSignature
using
the
Sign
procedure
of
[
CFRG-Pseudonym-BBS-Signature
],
with
appropriate
key
material,
bbsHeader
for
the
header
,
bbsMessages
for
the
messages
,
and
commitment_with_proof
for
the
commitment_with_proof
.
If
the
signing
procedure
uses
the
optional
signer_blind
parameter
retain
this
value
for
use
when
calling
3.3.1
serializeBaseProofValue
below.
This
provides
for
the
"pseudonym
with
hidden
pid"
feature.
bbsSignature
,
bbsHeader
,
publicKey
,
hmacKey
,
mandatoryPointers
,
pid
,
and
signer_blind
values
as
paramters.
Use
empty
byte
arrays
for
pid
and
signer_blind
if
they
are
not
used.
Note
publicKey
is
a
byte
array
of
the
public
key,
encoded
according
to
[
CFRG-BBS-SIGNATURE
].
proofValue
as
digital
proof
.
The
following
algorithm,
to
be
called
by
a
holder
of
a
bbs-2023
-protected
verifiable
credential
,
creates
a
selective
disclosure
derived
proof.
The
derived
proof
is
to
be
given
to
the
verifier
.
The
inputs
include
a
JSON-LD
document
(
document
),
a
BBS
base
proof
(
proof
),
an
array
of
JSON
pointers
to
use
to
selectively
disclose
statements
(
selectivePointers
),
an
OPTIONAL
BBS
presentationHeader
(a
byte
array),
an
OPTIONAL
commitment_with_proof
(a
byte
array),
an
OPTIONAL
pid
value
(a
byte
array),
and
any
custom
JSON-LD
API
options,
such
as
a
document
loader.
A
single
selectively
revealed
document
value,
represented
as
an
object,
is
produced
as
output.
bbsProof
,
labelMap
,
mandatoryIndexes
,
selectiveIndexes
,
and
revealDocument
to
the
values
associated
with
their
property
names
in
the
object
returned
when
calling
the
algorithm
in
Section
3.3.3
createDisclosureData
,
passing
the
document
,
proof
,
selectivePointers
,
presentationHeader
,
and
any
custom
JSON-LD
API
options,
such
as
a
document
loader.
newProof
to
a
shallow
copy
of
proof
.
proofValue
in
newProof
with
the
result
of
calling
the
algorithm
in
Section
3.3.6
serializeDerivedProofValue
,
passing
bbsProof
,
labelMap
,
mandatoryIndexes
,
selectiveIndexes
,
commitment_with_proof
,
and
pid
.
proof
"
property
in
revealDocument
to
newProof
.
revealDocument
as
the
selectively
revealed
document
.
The following algorithm specifies how to verify a data integrity proof given an secured data document . Required inputs are a secured data document ( map securedDocument ). This algorithm returns a verification result , which is a struct whose items are:
true
or
false
false
;
otherwise,
an
unsecured
data
document
To verify a derived proof, perform the following steps:
proof
value
removed.
proofValue
removed.
bbsProof
,
proofHash
,
mandatoryHash
,
selectedIndexes
,
presentationHeader
,
pseudonym
,
and
nonMandatory
to
the
values
associated
with
their
property
names
in
the
object
returned
when
calling
the
algorithm
in
Section
3.3.8
createVerifyData
,
passing
the
unsecuredDocument
,
proof
,
and
any
custom
JSON-LD
API
options
(such
as
a
document
loader).
bbsHeader
to
the
concatenation
of
proofHash
and
mandatoryHash
in
that
order.
Initialize
disclosedMessages
to
an
array
of
byte
arrays
obtained
from
the
UTF-8
encoding
of
the
elements
of
the
nonMandatory
array.
ProofVerify(PK,
proof,
header,
ph,
disclosed_messages,
disclosed_indexes)
of
[
CFRG-BBS-SIGNATURE
]
with
PK
set
as
the
public
key
of
the
original
issuer,
proof
set
as
bbsProof
,
header
set
as
bbsHeader
,
disclosed_messages
set
as
disclosedMessages
,
ph
set
as
presentationHeader
,
and
disclosed_indexes
set
as
selectiveIndexes
.
This
applies
to
the
regular
BBS
proof
case
as
well
as
"anonymous
holder
binding"
case.
PseudonymProofVerify(PK,
proof,
header,
ph,
disclosed_messages,
disclosed_indexes,
pseudonym)
of
[
CFRG-Pseudonym-BBS-Signature
],
with
PK
set
as
the
public
key
of
the
original
issuer,
proof
set
as
bbsProof
,
header
set
as
bbsHeader
,
disclosed_messages
set
as
disclosedMessages
,
ph
set
as
presentationHeader
,
disclosed_indexes
set
as
selectiveIndexes
,
and
pseudonym
.
This
applies
to
the
"pseudonym
with
issuer
known
pid"
and
"pseudonym
with
hidden
pid"
cases.
true
,
otherwise
Null
This section is non-normative.
The cryptographic properties of BBS signatures permit variants that can support advanced functionalities. This specification is limited to supporting only the most relevant of these enhancements, which we explain in the following sections. The variables commitment_with_proof , use_pseudonyms , pid , and pseudonym are associated with these features and are not otherwise needed for BBS signatures and proofs.
The optional BBS features described in this section, and included in the algorithms in this specification, are at risk and will be removed before the finalization of this specification if their respective specifications at the IETF do not reach RFC status on the same timeline or if there are not at least two independent implementations for each optional feature.
This feature binds, at the time of issuance, a document with base proof, to a secret, known only to a holder, in such a way, that only that holder can generate a revealed document with derived proof that will verify. For example, if an adversary obtained the document with base proof, they could not create a revealed document with derived proof that can verify.
To provide for this functionality, a holder generates a holder_secret value which should generally be at least 32 bytes long and cryptographically randomly generated. This value is never shared by the holder. Instead, the holder generates a commitment along with a zero knowledge proof of knowledge of this value, using the "Commitment Generation" procedure of [ CFRG-Blind-BBS-Signature ]. This computation involves cryptographically random values and computes the commitment_with_proof and secret_prover_blind values. The commitment_with_proof is conveyed to the issuer while the secret_prover_blind is kept secret and is retained by the holder for use in generation of derived proofs. Note that a holder can run the "Commitment Generation" procedure multiple times to produce unlinkable commitment_with_proof values for use with different issuers.
The issuer, on receipt of the commitment_with_proof , follows the procedures of [ CFRG-Blind-BBS-Signature ] to produce a base proof (signature) over the document with the commitment furnished by the holder. If the issuer chooses to use the signer_blind parameter when creating the signature in [ CFRG-Blind-BBS-Signature ], this value needs to be conveyed to the holder as part of the base proof value.
When the holder wants to create a selectively disclosed document with derived proof, they use their holder_secret (as a "commited message"), the secret_prover_blind , and, if supplied in the base proof, the signer_blind in the proof generation procedure of [ CFRG-Blind-BBS-Signature ].
Verification of the revealed document with derived proof uses the "regular" BBS proof verification procedures of [ CFRG-BBS-SIGNATURE ].
This feature is a privacy preserving enhancement that allows a verifier that has seen a selectively revealed document with derived proof from a holder to recognize that the same holder is presenting a new selectively revealed document with derived proof. Note that this may just be a new unlinkable proof (derived proof) on the same selectively revealed information. By "privacy preserving," we mean that no uniquely identifiable information is added that would allow tracking between different verifiers that may share information amongst themselves. This variant does allow for the issuer to monitor usage if verifiers share information with the issuer.
To furnish this capability, before creating the base proof for a document, an issuer generates a value known as a pid (prover id) which should be cryptographically random and at least 32 bytes long. This value is shared with the holder but otherwise kept secret. This value is then used in creating the base proof via the signing procedure in [ CFRG-Pseudonym-BBS-Signature ].
The holder receives the document with base proof which includes the pid value from the issuer. The holder obtains a verifier_id associated with the verifier for which they intend to create a revealed document with derived proof. Using the procedures of [ CFRG-Pseudonym-BBS-Signature ], a cryptographic pseudonym value is generated. The derived proof value is generated via the proof generation procedure of [ CFRG-Pseudonym-BBS-Signature ], and this value along with the pseudonym are given to the verifier. Note that the pid value cannot be recovered from the pseudonym .
When the verifier receives the revealed document with derived proof and pseudonym , they use the proof verification procedures of [ CFRG-Pseudonym-BBS-Signature ].
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 .
This section is non-normative.
The security of the base proof is dependent on the security properties of the associated BBS signature . Digital signatures might exhibit a number of desirable cryptographic properties [ Taming_EdDSAs ] among these are:
EUF-CMA ( existential unforgeability under chosen message attacks ) is usually the minimal security property required of a signature scheme. It guarantees that any efficient adversary who has the public key of the signer and received an arbitrary number of signatures on messages of its choice (in an adaptive manner): , cannot output a valid signature for a new message (except with negligible probability). In case the attacker outputs a valid signature on a new message: , it is called an existential forgery .
SUF-CMA ( strong unforgeability under chosen message attacks ) is a stronger notion than EUF-CMA . It guarantees that for any efficient adversary who has the public key of the signer and received an arbitrary number of signatures on messages of its choice: , it cannot output a new valid signature pair , such that (except with negligible probability). Strong unforgeability implies that an adversary cannot only sign new messages, but also cannot find a new signature on an old message.
In [ CDL2016 ] under some reasonable assumptions BBS signatures were proven to be EUF-CMA. Furthermore, in [ TZ2023 ], under similar assumptions BBS signatures were proven to be SUF-CMA. In both cases the assumptions are related to the hardness of the discrete logarithm problem which is not considered post large scale quantum computing secure.
Under non-quantum computing conditions [ CFRG-BBS-SIGNATURE ] provides additional security guidelines to BBS signature suite implementors. Further security considerations related to pairing friendly curves are discussed in [ CFRG-PAIRING-FRIENDLY ].
This section is non-normative.
The
security
of
the
derived
proof
is
dependent
on
the
security
properties
of
the
associated
BBS
proof
.
Both
[
CDL2016
]
and
[
TZ2023
]
prove
that
a
BBS
proof
is
a
zero
knowledge
proof
of
knowledge
of
a
BBS
signature
.
As explained in [ CFRG-BBS-SIGNATURE ] this means:
a verifying party in receipt of a proof is unable to determine which signature was used to generate the proof, removing a common source of correlation. In general, each proof generated is indistinguishable from random even for two proofs generated from the same signature.
and
The proofs generated by the scheme prove to a verifier that the party who generated the proof (holder/prover or an agent of theirs) was in possession of a signature without revealing it.
More precisely, verification of a BBS proof requires the original issuers public key as well as the unaltered, revealed BBS message in the proper order.
This section is non-normative.
Selective disclosure permits a holder to minimize the information revealed to a verifier to achieve a particular purpose. In prescribing an overall system that enables selective disclosure, care has to be taken that additional information that was not meant to be disclosed to the verifier is minimized. Such leakage can occur through artifacts of the system. Such artifacts can come from higher layers of the system, such as in the structure of data or from the lower level cryptographic primitives.
For example the BBS signature scheme is an extremely space efficient scheme for producing a signature on multiple messages , i.e., the cryptographic signature sent to the holder is a constant size regardless of the number of messages . The holder then can selectively disclose any of these messages to a verifier , however as part of the encryption scheme, the total number of messages signed by the issuer has to be revealed to the verifier . If such information leakage needs to be avoided then it is recommended to pad the number of messages out to a common length as suggested in the privacy considerations section of [ CFRG-BBS-SIGNATURE ].
At the higher levels, how data gets mapped into individual statements suitable for selective disclosure, i.e., BBS messages , is a potential source of data leakage. This cryptographic suite is able to eliminate many structural artifacts used to express JSON data that might leak information (nesting, map, or array position, etc.) by using JSON-LD processing to transform inputs into RDF. RDF can then be expressed as a canonical, flat format of simple subject, property, value statements (referred to as claims in the Verifiable Credentials Data Model [ VC-DATA-MODEL-2.0 ]). In the following, we examine RDF canonicalization, a general scheme for mapping a verifiable credential in JSON-LD format into a set of statements (BBS messages ), for selective disclosure. We show that after this process is performed, there remains a possible source of information leakage, and we show how this leakage is mitigated via the use of a keyed pseudo random function (PRF).
RDF
canonicalization
can
be
used
to
flatten
a
JSON-LD
VC
into
a
set
of
statements
.
The
algorithm
is
dependent
on
the
content
of
the
VC
and
also
employs
a
cryptographic
hash
function
to
help
in
ordering
the
statements
.
In
essence,
how
this
happens
is
that
each
JSON
object
that
represents
the
subject
of
claims
within
a
JSON-LD
document
will
be
assigned
an
id,
if
it
doesn't
have
an
@id
field
defined.
Such
ids
are
known
as
blank
node
ids
.
These
ids
are
needed
to
express
claims
as
simple
subject,
property,
value
statements
such
that
the
subject
in
each
claim
can
be
differentiated.
The
id
values
are
deterministically
set
per
[
RDF-CANON
]
and
are
based
on
the
data
in
the
document
and
the
output
of
a
cryptographic
hash
function
such
as
SHA-256.
Below we show two slightly different VCs for a set of windsurf sails and their canonicalization into a set of statements that can be used for selective disclosure. By changing the year of the 6.1 size sail we see a major change in statement ordering between these two VCs. If the holder discloses information about just his larger sails (the 7.0 and 7.8) the verifier could tell something changed about the set of sails, i.e., information leakage.
{ "@context": [ "https://www.w3.org/ns/credentials/v2", { "@vocab": "https://windsurf.grotto-networking.com/selective#" } ], "type": [ "VerifiableCredential" ], "credentialSubject": { "sails": [ { "size": 5.5, "sailName": "Kihei", "year": 2023 }, { "size": 6.1, "sailName": "Lahaina", "year": 2023 // Will change this to see the effect on canonicalization }, { "size": 7.0, "sailName": "Lahaina", "year": 2020 }, { "size": 7.8, "sailName": "Lahaina", "year": 2023 } ] } }
Canonical
form
of
the
above
VC.
Assignment
of
blank
node
ids,
i.e.,
the
_:c14nX
labels
are
dependent
upon
the
content
of
the
VC
and
this
also
affects
the
ordering
of
the
statements.
_:c14n0 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n0 <https://windsurf.grotto-networking.com/selective#size> "7.8E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n0 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> . _:c14n1 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n4 . _:c14n2 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n2 <https://windsurf.grotto-networking.com/selective#size> "7"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n2 <https://windsurf.grotto-networking.com/selective#year> "2020"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n3 <https://windsurf.grotto-networking.com/selective#sailName> "Kihei" . _:c14n3 <https://windsurf.grotto-networking.com/selective#size> "5.5E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n3 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n4 <https://windsurf.grotto-networking.com/selective#sails> _:c14n0 . _:c14n4 <https://windsurf.grotto-networking.com/selective#sails> _:c14n2 . _:c14n4 <https://windsurf.grotto-networking.com/selective#sails> _:c14n3 . _:c14n4 <https://windsurf.grotto-networking.com/selective#sails> _:c14n5 . _:c14n5 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n5 <https://windsurf.grotto-networking.com/selective#size> "6.1E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n5 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> .
Updated windsurf sail collection, i.e., the 6.1 size sail has been updated to the 2024 model. This changes the ordering of statements via the assignment of blank node ids .
{ "@context": [ "https://www.w3.org/ns/credentials/v2", { "@vocab": "https://windsurf.grotto-networking.com/selective#" } ], "type": [ "VerifiableCredential" ], "credentialSubject": { "sails": [ { "size": 5.5, "sailName": "Kihei", "year": 2023 }, { "size": 6.1, "sailName": "Lahaina", "year": 2024 // New sail to update older model, changes canonicalization }, { "size": 7.0, "sailName": "Lahaina", "year": 2020 }, { "size": 7.8, "sailName": "Lahaina", "year": 2023 } ] } }
Canonical form of the previous VC. Note the difference in blank node id assignment and ordering of statements.
_:c14n0 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n0 <https://windsurf.grotto-networking.com/selective#size> "6.1E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n0 <https://windsurf.grotto-networking.com/selective#year> "2024"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n1 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n1 <https://windsurf.grotto-networking.com/selective#size> "7.8E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n1 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> . _:c14n2 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n5 . _:c14n3 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n3 <https://windsurf.grotto-networking.com/selective#size> "7"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n3 <https://windsurf.grotto-networking.com/selective#year> "2020"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n4 <https://windsurf.grotto-networking.com/selective#sailName> "Kihei" . _:c14n4 <https://windsurf.grotto-networking.com/selective#size> "5.5E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n4 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n0 . _:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n1 . _:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n3 . _:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n4 .
To
prevent
such
information
leakage
from
the
assignment
of
these
blank
node
ids
and
the
ordering
they
impose
on
the
statements
,
an
HMAC
based
PRF
is
run
on
the
blank
node
ids
.
The
HMAC
secret
key
is
only
shared
between
the
issuer
and
holder
and
each
Base
Proof
generated
by
the
issuer
uses
a
new
HMAC
key.
An
example
of
this
can
be
seen
in
the
canonical
HMAC
test
vector
of
[
DI-ECDSA
].
As
discussed
in
the
next
section,
for
BBS
to
preserve
unlinkability
we
do
not
use
HMAC
based
blank
node
ids
but
produce
a
shuffled
version
of
the
ordering
based
on
the
HMAC
as
shown
in
test
vector
Example
12
.
Note
that
this
furnishes
less
information
hiding
concerning
blank
node
ids
than
in
the
ECDSA-SD
approach,
since
information
the
number
of
blank
node
ids
can
leak,
but
prevents
linkage
attacks
via
the
essentially
unique
identifiers
produced
by
applying
an
HMAC
to
blank
node
ids.
In some uses of VCs it can be important to the privacy of a holder to prevent the tracking or linking of multiple different verifier interactions. In particular we consider two important cases (i) verifier to issuer collusion , and (ii) verifier to verifier collusion . In the first case, shown in Figure 1 , a verifier reports back to the original issuer of the credential on an interaction with a holder . In this situation, the issuer could track all the holder interactions with various verifiers using the issued VC. In the second situation, shown in Figure 2 , multiple verifiers collude to share information about holders with whom they have interacted.
We
use
the
term
unlinkability
to
describe
the
property
of
a
VC
system
to
prevent
such
"linkage
attacks"
on
holder
privacy.
Although
the
term
unlinkability
is
relatively
new
section
3.3
of
[
NISTIR8053
]
discusses
and
gives
a
case
study
of
Re-identification
through
Linkage
Attacks
.
A
systemization
of
knowledge
on
linkage
attack
on
data
privacy
can
be
found
in
[
Powar2023
].
The
most
widespread
use
of
linkage
attack
on
user
privacy
occurs
via
the
practice
of
web
browser
fingerprinting,
a
survey
of
which
can
be
found
in
[
Pugliese2020
].
To quantify the notion of linkage, [ Powar2023 ] introduces the idea of an anonymity set . In the VC case we are concerned with here, the anonymity set would contain the holder of a particular VC and other holders associated with a particular issuer . The smaller the anonymity set the more likely the holder can be tracked across verifiers. Since a signed VC contains a reference to a public key of the issuer, the starting size for the anonymity set for a holder possessing a VC from a particular issuer is the number of VC issued by that issuer with that particular public/private key pair. Non-malicious issuers are expected to minimize the number of public/private key pairs used to issue VCs. Note that the anonymity set idea is similar to the group privacy concept in [ vc-bitstring-status-list ]. When we use the term linkage here we generally mean any mechanism that results in a reduction in size of the anonymity set.
Sources of linkage in a VC system supporting selective disclosure:
We discuss each of these below.
Cryptographic Hashes, HMACs, and digital signatures by their nature generate highly unique identifiers. The output of a hash function such as SHA-256, by its collision resistance properties, are guaranteed to be essentially unique given different inputs and result in a strong linkage, i.e., reduces the anonymity set size to one. Similarly deterministic signature algorithms such as Ed25519 and deterministic ECDSA will produce essentially unique outputs for different inputs and lead to strong linkages.
This implies that holders can be easily tracked across verifiers via digital signature, HMAC, or hash artifacts inside VCs and hence are vulnerable to verifier-verifier collusion and verifier-issuer collusion. Randomized signature algorithms such as some forms of ECDSA can permit the issuer to generate many distinct signatures on the same inputs and send these to the holder for use with different verifiers . Such an approach could be used to prevent verifier-verifier collusion based tracking but cannot help with verifier-issuer collusion.
To
achieve
unlinkability
requires
specially
designed
cryptographic
signature
schemes
that
allow
the
holder
to
generate
what
is
called
a
zero
knowledge
proof
of
knowledge
of
a
signature
(ZKPKS).
What
this
means
is
that
the
holder
can
take
a
signature
from
the
issuer
in
such
a
scheme,
compute
a
ZKPKS
to
send
to
a
verifier
.
This
ZKPKS
cannot
be
linked
back
to
the
original
signature,
but
has
all
the
desirable
properties
of
a
signature,
i.e.,
the
verifier
can
use
it
to
verify
that
the
messages
were
signed
by
the
issuers
public
key
and
that
the
messages
have
not
been
altered.
In
addition,
the
holder
can
generate
as
many
ZKPKSs
as
desired
for
different
verifiers
and
these
are
essentially
independent
and
unlinkable.
BBS
is
one
such
signature
scheme
that
supports
this
capability.
Although the ZKPKS, known as a BBS proof in this document, has guaranteed unlinkability properties. BBS when used with selective disclosure has two artifacts that can contribute to linkability. These are the total number of messages originally signed, and the index values for the revealed statements. See the privacy considerations in [ CFRG-BBS-SIGNATURE ] for a discussion and mitigation techniques.
As
mentioned
in
the
section
on
Issuer's
Public
Keys
of
[
CFRG-BBS-SIGNATURE
]
there
is
the
potential
threat
that
an
issuer
might
use
multiple
public
keys
with
some
of
those
used
to
track
a
specific
subset
of
users
via
verifier-issuer
collusion.
Since
the
issuers
public
key
has
to
be
visible
to
the
verifier
,
i.e.,
it
is
referenced
in
the
BBS
proof
(derived
proof)
this
can
be
used
as
a
linkage
point
if
the
issuer
has
many
different
public
keys
and
particularly
if
it
uses
a
subset
of
those
keys
with
a
small
subset
of
users
(
holders
).
We
saw
in
the
section
on
information
leakage
that
RDF
canonicalization
uses
a
hash
function
to
order
statements
and
that
a
further
shuffle
of
the
order
of
the
statements
is
performed
based
on
an
HMAC.
This
can
leave
a
fingerprint
that
might
allow
for
some
linkage.
How
strong
of
a
linkage
is
dependent
on
the
number
of
blank
nodes,
essentially
JSON
objects
within
the
VC,
and
the
number
of
indexes
revealed.
Given
n
blank
nodes
and
k
disclosed
indexes
in
the
worst
case
this
would
be
a
reduction
in
the
anonymity
set
size
by
a
factor
of
C(n,
k)
,
i.e.,
the
number
combinations
of
size
k
chosen
from
a
set
of
n
elements.
One
can
keep
this
number
quite
low
by
reducing
the
number
of
blank
nodes
in
the
VC,
e.g.,
keep
the
VC
short
and
simple.
JSON-LD
is
a
JSON-based
format
for
serialization
of
Linked
Data.
As
such,
it
supports
assigning
a
globally
unambiguous
@id
attribute
(node
identifier)
to
each
object
("node",
in
JSON-LD
terminology)
within
a
document.
This
allows
for
the
linking
of
linked
data
,
enabling
information
about
the
same
entity
to
be
correlated.
This
correlation
can
be
desirable
or
undesirable,
depending
on
the
use
case.
When
using
BBS
for
its
unlinkability
feature,
globally
unambiguous
node
identifiers
cannot
be
used
for
individuals
nor
for
their
personally
identifiable
information,
since
the
strong
linkage
they
provide
is
undesirable.
Note
that
the
use
of
such
identifiers
is
acceptable
when
expressing
statements
about
non-personal
information
(e.g.,
using
a
globally
unambiguous
identifier
to
identify
a
large
country
or
a
concert
event).
Also
note
that
JSON-LD's
use
of
@context
,
which
maps
terms
to
IRIs,
does
not
generally
affect
unlinkability.
In
the
[
vc-data-integrity
]
specification,
a
number
of
properties
of
the
proof
attribute
of
a
VC
are
given.
Care
has
to
be
taken
that
optional
fields
ought
not
provide
strong
linkage
across
verifiers.
The
optional
fields
include:
id
,
created
,
expires
,
domain
,
challenge
,
and
nonce
.
For
example
the
optional
created
field
is
a
dateTimeStamp
object
which
can
specify
the
creation
date
for
the
proof
down
to
an
arbitrary
sub-second
granularity.
Such
information,
if
present,
could
greatly
reduce
the
size
of
the
anonymity
set.
If
the
issuer
wants
to
include
such
information
they
ought
to
make
it
as
coarse
grained
as
possible,
relative
to
the
number
of
VCs
being
issued
over
time.
The
issuer
can
also
compel
a
holder
to
reveal
certain
statements
to
a
verifier
via
the
mandatoryPointers
input
used
in
the
creation
of
the
Base
Proof
.
See
section
3.4.2
Base
Proof
Transformation
(bbs-2023)
,
Example
9
,
and
Example
10
.
By
compel
we
mean
that
a
generated
Derived
Proof
will
not
verify
unless
these
statements
are
revealed
to
the
verifier
.
Care
should
be
taken
such
that
if
such
information
is
required
to
be
disclosed,
that
the
anonymity
set
remains
sufficiently
large.
As discussed in [ Powar2023 ] there are many documented cases of re-identification of individuals from linkage attacks. Hence the holder is urged to reveal as little information as possible to help keep the anonymity set large. In addition, it has been shown a number of times that innocuous seeming information can be highly unique and thus leading to re-identification or tracking. See [ NISTIR8053 ] for a walk through of a particularly famous case of a former governor of Massachusetts and [ Powar2023 ] for further analysis and categorization of 94 such public cases.
It ought to be pointed out that maintaining unlinkability, i.e., anonymity, requires care in the systems holding and communicating the VCs. Networking artifacts such as IP address (layer 3) or Ethernet/MAC address (layer 2) are well known sources of linkage. For example, mobile phone MAC addresses can be used to track users if they revisited a particular access point, this led to mobile phone manufacturers providing a MAC address randomization feature. Public IP addresses generally provide enough information to geolocate an individual to a city or region within a country potentially greatly reducing the anonymity set.
This section is non-normative.
Demonstration of selective disclosure features including mandatory disclosure, selective disclosure, and overlap between those, requires an input credential document with more content than previous test vectors. To avoid excessively long test vectors, the starting document test vector is based on a purely fictitious windsurfing (sailing) competition scenario. In addition, we break the test vectors into two groups, based on those that would be generated by the issuer (base proof) and those that would be generated by the holder (derived proof).
To add a selective disclosure base proof to a document, the issuer needs the following cryptographic key material:
The key material used for generating the test vectors to test add base proof is shown below. Hexadecimal representation is used for the BBS key pairs and the HMAC key.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/BBSKeyMaterial.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/BBSKeyMaterial.json</pre> </body> </html>
In our scenario, a sailor is registering with a race organizer for a series of windsurfing races to be held over a number of days on Maui. The organizer will inspect the sailor's equipment to certify that what has been declared is accurate. The sailor's unsigned equipment inventory is shown below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/windDoc.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/windDoc.json</pre> </body> </html>
In addition to letting other sailors know what kinds of equipment their competitors may be sailing on, it is mandatory that each sailor disclose the year of their most recent windsurfing board and full details on two of their sails. Note that all sailors are identified by a sail number that is printed on all their equipment. This mandatory information is specified via an array of JSON pointers as shown below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/windMandatory.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/windMandatory.json</pre> </body> </html>
The result of applying the above JSON pointers to the sailor's equipment document is shown below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/addPointerValues.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/addPointerValues.json</pre> </body> </html>
Transformation of the unsigned document begins with canonicalizing the document, as shown below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/addBaseDocCanon.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/addBaseDocCanon.json</pre> </body> </html>
To prevent possible information leakage from the ordering of the blank node IDs these are processed through a PRF (i.e., the HMAC) to give the canonicalized HMAC document shown below. This represents an ordered list of statements that will be subject to mandatory and selective disclosure, i.e., it is from this list that statements are grouped.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/addBaseDocHMACCanon.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/addBaseDocHMACCanon.json</pre> </body> </html>
The above canonical document gets grouped into mandatory and non-mandatory statements. The final output of the selective disclosure transformation process is shown below. Each statement is now grouped as mandatory or non-mandatory, and its index in the previous list of statements is remembered.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/addBaseTransform.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/addBaseTransform.json</pre> </body> </html>
The next step is to create the base proof configuration and canonicalize it. This is shown in the following two examples.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/addProofConfig.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/addProofConfig.json</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/addProofConfigCanon.txt</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/addProofConfigCanon.txt</pre> </body> </html>
In
the
hashing
step,
we
compute
the
SHA-256
hash
of
the
canonicalized
proof
options
to
produce
the
proofHash
,
and
we
compute
the
SHA-256
hash
of
the
join
of
all
the
mandatory
N-Quads
to
produce
the
mandatoryHash
.
These
are
shown
below
in
hexadecimal
format.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/addHashData.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/addHashData.json</pre> </body> </html>
Shown
below
are
the
computed
bbsSignature
in
hexadecimal,
and
the
mandatoryPointers
.
These
are
are
fed
to
the
final
serialization
step
with
the
hmacKey
.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/addRawBaseSignatureInfo.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/addRawBaseSignatureInfo.json</pre> </body> </html>
Finally,
the
values
above
are
run
through
the
algorithm
of
Section
3.3.1
serializeBaseProofValue
,
to
produce
the
proofValue
which
is
used
in
the
signed
base
document
shown
below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/addSignedSDBase.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/addSignedSDBase.json</pre> </body> </html>
Random
numbers
are
used,
and
an
optional
presentationHeader
can
be
an
input,
for
the
creation
of
BBS
proofs
.
To
furnish
a
deterministic
set
of
test
vectors,
we
used
the
Mocked
Random
Scalars
procedure
from
[
CFRG-BBS-SIGNATURE
].
The
seed
and
presentationHeader
values
we
used
for
generation
of
the
derived
proof
test
vectors
are
given
in
hex,
below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/BBSDeriveMaterial.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/BBSDeriveMaterial.json</pre> </body> </html>
To
create
a
derived
proof,
a
holder
starts
with
a
signed
document
containing
a
base
proof.
The
base
document
we
will
use
for
these
test
vectors
is
the
final
example
from
Section
A.1
Base
Proof
,
above.
The
first
step
is
to
run
the
algorithm
of
Section
3.3.2
parseBaseProofValue
to
recover
bbsSignature
,
hmacKey
,
and
mandatoryPointers
,
as
shown
below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/derivedRecoveredBaseData.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/derivedRecoveredBaseData.json</pre> </body> </html>
Next, the holder needs to indicate what else, if anything, they wish to reveal to the verifiers, by specifying JSON pointers for selective disclosure. In our windsurfing competition scenario, a sailor (the holder) has just completed their first day of racing, and wishes to reveal to the general public (the verifiers) all the details of the windsurfing boards they used in the competition. These are shown below. Note that this slightly overlaps with the mandatory disclosed information which included only the year of their most recent board.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/windSelective.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/windSelective.json</pre> </body> </html>
To
produce
the
revealDocument
(i.e.,
the
unsigned
document
that
will
eventually
be
signed
and
sent
to
the
verifier),
we
append
the
selective
pointers
to
the
mandatory
pointers,
and
input
these
combined
pointers
along
with
the
document
without
proof
to
the
selectJsonLd
algorithm
of
[
DI-ECDSA
],
to
get
the
result
shown
below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/derivedUnsignedReveal.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/derivedUnsignedReveal.json</pre> </body> </html>
Now that we know what the revealed document looks like, we need to furnish appropriately updated information to the verifier about which statements are mandatory, and the indexes for the selected non-mandatory statements. Running step 6 of the 3.3.3 createDisclosureData yields an abundance of information about various statement groups relative to the original document. Below we show a portion of the indexes for those groups.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/derivedGroupIndexes.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/derivedGroupIndexes.json</pre> </body> </html>
The
verifier
needs
to
be
able
to
aggregate
and
hash
the
mandatory
statements.
To
enable
this,
we
furnish
them
with
a
list
of
indexes
of
the
mandatory
statements
adjusted
to
their
positions
in
the
reveal
document
(i.e.,
relative
to
the
combinedIndexes
),
while
the
selectiveIndexes
need
to
be
adjusted
relative
to
their
positions
within
the
nonMandatoryIndexes
.
These
"adjusted"
indexes
are
shown
below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/derivedAdjIndexes.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/derivedAdjIndexes.json</pre> </body> </html>
The
last
important
piece
of
disclosure
data
is
a
mapping
of
canonical
blank
node
IDs
to
HMAC-based
shuffled
IDs,
the
labelMap
,
computed
according
to
Section
3.3.3
createDisclosureData
.
This
is
shown
below
along
with
the
rest
of
the
disclosure
data
minus
the
reveal
document.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/derivedDisclosureData.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/derivedDisclosureData.json</pre> </body> </html>
Finally, using the disclosure data above with the algorithm of Section 3.3.6 serializeDerivedProofValue , we obtain the signed derived (reveal) document shown below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/wFDzTH/TestVectors/derivedRevealDocument.json</pre><pre>Cannot GET /uploads/sv2FpN/TestVectors/derivedRevealDocument.json</pre> </body> </html>
Portions of the work on this specification have been funded by the United States Department of Homeland Security's (US DHS) Silicon Valley Innovation Program under contracts 70RSAT20T00000003, and 70RSAT20T00000033. The content of this specification does not necessarily reflect the position or the policy of the U.S. Government and no official endorsement should be inferred.