W3C
Candidate
Recommendation
Draft
20
Copyright © 2024 World Wide Web Consortium . W3C ® liability , trademark and permissive document license rules apply.
This
specification
describes
a
Data
Integrity
cryptographic
suite
for
use
when
creating
or
verifying
a
digital
signature
using
the
twisted
Edwards
Curve
the
Ed25519
instantiation
of
the
Edwards-Curve
Digital
Signature
Algorithm
(EdDSA)
and
Curve25519
(ed25519).
(EdDSA).
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 Draft using the Recommendation track .
Publication as a Candidate Recommendation does not imply endorsement by W3C and its Members. A Candidate Recommendation Draft integrates changes from the previous Candidate Recommendation that the Working Group intends to include in a subsequent Candidate Recommendation Snapshot.
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 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 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
proofs
for
Ed25519
EdDSA
signatures
in
conformance
with
the
Data
Integrity
[
VC-DATA-INTEGRITY
]
specification.
The
approach
is
accepted
by
the
U.S.
National
Institute
of
Standards
in
the
latest
FIPS
186-5
[
FIPS-186-5
]
publication
and
meets
U.S.
Federal
Information
Processing
requirements
when
using
cryptography
to
secure
digital
information.
The suites described in this specification use the RDF Dataset Canonicalization Algorithm [ RDF-CANON ] or the JSON Canonicalization Scheme [ RFC8785 ] to transform an input document into its canonical form. The canonical representation is then hashed and signed with a detached signature algorithm.
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 , 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.
These
parts
would
have
to
be
removed
in
order
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 verification methods, such as cryptographic public keys, and data integrity proofs, such as digital signatures.
This cryptographic suite is used to verify Data Integrity Proofs [ VC-DATA-INTEGRITY ] produced using Edwards Curve cryptographic key material. The encoding formats for those key types are provided in this section. Lossless cryptographic key transformation processes that result in equivalent cryptographic key material MAY be used for the processing of digital signatures.
The
Multikey
format
,
defined
in
[
VC-DATA-INTEGRITY
Controller
Documents
1.0
],
,
is
used
to
express
public
keys
for
the
cryptographic
suites
defined
in
this
specification.
The
publicKeyMultibase
value
of
the
verification
method
MUST
start
with
the
base-58-btc
prefix
(
z
),
as
defined
in
the
Multibase
section
of
[
VC-DATA-INTEGRITY
Controller
Documents
1.0
].
.
A
Multibase-encoded
Multikey
value
follows,
which
MUST
consist
of
a
binary
value
that
starts
with
the
two-byte
prefix
0xed01
,
which
is
the
Multikey
header
for
an
Ed25519
public
key,
followed
by
the
32-byte
public
key
data,
all
of
which
is
then
encoded
using
base-58-btc.
Any
other
encoding
MUST
NOT
be
allowed.
Developers
are
advised
to
not
accidentally
publish
a
representation
of
a
private
key.
Implementations
of
this
specification
will
raise
errors
if
they
encounter
a
Multikey
prefix
value
other
than
0xed01
in
a
publicKeyMultibase
value.
{
"id": "https://example.com/issuer/123#key-0",
"type": "Multikey",
"controller": "https://example.com/issuer/123",
"publicKeyMultibase": "z6Mkf5rGMoatrSj1f4CyvuHBeXJELe9RPdzo2PKGNCKVtZxP"
}
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/multikey/v1"
],
"id": "did:example:123",
"verificationMethod": [{
"id": "did:example:123#key-0",
"type": "Multikey",
"controller": "did:example:123",
"publicKeyMultibase": "z6Mkf5rGMoatrSj1f4CyvuHBeXJELe9RPdzo2PKGNCKVtZxP"
}],
"authentication": [
"did:example:123#key-0"
],
"assertionMethod": [
"did:example:123#key-0"
],
"capabilityDelegation": [
"did:example:123#key-0"
],
"capabilityInvocation": [
"did:example:123#key-0"
]
}
The
secretKeyMultibase
property
represents
a
Multibase-encoded
Multikey
expression
of
an
Ed25519
secret
key
(sometimes
also
referred
to
as
a
private
key).
The
value
starts
with
the
two-byte
prefix
0x8026
,
followed
by
the
32-byte
Ed25519
secret
key
data.
The
combined
34-byte
value
is
then
base58-btc
encoded
and
z
is
added
as
the
prefix
on
the
encoded
value.
Developers
are
advised
to
prevent
accidental
publication
of
a
representation
of
a
secret
key,
and
to
not
export
the
secretKeyMultibase
property
by
default,
when
serializing
key
pairs
to
Multikey.
This section details the proof representation formats that are defined by this specification.
A proof contains the attributes specified in the Proofs section of [ VC-DATA-INTEGRITY ] with the following restrictions.
The
type
property
MUST
be
DataIntegrityProof
.
The
cryptosuite
property
of
the
proof
MUST
be
eddsa-rdfc-2022
or
eddsa-jcs-2022
.
The
proofValue
property
of
the
proof
MUST
be
a
detached
EdDSA
signature
produced
according
to
[
RFC8032
],
encoded
using
the
base-58-btc
header
and
alphabet
as
described
in
the
Multibase
section
of
[
VC-DATA-INTEGRITY
Controller
Documents
1.0
].
.
{
"@context": [
{"myWebsite": "https://vocabulary.example/myWebsite"},
"https://www.w3.org/ns/credentials/v2"
],
"myWebsite": "https://hello.world.example/",
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-rdfc-2022",
"created": "2023-02-24T23:36:38Z",
"verificationMethod": "https://vc.example/issuers/5678#z6MkrJVnaZkeFzdQyMZu1
cgjg7k1pZZ6pvBQ7XJPt4swbTQ2",
"proofPurpose": "assertionMethod",
"proofValue": "z5C5b1uzYJN6pDR3aWgAqUMoSB1JY29epA74qyjaie9qh4okm9DZP6y77eTNq
5NfYyMwNu9bpQQWUHKH5zAmEtszK"
}
}
The
following
section
describes
multiple
Data
Integrity
cryptographic
suites
that
utilize
use
the
twisted
Edwards
Curve
Edwards-Curve
Digital
Signature
Algorithm.
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
.
eddsa-rdfc-2022
:
eddsa-jcs-2022
:
The
eddsa-rdfc-2022
cryptographic
suite
takes
an
input
document,
canonicalizes
the
document
using
the
RDF
Dataset
Canonicalization
algorithm
[
RDF-CANON
],
and
then
cryptographically
hashes
and
signs
the
output
resulting
in
the
production
of
a
data
integrity
proof.
The
algorithms
in
this
section
also
include
the
verification
of
such
a
data
integrity
proof.
When the RDF Dataset Canonicalization Algorithm [ RDF-CANON ] is used, implementations will detect dataset poisoning by default, and abort processing upon such detection.
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 verify a data integrity proof given an secured data document . Required inputs are an secured data document ( map securedDocument ). This algorithm returns a verification result , which is a struct whose items are:
true
or
false
false
,
Null
;
otherwise,
an
unsecured
data
document
proof
value
removed.
proofValue
removed.
true
,
unsecuredDocument
;
otherwise,
Null
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.2.4 Hashing (eddsa-rdfc-2022) .
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
)
and
a
cryptosuite
identifier
(
cryptosuite
).
A
transformed
data
document
is
produced
as
output.
Whenever
this
algorithm
encodes
strings,
it
MUST
use
UTF-8
encoding.
options
.
type
is
not
set
to
the
string
DataIntegrityProof
and
options
.
cryptosuite
is
not
set
to
the
string
eddsa-rdfc-2022
,
an
error
MUST
be
raised
that
SHOULD
convey
an
error
type
of
PROOF_TRANSFORMATION_ERROR
.
canonicalDocument
as
the
transformed
data
document
.
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.2.6 Proof Serialization (eddsa-rdfc-2022) or Section 3.2.7 Proof Verification (eddsa-rdfc-2022) .
The
required
inputs
to
this
algorithm
are
a
transformed
data
document
(
transformedDocument
)
and
canonical
proof
configuration
(
canonicalProofConfig
).
A
single
hash
data
value
represented
as
series
of
bytes
is
produced
as
output.
proofConfigHash
be
the
result
of
applying
the
SHA-256
(SHA-2
with
256-bit
output)
cryptographic
hashing
algorithm
[
RFC6234
]
to
the
canonicalProofConfig
.
proofConfigHash
will
be
exactly
32
bytes
in
size.
transformedDocumentHash
be
the
result
of
applying
the
SHA-256
(SHA-2
with
256-bit
output)
cryptographic
hashing
algorithm
[
RFC6234
]
to
the
transformedDocument
.
transformedDocumentHash
will
be
exactly
32
bytes
in
size.
hashData
be
the
result
of
concatenating
proofConfigHash
(the
first
hash
produced
above)
followed
by
transformedDocumentHash
(the
second
hash
produced
above).
hashData
as
the
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 proof hashing algorithm .
The
required
inputs
to
this
algorithm
are
the
document
(
unsecuredDocument
)
and
the
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.
DataIntegrityProof
and/or
proofConfig
.
cryptosuite
is
not
set
to
eddsa-rdfc-2022
,
an
error
MUST
be
raised
and
SHOULD
convey
an
error
type
of
PROOF_GENERATION_ERROR
.
@context
to
unsecuredDocument
.
@context
.
The
following
algorithm
specifies
how
to
serialize
a
digital
signature
from
a
set
of
cryptographic
hash
data.
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
).
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.
privateKeyBytes
be
the
result
of
retrieving
the
private
key
bytes
associated
with
the
options
.
verificationMethod
value
as
described
in
the
Data
Integrity
[
VC-DATA-INTEGRITY
]
specification,
Section
proofBytes
be
the
result
of
applying
the
Edwards-Curve
Digital
Signature
Algorithm
(EdDSA)
[
RFC8032
],
using
the
Ed25519
variant
(Pure
EdDSA),
with
hashData
as
the
data
to
be
signed
using
the
private
key
specified
by
privateKeyBytes
.
proofBytes
will
be
exactly
64
bytes
in
size.
proofBytes
as
the
digital
proof
.
The
following
algorithm
specifies
how
to
verify
a
digital
signature
from
a
set
of
cryptographic
hash
data.
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
),
a
digital
signature
(
proofBytes
)
and
proof
options
(
options
).
A
verification
result
represented
as
a
boolean
value
is
produced
as
output.
publicKeyBytes
be
the
result
of
retrieving
the
public
key
bytes
associated
with
the
options
.
verificationMethod
value
as
described
in
the
verificationResult
be
the
result
of
applying
the
verification
algorithm
for
the
Edwards-Curve
Digital
Signature
Algorithm
(EdDSA)
[
RFC8032
],
using
the
Ed25519
variant
(Pure
EdDSA),
with
hashData
as
the
data
to
be
verified
against
the
proofBytes
using
the
public
key
specified
by
publicKeyBytes
.
verificationResult
as
the
verification
result
.
The
eddsa-jcs-2022
cryptographic
suite
takes
an
input
document,
canonicalizes
the
document
using
the
JSON
Canonicalization
Scheme
[
RFC8785
],
and
then
cryptographically
hashes
and
signs
the
output
resulting
in
the
production
of
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.
unsecuredDocument
.
@context
is
present,
set
proof
.
@context
to
unsecuredDocument
.
@context
.
The following algorithm specifies how to verify a data integrity proof given an secured data document . Required inputs are an secured data document ( map securedDocument ). This algorithm returns a verification result , which is a struct whose items are:
true
or
false
true
,
an
unsecured
data
document
;
otherwise
Null
proof
value
removed.
proofValue
removed.
false
and
skip
to
the
last
step.
true
,
unsecuredDocument
;
otherwise,
Null
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.3.4 Hashing (eddsa-jcs-2022) .
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
)
and
a
cryptosuite
identifier
(
cryptosuite
).
A
transformed
data
document
is
produced
as
output.
Whenever
this
algorithm
encodes
strings,
it
MUST
use
UTF-8
encoding.
options
.
type
is
not
set
to
the
string
DataIntegrityProof
and
options
.
cryptosuite
is
not
set
to
the
string
eddsa-jcs-2022
,
an
error
MUST
be
raised
that
SHOULD
convey
an
error
type
of
PROOF_VERIFICATION_ERROR
.
canonicalDocument
be
the
result
of
applying
the
JSON
Canonicalization
Scheme
[
RFC8785
]
to
a
JSON
serialization
of
the
unsecuredDocument
.
canonicalDocument
as
the
transformed
data
document
.
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.3.6 Proof Serialization (eddsa-jcs-2022) or Section 3.3.7 Proof Verification (eddsa-jcs-2022) .
The
required
inputs
to
this
algorithm
are
a
transformed
data
document
(
transformedDocument
)
and
canonical
proof
configuration
(
canonicalProofConfig
).
A
single
hash
data
value
represented
as
series
of
bytes
is
produced
as
output.
transformedDocumentHash
be
the
result
of
applying
the
SHA-256
(SHA-2
with
256-bit
output)
cryptographic
hashing
algorithm
[
RFC6234
]
to
the
transformedDocument
.
transformedDocumentHash
will
be
exactly
32
bytes
in
size.
proofConfigHash
be
the
result
of
applying
the
SHA-256
(SHA-2
with
256-bit
output)
cryptographic
hashing
algorithm
[
RFC6234
]
to
the
canonicalProofConfig
.
proofConfigHash
will
be
exactly
32
bytes
in
size.
hashData
be
the
result
of
joining
proofConfigHash
(the
first
hash)
with
transformedDocumentHash
(the
second
hash).
hashData
as
the
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 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.
proofConfig
be
a
clone
of
the
options
object.
proofConfig
.
type
is
not
set
to
DataIntegrityProof
or
proofConfig
.
cryptosuite
is
not
set
to
eddsa-jcs-2022
,
an
error
MUST
be
raised
that
SHOULD
convey
an
error
type
of
PROOF_GENERATION_ERROR
.
canonicalProofConfig
be
the
result
of
applying
the
JSON
Canonicalization
Scheme
[
RFC8785
]
to
the
proofConfig
.
canonicalProofConfig
.
The
following
algorithm
specifies
how
to
serialize
a
digital
signature
from
a
set
of
cryptographic
hash
data.
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
).
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.
privateKeyBytes
be
the
result
of
retrieving
the
private
key
bytes
associated
with
the
options
.
verificationMethod
value
as
described
in
the
Data
Integrity
[
VC-DATA-INTEGRITY
]
specification,
Section
4:
Retrieving
Cryptographic
Material
.
proofBytes
be
the
result
of
applying
the
Edwards-Curve
Digital
Signature
Algorithm
(EdDSA)
[
RFC8032
],
using
the
Ed25519
variant
(Pure
EdDSA),
with
hashData
as
the
data
to
be
signed
using
the
private
key
specified
by
privateKeyBytes
.
proofBytes
will
be
exactly
64
bytes
in
size.
proofBytes
as
the
digital
proof
.
The
following
algorithm
specifies
how
to
verify
a
digital
signature
from
a
set
of
cryptographic
hash
data.
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
),
a
digital
signature
(
proofBytes
)
and
proof
options
(
options
).
A
verification
result
represented
as
a
boolean
value
is
produced
as
output.
publicKeyBytes
be
the
result
of
retrieving
the
public
key
bytes
associated
with
the
options
.
verificationMethod
value
as
described
in
the
Data
Integrity
[
VC-DATA-INTEGRITY
]
specification,
Section
4:
Retrieving
Cryptographic
Material
.
verificationResult
be
the
result
of
applying
the
verification
algorithm
for
the
Edwards-Curve
Digital
Signature
Algorithm
(EdDSA)
[
RFC8032
],
using
the
Ed25519
variant
(Pure
EdDSA),
with
hashData
as
the
data
to
be
verified
against
the
proofBytes
using
the
public
key
specified
by
publicKeyBytes
.
verificationResult
as
the
verification
result
.
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 .
The following section describes security considerations that developers implementing this specification should be aware of in order to create secure software.
This section is non-normative.
Ed25519 signatures (EdDSA algorithm with edwards25519 curve) have been widely adopted, due both to the compact size of the keys and signatures and to the speed at which signatures can be produced and verified. Many libraries exist that can create and verify Ed25519 signatures. Since the publication of [ RFC8032 ], security properties of Ed25519 signatures have been rigorously proven (see [ Provable_Ed25519 ] and [ Taming_EdDSAs ]). However, it has been observed that a significant number of libraries do not achieve these security levels, due to missing input validity checks during the signature verification process. In this section, we summarize the security levels achievable with Ed25519 signatures, and indicate how one can determine whether a library will support those levels.
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). If 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 not only cannot sign new messages, but also cannot find a new signature on an old message. See [ Provable_Ed25519 ] for a real world attack that would have been circumvented with SUF-CMA security over EUF-CMA security.
Binding signature (BS) We say that a signature scheme is binding if no efficient signer can output a tuple , where both and are valid message signature pairs under the public key and (except with negligible probability). A binding signature makes it impossible for the signer to claim later that it has signed a different message; the signature binds the signer to the message.
Strongly Binding signature (SBS) Certain applications may require a signature to not only be binding to the message but also be binding to the public key. We say that a signature scheme is strongly-binding if any efficient signer cannot output a tuple , where is a valid signature for the public key and is a valid signature for the public key and either or , or both (except with negligible probability). See [ Provable_Ed25519 ] for real world attacks that would have been circumvented with the SBS property.
Note that the BS and SBS properties are forms of non-repudiation .
As pointed out in [ Taming_EdDSAs ], flaws in Ed25519 libraries primarily occur on the signature verification side, where edge cases are sometimes not properly checked. An Ed25519 signature library that is in conformance with [ RFC8032 ] or [ FIPS-186-5 ], i.e., one that performs all specified validation checks, will have the SUF-CMA property in addition to EUF-CMA .
Reference [ Taming_EdDSAs ] achieves the BS and SBS properties along with SUF-CMA in their "signature verification algorithm 2" where an additional check is performed against the public key A to make sure that it is not one of eight "small order points". These additional checks incur minimal processing overhead.
Reference [ Taming_EdDSAs ] included a set of twelve test vectors to test various Ed25519 libraries available at the time of publication. They found that a significant portion missed edge cases and hence did not achieve SUF-CMA (just EUF-CMA), and only two libraries out of sixteen achieved all the security properties. Since the time of publication, more Ed25519 libraries have been created, and some of the libraries have been updated to include all verification checks. Implementers are recommended to test the Ed25519 library they are using against the test vectors of [ Taming_EdDSAs ].
Before reading this section, readers are urged to familiarize themselves with general privacy advice provided in the Privacy Considerations section of the Data Integrity specification .
The following section describes privacy considerations that developers implementing this specification should be aware of in order to avoid violating privacy assumptions.
This cryptography suite does not provide for selective disclosure or unlinkability. If signatures are re-used, they can be used as correlatable data.
Ed25519Signature2020
is
an
earlier
version
of
a
cryptographic
suite
for
use
of
the
EdDSA
algorithm
and
Curve25519.
While
it
has
been
used
in
production
systems,
new
implementations
should
instead
use
eddsa-rdfc-2022
.
Ed25519Signature2020
has
been
kept
in
this
specification
to
provide
a
stable
reference.
We
need
to
add
documentation
to
note
that
this
key
format
is
deployed
and
widely
used
in
production,
but
is
deprecated.
Multikey
and
JsonWebKey
supersede
it.
The
type
of
the
verification
method
MUST
be
Ed25519VerificationKey2020
.
The
controller
of
the
verification
method
MUST
be
a
URL.
The
publicKeyMultibase
value
of
the
verification
method
MUST
start
with
the
base-58-btc
prefix
(
z
),
as
defined
in
the
Multibase
section
of
[
VC-DATA-INTEGRITY
].
A
Multibase-encoded
Multikey
value
follows,
which
MUST
consist
of
a
binary
value
that
starts
with
the
two-byte
prefix
0xed01
,
which
is
the
Multikey
header
for
an
Ed25519
public
key,
followed
by
the
32-byte
public
key
data,
all
of
which
is
then
encoded
using
base-58-btc.
Any
other
encoding
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
Multikey
header
value
other
than
0xed01
being
used
in
a
publicKeyMultibase
value.
{
"id": "https://example.com/issuer/123#key-0",
"type": "Ed25519VerificationKey2020",
"controller": "https://example.com/issuer/123",
"publicKeyMultibase": "z6Mkf5rGMoatrSj1f4CyvuHBeXJELe9RPdzo2PKGNCKVtZxP"
}
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/ed25519-2020/v1"
],
"id": "did:example:123",
"verificationMethod": [{
"id": "did:example:123#key-0",
"type": "Ed25519VerificationKey2020",
"controller": "did:example:123",
"publicKeyMultibase": "z6Mkf5rGMoatrSj1f4CyvuHBeXJELe9RPdzo2PKGNCKVtZxP"
}],
"authentication": [
"did:example:123#key-0"
],
"assertionMethod": [
"did:example:123#key-0"
],
"capabilityDelegation": [
"did:example:123#key-0"
],
"capabilityInvocation": [
"did:example:123#key-0"
]
}
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
Ed25519VerificationKey2020
.
The
type
property
of
the
proof
MUST
be
Ed25519Signature2020
.
The
created
property
of
the
proof
MUST
be
an
[
XMLSCHEMA11-2
]
formatted
date
string.
The
proofPurpose
property
of
the
proof
MUST
be
a
string,
and
MUST
match
the
verification
relationship
expressed
by
the
verification
method
controller
.
The
proofValue
property
of
the
proof
MUST
be
a
detached
EdDSA
produced
according
to
[
RFC8032
],
encoded
using
the
base-58-btc
header
and
alphabet
as
described
in
the
Multibase
section
of
[
VC-DATA-INTEGRITY
].
{
"@context": [
{"myWebsite": "https://vocabulary.example/myWebsite"},
"https://w3id.org/security/suites/ed25519-2020/v1"
],
"myWebsite": "https://hello.world.example/",
"proof": {
"type": "Ed25519Signature2020",
"created": "2020-11-05T19:23:24Z",
"verificationMethod": "https://di.example/issuer#z6MkjLrk3gKS2nnkeWcmcxiZPGskmesDpuwRBorgHxUXfxnG",
"proofPurpose": "assertionMethod",
"proofValue": "z4oey5q2M3XKaxup3tmzN4DRFTLVqpLMweBrSxMY2xHX5XTYVQeVbY8nQAVHMrXFkXJpmEcqdoDwLWxaqA3Q1geV6"
}
}
The
Ed25519Signature2020
cryptographic
suite
takes
an
input
document,
canonicalizes
the
document
using
the
RDF
Dataset
Canonicalization
algorithm
[
RDF-CANON
],
and
then
cryptographically
hashes
and
signs
the
output
resulting
in
the
production
of
a
data
integrity
proof.
The
algorithms
in
this
section
also
include
the
verification
of
such
a
data
integrity
proof.
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 Section A.2.1.3 Transformation (Ed25519Signature2020) , the hashing algorithm is defined in Section A.2.1.4 Hashing (Ed25519Signature2020) , and the proof serialization algorithm is defined in Section A.2.1.6 Proof Serialization (Ed25519Signature2020) .
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 Section A.2.1.3 Transformation (Ed25519Signature2020) , the hashing algorithm is defined in Section A.2.1.4 Hashing (Ed25519Signature2020) , and the proof verification algorithm is defined in Section A.2.1.7 Proof Verification (Ed25519Signature2020) .
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 A.2.1.4 Hashing (Ed25519Signature2020) .
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
)
and
a
cryptosuite
identifier
(
cryptosuite
).
A
transformed
data
document
is
produced
as
output.
Whenever
this
algorithm
encodes
strings,
it
MUST
use
UTF-8
encoding.
options
.
type
is
not
set
to
the
string
Ed25519Signature2020
,
an
error
MUST
be
raised
that
SHOULD
convey
an
error
type
of
PROOF_TRANSFORMATION_ERROR
.
canonicalDocument
as
the
transformed
data
document
.
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 A.2.1.6 Proof Serialization (Ed25519Signature2020) or Section A.2.1.7 Proof Verification (Ed25519Signature2020) .
The
required
inputs
to
this
algorithm
are
a
transformed
data
document
(
transformedDocument
)
and
proof
configuration
(
proofConfig
).
The
proof
configuration
MUST
contain
a
type
identifier
for
the
cryptographic
suite
(
type
)
and
MAY
contain
a
cryptosuite
identifier
(
cryptosuite
).
A
single
hash
data
value
represented
as
series
of
bytes
is
produced
as
output.
transformedDocumentHash
be
the
result
of
applying
the
SHA-256
(SHA-2
with
256-bit
output)
cryptographic
hashing
algorithm
[
RFC6234
]
to
the
transformedDocument
.
transformedDocumentHash
will
be
exactly
32
bytes
in
size.
proofConfigHash
be
the
result
of
applying
the
SHA-256
(SHA-2
with
256-bit
output)
cryptographic
hashing
algorithm
[
RFC6234
]
to
the
canonicalProofConfig
.
proofConfigHash
will
be
exactly
32
bytes
in
size.
hashData
be
the
result
of
joining
proofConfigHash
(the
first
hash)
with
transformedDocumentHash
(the
second
hash).
hashData
as
the
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 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
MAY
contain
a
cryptosuite
identifier
(
cryptosuite
).
A
proof
configuration
object
is
produced
as
output.
proofConfig
.
type
is
not
set
to
Ed25519Signature2020
,
an
error
MUST
be
raised
and
SHOULD
convey
an
error
type
of
PROOF_GENERATION_ERROR
.
proofConfig
.
@context
to
unsecuredDocument
.
@context
canonicalProofConfig
be
the
result
of
applying
the
RDF
Dataset
Canonicalization
algorithm
[
RDF-CANON
]
to
the
proofConfig
.
canonicalProofConfig
.
The
following
algorithm
specifies
how
to
serialize
a
digital
signature
from
a
set
of
cryptographic
hash
data.
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
).
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.
privateKeyBytes
be
the
result
of
retrieving
the
private
key
bytes
associated
with
the
options
.
verificationMethod
value
as
described
in
the
Data
Integrity
[
VC-DATA-INTEGRITY
]
specification,
Section
4:
Retrieving
Cryptographic
Material
.
proofBytes
be
the
result
of
applying
the
Edwards-Curve
Digital
Signature
Algorithm
(EdDSA)
[
RFC8032
],
using
the
Ed25519
variant
(Pure
EdDSA),
with
hashData
as
the
data
to
be
signed
using
the
private
key
specified
by
privateKeyBytes
.
proofBytes
will
be
exactly
64
bytes
in
size.
proofBytes
as
the
digital
proof
.
The
following
algorithm
specifies
how
to
verify
a
digital
signature
from
a
set
of
cryptographic
hash
data.
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
),
a
digital
signature
(
proofBytes
)
and
proof
options
(
options
).
A
verification
result
represented
as
a
boolean
value
is
produced
as
output.
publicKeyBytes
be
the
result
of
retrieving
the
public
key
bytes
associated
with
the
options
.
verificationMethod
value
as
described
in
the
Data
Integrity
[
VC-DATA-INTEGRITY
]
specification,
Section
4:
Retrieving
Cryptographic
Material
.
verificationResult
be
the
result
of
applying
the
verification
algorithm
for
the
Edwards-Curve
Digital
Signature
Algorithm
(EdDSA)
[
RFC8032
],
using
the
Ed25519
variant
(Pure
EdDSA),
with
hashData
as
the
data
to
be
verified
against
the
proofBytes
using
the
public
key
specified
by
publicKeyBytes
.
verificationResult
as
the
verification
result
.
This section is non-normative.
The signer needs to generate a private/public key pair with the private key used for signing and the public key made available for verification. The representation of the public key and the representation of the private key are shown below.
{
publicKeyMultibase: "z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2",
privateKeyMultibase: "z3u2en7t5LR2WtQH5PfFqMqwVHBeXouLzo6haApm8XHqvjxq"
}
Signing begins with a credential without an attached proof, which is converted to canonical form, and then hashed, as shown in the following three examples.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/unsigned.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/unsigned.json</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-rdfc-2022/canonDocDataInt.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-rdfc-2022/canonDocDataInt.txt</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-rdfc-2022/docHashDataInt.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-rdfc-2022/docHashDataInt.txt</pre> </body> </html>
The next step is to take the proof options document, convert it to canonical form, and obtain its hash, as shown in the next three examples.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-rdfc-2022/proofConfigDataInt.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-rdfc-2022/proofConfigDataInt.json</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-rdfc-2022/proofCanonDataInt.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-rdfc-2022/proofCanonDataInt.txt</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-rdfc-2022/proofHashDataInt.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-rdfc-2022/proofHashDataInt.txt</pre> </body> </html>
Finally, we concatenate the hash of the proof options followed by the hash of the credential without proof, use the private key with the combined hash to compute the Ed25519 signature, and then base58-btc encode the signature.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-rdfc-2022/combinedHashDataInt.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-rdfc-2022/combinedHashDataInt.txt</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-rdfc-2022/sigHexDataInt.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-rdfc-2022/sigHexDataInt.txt</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-rdfc-2022/sigBTC58DataInt.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-rdfc-2022/sigBTC58DataInt.txt</pre> </body> </html>
Assemble the signed credential with the following two steps:
proofValue
field
with
the
previously
computed
base58-btc
value
to
the
proof
options
document.
proof
field
of
the
credential
to
the
augmented
proof
option
document.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-rdfc-2022/signedDataInt.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-rdfc-2022/signedDataInt.json</pre> </body> </html>
The signer needs to generate a private/public key pair with the private key used for signing and the public key made available for verification. The representation of the public key, and the representation of the private key are shown below.
{
publicKeyMultibase: "z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2",
privateKeyMultibase: "z3u2en7t5LR2WtQH5PfFqMqwVHBeXouLzo6haApm8XHqvjxq"
}
Signing begins with a credential without an attached proof, which is converted to canonical form, and then hashed, as shown in the following three examples.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/unsigned.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/unsigned.json</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-jcs-2022/canonDocJCS.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-jcs-2022/canonDocJCS.txt</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-jcs-2022/docHashJCS.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-jcs-2022/docHashJCS.txt</pre> </body> </html>
The next step is to take the proof options document, convert it to canonical form, and obtain its hash, as shown in the next three examples.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-jcs-2022/proofConfigJCS.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-jcs-2022/proofConfigJCS.json</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-jcs-2022/proofCanonJCS.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-jcs-2022/proofCanonJCS.txt</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-jcs-2022/proofHashJCS.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-jcs-2022/proofHashJCS.txt</pre> </body> </html>
Finally, we concatenate the hash of the proof options followed by the hash of the credential without proof, use the private key with the combined hash to compute the Ed25519 signature, and then base58-btc encode the signature.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-jcs-2022/combinedHashJCS.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-jcs-2022/combinedHashJCS.txt</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-jcs-2022/sigHexJCS.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-jcs-2022/sigHexJCS.txt</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-jcs-2022/sigBTC58JCS.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-jcs-2022/sigBTC58JCS.txt</pre> </body> </html>
Assemble the signed credential with the following two steps:
proofValue
field
with
the
previously
computed
base58-btc
value
to
the
proof
options
document.
proof
field
of
the
credential
to
the
augmented
proof
option
document.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/eddsa-jcs-2022/signedJCS.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/eddsa-jcs-2022/signedJCS.json</pre> </body> </html>
The signer needs to generate a private/public key pair with the private key used for signing and the public key made available for verification. The representation of the public key, and the representation of the private key, are shown below.
{
publicKeyMultibase: "z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2",
privateKeyMultibase: "z3u2en7t5LR2WtQH5PfFqMqwVHBeXouLzo6haApm8XHqvjxq"
}
Signing begins with a credential without an attached proof, which is converted to canonical form, and then hashed, as shown in the following three examples.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/unsigned.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/unsigned.json</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/Ed25519Signature2020/canonDocEdSig.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/Ed25519Signature2020/canonDocEdSig.txt</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/Ed25519Signature2020/docHashEdSig.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/Ed25519Signature2020/docHashEdSig.txt</pre> </body> </html>
The next step is to take the proof options document, convert it to canonical form, and obtain its hash, as shown in the next three examples.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/Ed25519Signature2020/proofConfigEdSig.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/Ed25519Signature2020/proofConfigEdSig.json</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/Ed25519Signature2020/proofCanonEdSig.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/Ed25519Signature2020/proofCanonEdSig.txt</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/Ed25519Signature2020/proofHashEdSig.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/Ed25519Signature2020/proofHashEdSig.txt</pre> </body> </html>
Finally, we concatenate the hash of the proof options followed by the hash of the credential without proof, use the private key with the combined hash to compute the Ed25519 signature, and then base58-btc encode the signature.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/Ed25519Signature2020/combinedHashEdSig.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/Ed25519Signature2020/combinedHashEdSig.txt</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/Ed25519Signature2020/sigHexEdSig.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/Ed25519Signature2020/sigHexEdSig.txt</pre> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/Ed25519Signature2020/sigBTC58EdSig.txt</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/Ed25519Signature2020/sigBTC58EdSig.txt</pre> </body> </html>
Assemble the signed credential with the following two steps:
proofValue
field
with
the
previously
computed
base58-btc
value
to
the
proof
options
document.
proof
field
of
the
credential
to
the
augmented
proof
option
document.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/Ed25519Signature2020/signedEdSig.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/Ed25519Signature2020/signedEdSig.json</pre> </body> </html>
Proof
sets
and
chains
are
defined
in
the
[
VC-DATA-INTEGRITY
].
We
provide
test
vectors
showing
the
creation
of
proof
sets
and
chains
with
the
eddsa-rdfc-2022
cryptosuite.
Multiple
signers
can
be
involved
in
the
generation
of
proof
sets
and
chains
so
multiple
public/private
key
pairs
are
needed.
These
are
shown
below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/proof-set-chain/multiKeyPairs.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/proof-set-chain/multiKeyPairs.json</pre> </body> </html>
The original unsigned credential is shown below:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/proof-set-chain/unsigned.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/proof-set-chain/unsigned.json</pre> </body> </html>
To
demonstrate
creating
a
proof
set,
we
start
with
a
document
containing
a
single
proof
and
add
another
proof
to
it.
The
starting
document
is
shown
below
and
contains
a
proof
signed
with
keyPair1
.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/proof-set-chain/signedProofSet1.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/proof-set-chain/signedProofSet1.json</pre> </body> </html>
The
options
input
to
Section
4.4:
Add
Proof
Set/Chain
in
[
VC-DATA-INTEGRITY
]
is
shown
below.
Note
that
it
does
not
include
a
previousProof
attribute
since
we
are
constructing
a
proof
set
and
not
a
chain.
In
addition,
we
will
be
using
keyPair2
for
signing.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/proof-set-chain/proofSetConfig2.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/proof-set-chain/proofSetConfig2.json</pre> </body> </html>
Per
the
algorithm
of
Section
4.4:
Add
Proof
Set/Chain
in
[
VC-DATA-INTEGRITY
],
we
create
an
array
variable,
allProofs
,
and
add
the
proof
from
the
starting
document
to
it.
Since
there
is
no
previousProof
attribute,
no
modification
of
unsignedDocument
is
needed
prior
to
computing
the
signed
proof
in
step
6
of
Section
4.4:
Add
Proof
Set/Chain
in
[
VC-DATA-INTEGRITY
].
The
signed
proof
configuration
is
shown
below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/proof-set-chain/proofSetConfigSigned2.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/proof-set-chain/proofSetConfigSigned2.json</pre> </body> </html>
The
signed
proof
options
above
gets
appended
to
the
allProofs
variable,
which
then
gets
set
as
the
proof
attribute
of
the
unsigned
document
to
produce
the
final
signed
document
as
shown
below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/proof-set-chain/signedProofSet2.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/proof-set-chain/signedProofSet2.json</pre> </body> </html>
This
collection
of
test
vectors
demonstrates
the
construction
a
proof
chain.
We
start
with
a
document
containing
a
proof
set,
i.e.,
our
previous
example,
and
then
add
a
new
proof
to
the
credential
that
has
a
dependency
on
the
existing
proofs.
This
example
also
demonstrates
the
case
where
the
previousProofs
attribute
is
an
array.
This
example
uses
keyPair3
and
the
starting
document
is
given
below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/proof-set-chain/signedProofSet2.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/proof-set-chain/signedProofSet2.json</pre> </body> </html>
The
options
input
to
Section
4.4:
Add
Proof
Set/Chain
in
[
VC-DATA-INTEGRITY
]
is
shown
below.
Note
that
it
includes
a
previousProof
attribute
since
we
are
constructing
a
proof
chain.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/proof-set-chain/proofChainConfig1.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/proof-set-chain/proofChainConfig1.json</pre> </body> </html>
Per
the
algorithm
of
Section
4.4:
Add
Proof
Set/Chain
in
[
VC-DATA-INTEGRITY
],
we
create
an
array
variable,
allProofs
,
and
add
the
proofs
from
the
starting
document
to
it.
Since
the
options
contains
the
previousProof
attribute,
we
compute
the
matchingProofs
variable
per
step
4
of
Section
4.4:
Add
Proof
Set/Chain
,
and
we
set
the
unsecuredDocument.proof
equal
to
the
matchingProofs
.
This
produces
the
document
shown
below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/proof-set-chain/proofChainTempDoc1.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/proof-set-chain/proofChainTempDoc1.json</pre> </body> </html>
In
step
6,
we
use
the
previous
document
(unsecured
document
with
previous
proofs
added
to
it)
to
compute
the
proofValue
attribute.
This
gives
the
signed
configuration
options
(proof)
shown
below:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/proof-set-chain/proofChainConfigSigned1.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/proof-set-chain/proofChainConfigSigned1.json</pre> </body> </html>
The
signed
proof
options
above
gets
appended
to
the
allProofs
variable,
which
then
gets
set
as
the
proof
attribute
of
the
unsigned
document
to
produce
the
final
signed
document
as
shown
below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/proof-set-chain/signedProofChain1.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/proof-set-chain/signedProofChain1.json</pre> </body> </html>
This
collection
of
test
vectors
demonstrates
construction
of
an
extended
proof
chain.
We
start
with
the
output
of
the
previous
section
and
add
an
additional
proof
that
is
dependent
on
one
of
the
existing
proofs.
This
example
uses
keyPair4
,
and
the
starting
document
is
given
below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/proof-set-chain/signedProofChain1.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/proof-set-chain/signedProofChain1.json</pre> </body> </html>
The
options
input
to
Section
4.4:
Add
Proof
Set/Chain
in
[
VC-DATA-INTEGRITY
]
is
shown
below.
Note
that
it
includes
a
previousProof
attribute
since
we
are
constructing
a
proof
chain,
however
this
time
it
is
a
single
value.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/proof-set-chain/proofChainConfig2.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/proof-set-chain/proofChainConfig2.json</pre> </body> </html>
Per
the
algorithm
of
Section
4.4:
Add
Proof
Set/Chain
in
[
VC-DATA-INTEGRITY
],
we
create
an
array
variable,
allProofs
,
and
add
the
proofs
from
the
starting
document
to
it.
Since
the
options
contains
the
previousProof
attribute,
we
compute
the
matchingProofs
variable
per
step
4
of
Section
4.4:
Add
Proof
Set/Chain
,
and
we
set
the
unsecuredDocument.proof
equal
to
the
matchingProofs
.
This
produces
the
document
shown
below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/proof-set-chain/proofChainTempDoc2.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/proof-set-chain/proofChainTempDoc2.json</pre> </body> </html>
In
step
6,
we
use
the
previous
document
(unsecured
document
with
previous
proofs
added
to
it)
to
compute
the
proofValue
attribute.
This
gives
the
signed
configuration
options
(proof)
shown
below:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/proof-set-chain/proofChainConfigSigned2.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/proof-set-chain/proofChainConfigSigned2.json</pre> </body> </html>
The
signed
proof
options
above
gets
appended
to
the
allProofs
variable,
which
then
gets
set
as
the
proof
attribute
of
the
unsigned
document
to
produce
the
final
signed
document
as
shown
below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body><pre>Cannot GET /uploads/rX6lRk/TestVectors/proof-set-chain/signedProofChain2.json</pre><pre>Cannot GET /uploads/SMvUgI/TestVectors/proof-set-chain/signedProofChain2.json</pre> </body> </html>
This section is non-normative.
This section contains the substantive changes that have been made to this specification over time.
Changes since the First Public Working Draft :
Referenced in:
Referenced in: