This specification describes several Data Integrity Cryptosuites for use when generating a digital signature using Post-Quantum digital signature algorithms.
This specification is experimental, do not use it in any production setting.
This specification defines several cryptographic suites for the purposes of creating and verifying proofs for Post-Quantum signatures, in conformance with the Data Integrity [[VC-DATA-INTEGRITY]] specification.
This specification uses either the RDF Dataset Canonicalization Algorithm [[RDF-CANON]] or the JSON Canonicalization Scheme [[RFC8785]] to transform the input document into its canonical form. It uses a hash based on SHA-2 [[RFC6234]] and appropriate to the security category as the message digest, and supports a number of different Post-Quantum signature algorithms with varying properties such as public key size, signature size, and computational and implementational complexity.
Terminology used throughout this document is defined in the Terminology section of the [[[VC-DATA-INTEGRITY]]] specification.
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 [[[#data-model]]] and [[[#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 to express verification methods, such as cryptographic public keys, and data integrity proofs, such as digital signatures.
These verification methods are used to verify Data Integrity Proofs [[VC-DATA-INTEGRITY]] produced using the cryptographic key material for the various algorithms and parameter sets supported by this specification. 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, defined in [[[CID]]], 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 public key.
| Signature Name | Varint Code | Multi-Byte Prefix | Raw Public Key Size |
|---|---|---|---|
| ML-DSA-44 | 0x1210 | 0x9024 | 1312 |
| SLH-DSA-SHA2-128s | 0x1220 | 0xa024 | 32 |
| FALCON-512* | 0x122c | 0xac24 | 897 |
| SQIsign-I* | 0x122e | 0xae24 | 65 |
The Multikey encoding of a public key for a signature supported by this specification MUST start with the corresponding multi-byte prefix for the signature named in [[[#MultiKeyTable]]] followed by the raw public key bytes. This multi-byte prefix is the varint expression of the varint code given in the previous table. The resulting value will have a byte length given by the raw public key size in the table plus the length of the multi-byte prefix. This value MUST then be encoded using the base-64-url alphabet, according to the Multibase section of [[[CID]]] and then prepended with the base-64-url Multibase header (`u`).
Examples of all the `publicKeyMultibase` encodings defined in this specification can be found in appendix [[[#TestVectors]]].
Note*: The codes given in [[[#MultiKeyTable]]] for FALCON-512 and SQIsign-I are preliminary and not currently registered with multicodecs. When these signature schemes are formalized by NIST or other SDOs these values should be updated/registered.
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 of the proof MUST be `DataIntegrityProof`.
The `cryptosuite` property of the proof MUST be one of the values from [[[#CryptosuiteTable]]], below, or [[[#SDCryptosuiteTable]]] for selective disclosure cryptosuites.
| Name | Signature Algorithm | Signature Length |
|---|---|---|
| `mldsa44-rdfc-2024` | ML-DSA-44 | 2420 |
| `mldsa44-jcs-2024` | ML-DSA-44 | 2420 |
| `slhdsa128-rdfc-2024` | SLH-DSA-SHA2-128s | 7856 |
| `slhdsa128-jcs-2024` | SLH-DSA-SHA2-128s | 7856 |
| `falcon512-rdfc-2024` | FALCON-512 | 666 |
| `falcon512-jcs-2024` | FALCON-512 | 666 |
| `sqisign1-rdfc-2024` | SQIsign-I | 148 |
| `sqisign1-jcs-2024` | SQIsign-I | 148 |
The value of the `proofValue` property of the proof MUST be a signature produced by the signature algorithm corresponding to the `cryptosuite` given in [[[#CryptosuiteTable]]]. This signature is produced according to using the algorithms specified in section [[[#Algorithms]]], then encoded using the base-64-url-nopad header and alphabet as described in the Multibase section of [[CID]].
Examples of the `proofValue` for all the cryptosuites defined in this specification can be found in appendix [[[#TestVectors]]].
The following sections describe multiple Data Integrity cryptographic suites that utilize quantum safe signature algorithms at different claimed security categories. For a given claimed security category, an appropriate hash function MUST be use in the [[[#HashingAlg]]].
From [[[NIST-SP-800-57-Part-1R6]]], Section 4.6.1.4 on the "Security Strengths of Hash Functions, XOFs, and Their Applications," the following hash function are chosen for use with digital signatures in [[[#HashSigTable]]].
| Security Strength | Hash Function |
|---|---|
| Category 1 or 2 | SHA-256 |
| Category 3 or 4 | SHA-384 |
| Category 5 | SHA-512 |
This specification supports cryptosuites based on both the Universal RDF Dataset Canonicalization Algorithm [[RDF-CANON]], `rdfc` and JSON Canonicalization Scheme [[RFC8785]], `jcs`. When the RDF Dataset Canonicalization Algorithm [[RDF-CANON]] is used with the [[[#ProofConfigurationAlg]]] and [[[#TransformationAlg]]] algorithms the cryptographic hashing function that is passed to the algorithm MUST be from [[[#HashSigTable]]] appropriate for the claimed security of the signature scheme.
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.
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 for proof serialization and proof verification of each of the respective cryptosuites.
The required inputs to this algorithm are a transformed data document (|transformedDocument|), canonical proof configuration (|canonicalProofConfig|), and hash name (|hashName|). A single hash data value represented as a series of bytes is produced as output.
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|), a cryptosuite identifier (|cryptosuite|), the canonicalization scheme (|canonScheme|) and hash name (|hashName|). The proof options MUST contain a type identifier for the cryptographic suite (|type|) and MUST contain the cryptosuite identifier (|cryptosuite|). A proof configuration object 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 [[[#HashingAlg]]].
Required inputs to this algorithm are an unsecured data document (|unsecuredDocument|), transformation options (|options|), a cryptosuite identifier (|cryptosuite|), the canonicalization scheme (|canonScheme|) and hash name (|hashName|). 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.
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 Section 4: Algorithms of the Data Integrity specification [[VC-DATA-INTEGRITY]]. Required inputs are cryptographic hash data (|hashData|), proof options (|options|), and a signature function (|sigFunc|). 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.
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 Section 4: Algorithms of the Data Integrity [[VC-DATA-INTEGRITY]] specification. Required inputs are cryptographic hash data (|hashData|), a digital signature (|proofBytes|), proof options (|options|), and a verification function (|verifyFunc|). A verification result represented as a boolean value is produced as output.
This algorithm is used to configure a cryptographic suite to be used by the Add Proof and Verify Proof functions in [[[VC-DATA-INTEGRITY]]]. The algorithm takes an options object ([=map=] |options|) as input and returns a [=data integrity cryptographic suite instance|cryptosuite instance=] ([=struct=] |cryptosuite|).
The Module-Lattice-Based Digital Signature Standard defined in [[[FIPS-204]]] [[FIPS-204]] defines parameter sets for three different claimed security strengths. The claimed security strengths, private key, public key, and signature sizes are summarized in [[[#MLSummaryTable]]].
| Name | Security | Private Key | Public Key | Signature |
|---|---|---|---|---|
| ML-DSA-44 | Category 2 | 2560 | 1312 | 2420 |
| ML-DSA-65 | Category 3 | 4032 | 1952 | 3309 |
| ML-DSA-87 | Category 5 | 4896 | 2592 | 4627 |
Supporting both the Universal RDF Dataset Canonicalization Algorithm [[RDF-CANON]], "`rdfc`", the JSON Canonicalization Scheme [[RFC8785]], "`jcs`", and a maximum security category of 2, leads to the family of ML-DSA cryptosuites given in [[[#MLSuitesTable]]].
| Name | Canonalization | Signature/Verification | Hash |
|---|---|---|---|
| `mldsa44-rdfc-2024` | RDFC | ML-DSA-44 | SHA-256 |
| `mldsa44-jcs-2024` | JCS | ML-DSA-44 | SHA-256 |
The following algorithm specifies how to create a [=data integrity proof=] given an unsecured data document and an ML-DSA cryptosuite chosen from [[[#MLSuitesTable]]]. The choice of cryptosuite sets the values of |canonScheme|, |hashName|, |sigFunc|, and |verifyFunc| per [[[#MLSuitesTable]]], which are used in the algorithm below. Additional 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 [=struct/items=] are:
The Stateless Hash-Based Digital Signature Standard defined in [[[FIPS-205]]] [[FIPS-205]] defines parameter sets for three different claimed security strengths, optimized for size or speed, and a specified hash function family. This specification considers a subset of these parameter sets, optimized for smaller size, and based on the SHA2 hash function family, as shown in [[[#SLHSigTable]]].
| Name | Security | Private Key | Public Key | Signature |
|---|---|---|---|---|
| SLH-DSA-SHA2-128s | Category 1 | 64 | 32 | 7856 |
| SLH-DSA-SHA2-192s | Category 3 | 96 | 48 | 16224 |
| SLH-DSA-SHA2-256s | Category 5 | 128 | 64 | 29792 |
Supporting both Universal RDF Dataset Canonicalization Algorithm [[RDF-CANON]], "`rdfc`", JSON Canonicalization Scheme [[RFC8785]], "`jcs`", and a maximum security category of 1, leads to the family of ML-DSA cryptosuites given in [[[#SLHSuiteTable]]].
| Name | Canonizalization | Signature/Verification | Hash |
|---|---|---|---|
| `slhdsa128-rdfc-2024` | RDFC | SLH-DSA-SHA2-128s | SHA-256 |
| `slhdsa128-jcs-2024` | JCS | SLH-DSA-SHA2-128s | SHA-256 |
The following algorithm specifies how to create a [=data integrity proof=] given an unsecured data document and an SLH-DSA cryptosuite chosen from [[[#SLHSuiteTable]]]. The choice of cryptosuite sets the values of |canonScheme|, |hashName|, |sigFunc|, and |verifyFunc| as found in [[[#SLHSuiteTable]]], for use in the algorithm below. Additional 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 [=struct/items=] are:
The [[FALCON]] signature algorithm is undergoing standardization by NIST. The information presented here is based on the Post-Quantum Cryptography Round 3 Submission information. This section will be updated when the NIST specification is issued.
[[FALCON]] is a lattice-based signature scheme. It stands for the following acronym: FAst Fourier Lattice-based COmpact signatures over NTRU. FALCON defines parameter sets for two different claimed security strengths. The claimed security strengths, private key, public key, and signature sizes are summarized in [[[#FalconSummaryTable]]].
| Name | Security | Private Key | Public Key | Signature |
|---|---|---|---|---|
| FALCON-512 | Category 1 | 1281 | 897 | 666 |
| FALCON-1024 | Category 5 | 2305 | 1793 | 1280 |
Private key size information from openquantumsafe.org.
Supporting both the Universal RDF Dataset Canonicalization Algorithm [[RDF-CANON]], "`rdfc`", the JSON Canonicalization Scheme [[RFC8785]], "`jcs`", and a maximum security category of 1, leads to the family of FALCON cryptosuites given in [[[#FALCONSuitesTable]]].
| Name | Canonalization | Signature/Verification | Hash |
|---|---|---|---|
| `falcon512-rdfc-2024` | RDFC | FALCON-512 | SHA-256 |
| `falcon512-jcs-2024` | JCS | FALCON-512 | SHA-256 |
The following algorithm specifies how to create a [=data integrity proof=] given an unsecured data document and a FALCON cryptosuite chosen from [[[#FALCONSuitesTable]]]. The choice of cryptosuite sets the values of |canonScheme|, |hashName|, |sigFunc|, and |verifyFunc| per [[[#FALCONSuitesTable]]], which are used in the algorithm below. Additional 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 [=struct/items=] are:
The SQIsign signature algorithm has been submitted to NIST. SQIsign aims for very compact key and signature sizes. The information presented here is based on specification v2.01, 2025-07-07. This section will be updated as appropriate.
SQIsign relies on the hardness of a computational problem from number theory: computing the endomorphism ring of a supersingular elliptic curve, the endomorphism ring problem. SQIsign defines parameter sets for three different claimed security strengths. The claimed security strengths, private key, public key, and signature sizes are summarized in [[[#SQISummaryTable]]].
| Name | Security | Private Key | Public Key | Signature |
|---|---|---|---|---|
| SQIsign-I | Category 1 | 353 | 65 | 148 |
| SQIsign-III | Category 3 | 529 | 97 | 224 |
| SQIsign-V | Category 5 | 701 | 129 | 292 |
Supporting both the Universal RDF Dataset Canonicalization Algorithm [[RDF-CANON]], "`rdfc`", the JSON Canonicalization Scheme [[RFC8785]], "`jcs`", and a maximum security category of 1, leads to the family of SQIsign cryptosuites given in [[[#SQISuitesTable]]].
| Name | Canonalization | Signature/Verification | Hash |
|---|---|---|---|
| `sqisign1-rdfc-2024` | RDFC | SQIsign-I | SHA-256 |
| `sqisign1-jcs-2024` | JCS | SQIsign-I | SHA-256 |
The following algorithm specifies how to create a [=data integrity proof=] given an unsecured data document and a SQIsign cryptosuite chosen from [[[#SQISuitesTable]]]. The choice of cryptosuite sets the values of |canonScheme|, |hashName|, |sigFunc|, and |verifyFunc| per [[[#SQISuitesTable]]], which are used in the algorithm below. Additional 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 [=struct/items=] are:
This section provides algorithms for a relatively efficient approach to enabling selective disclosure of a verifiable credential protected by a quantum safe signature algorithm. This approach utilizes a single quantum safe signature while sharing additional information concerning the cryptographic hashes of the processed claims. This contrasts with the approach taken in [[VC-DI-ECDSA]] selective disclosure where a short signature is given for each processed claim and no additional hashes are shared. This also contrasts with the approach in [[VC-DI-BBS]] where the underlying signature scheme supports multiple claims and only a single short signature is shared.
In all the approaches to selective disclosure mentioned above the same core set of selective disclosure processing functions contained in [[VC-DI-ECDSA]] are utilized which enables flexibility and efficiency in implementations. The approach taken here is roughly more efficient when a signature is longer than twice the size of the corresponding hash for a given security level, e.g., 64 bytes for security category 1 or 2. From [[[#CryptosuiteTable]]] we can see that this condition is true for all signature algorithms currently considered in this specification.
The general selective disclosure functions in [[VC-DI-ECDSA]] are planned to be moved to an updated version of [[VC-DATA-INTEGRITY]].
Selective disclosure is enabled by the issuer creating a base proof as specified in section [[[#SD-Base]]]. The issuer can specify that certain claims are mandatory, i.e., have to be revealed to the verifier. The holder on receiving the issued verifiable credential with the base proof, uses it to create a related verifiable credential whose claims are a selected subset of claims from the received document. This is done with the algorithm of section [[[#SD-Derived]]]. Finally the verifier uses the algorithm of section [[[#SD-Verify-Derived]]] to verify the selectively disclosed verifiable credential.
The selective disclosure cryptosuites defined in this specification are listed in [[[#SDCryptosuiteTable]]]. Note that all selective disclosure cryptosuites utilize the advanced features of [[RDF-CANON]].
| Name | Signature Algorithm | Signature Length |
|---|---|---|
| `mldsa44-sd-2024` | ML-DSA-44 | 2420 |
| `slhdsa128-sd-2024` | SLH-DSA-SHA2-128s | 7856 |
| `falcon512-sd-2024` | FALCON-512 | 666 |
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 [[[#base-proof-hashing-selective-disclosure]]].
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.
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 [[[#base-proof-serialization-selective-disclosure]]].
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.
To do: provide background on cryptographic random number generation in the security considerations section. For example cite appropriate references such as NIST SP-800-90A,B,C documents and/or BSI AIS 20 and AIS 31 documents.
The following algorithm specifies how to create a base proof; called by an issuer of an Quantum-Safe-SD-protected Verifiable Credential. 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|). 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.
The Quantum-Safe-SD base proof header bytes 0xd9, 0x5d, and 0x10 were chosen to not collide with any of the [[VC-DI-ECDSA]] or [[VC-DI-BBS]] values. They are currently tentative.
The following algorithm creates a selective disclosure derived proof; called by a holder of an Quantum-Safe-SD protected [=verifiable credential=]. The derived proof is to be given to the [=verifier=]. The inputs include a JSON-LD document (|document|), Quantum-Safe-SD base proof (|proof|), an array of JSON pointers to use to selectively disclose statements (|selectivePointers|), 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.
The following algorithm creates data to be used to generate a derived proof. The inputs include a JSON-LD document (|document|), an Quantum-Safe-SD base proof (|proof|), an array of JSON pointers to use to selectively disclose statements (|selectivePointers|), and any custom JSON-LD API options, such as a document loader). A single object, disclosure data, is produced as output, which contains the "signature", "salts", "saltedHashes", "labelMap", "mandatoryIndexes", "selectiveIndexes" and "revealDocument" fields.
The following algorithm parses the components of an Quantum Safe selective disclosure base proof value. The required inputs are a proof value (|proofValue|). A single object parsed base proof, containing five elements, using the names `signature`, `hmacKey`, `salts` `saltedHashes`, and `mandatoryPointers`, is produced as output.
The following algorithm serializes a Quantum-Safe-SD derived proof value. The required inputs are a base signature (|signature|), an array of salts (|salts|), an array of salted hashes (|saltedHashes|), a label map (|labelMap|), an array of mandatory indexes (|mandatoryIndexes|). and an array of selective indexes (|selectiveIndexes|). A single derived proof value, serialized as a byte string, is produced as output.
The Quantum-Safe-SD disclosure proof header bytes `0xd9`, `0x5d`, and `0x11` were chosen to not conflict with values used by [[VC-DI-ECDSA]] and [[VC-DI-BBS]] and are tentative.
The following algorithm attempts verification of an Quantum-Safe-SD derived proof. This algorithm is called by a verifier of an Quantum-Safe-SD protected [=verifiable credential=]. The inputs include a JSON-LD document (|document|), a Quantum-Safe-SD disclosure proof (|proof|), and any custom JSON-LD API options, such as a document loader. This algorithm returns a [=verification result=]:
The following algorithm creates the data needed to perform verification of an Quantum-Safe-SD protected [=verifiable credential=]. The inputs include a JSON-LD document (|document|), an Quantum-Safe-SD 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: "signature", "proofHash", "salts", "saltedHashes", "nonMandatory", "mandatoryHash", and "selectiveIndexes".
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 value object is produced as output, which contains a set to six elements, using the names "signature", "salts", "saltedHashes", "labelMap", "mandatoryIndexes", and "selectiveIndexes".
Should we also mention additional checks on the values of |salts|, |saltedHashes|, |mandatoryIndexes|, and |selectiveIndexes|? In particular, the length of the the |salts| and |saltedHashes| must be the same. The all elements of the |mandatoryIndexes| and |selectiveIndexes| should be in the range of 0 to the length of |salts|. There should not be repeated items in the |mandatoryIndexes| and |selectiveIndexesArrays|. Also the elements of each of these arrays should be increasing order. Note that the minimal additional checks appear in [[[#SD-Verify-Derived]]].
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 or protocols based on verifiable credentials signed using the cryptosuites defined here.
All signature suites in this specification are designed to satisfy either existential unforgeability under chosen-message attacks (EUF-CMA) or strong unforgeability under chosen message attacks (SUF-CMA) or both as defined below.
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.
Besides EUF-CMA and SUF-CMA there are additional properties a digital signature scheme can possess that may be essential for overall software or protocol security depending on the application. These are discussed in [[BUFF]], which is also referenced by [[FIPS-204]] and [[FIPS-205]]. These additional properties are defined in [[BUFF]] as: exclusive ownership, message-bound signatures, and non re-signability.
Exclusive Ownership (EO): the property that a signature only verifies under a single public key. Without this property a system could be vunerable to an attack that allows constructing another key pair under which a given signature verifies, but never breaks the EUF-CMA property. Such an attack is documented in both [[BUFF]] and in [[Provable_Ed25519]] where it is called a "key substitution attack".
Message-Bound Signatures (MBS): the property that a signature is only valid for a unique message. This property is key for data integrity and all signature schemes chosen here currently support it. From [[BUFF]]: "A possible cause can be the presence of weak keys that verify multiple or even all messages. The absence of this property can lead to problems in protocols that depend on uniqueness properties in the presence of adversarially chosen keys."
Non Re-signability (NR): meaning that one cannot produce a signature under another key given a signature for some unknown message m, i.e., that an adversary cannot produce a legitimate signature verifying under its public key for a message it does not know. See [[BUFF]] for an example of a system that could be vulnerable without this property.
In [[[#SecurityProperties]]] we summarize the known security properties of the signature schemes in this specification.
| Name | EUF-CMA | SUF-CMA | EO | MBS | NR |
|---|---|---|---|---|---|
| ML-DSA | Yes | Yes | Yes | Yes | Yes |
| SLH-DSA | Yes | No | Unknown | Yes | Unknown |
| FALCON* | Yes | No | No | Yes | No |
| SQIsign | Yes | No | Yes | Yes | Yes |
Note*: This is based on the "third round FALCON" currently used hear and according to [[BUFF]] will be updated when FIPS-206 is released.
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.
The cryptographic suites described in this specification do not support [=selective disclosure=] or [=unlinkable disclosure=]. If [=selective disclosure=] is a desired feature, readers might find the [[[?VC-DI-ECDSA]]] specification useful. If [=unlinkable disclosure=] is of interest, the [[[?VC-DI-BBS]]] specification provides an unlinkable digital signature mechanism.
A relatively efficient selective, but not unlinkable, disclosure mechanism can be created by combining the selective disclosure functions defined in [[[?VC-DI-ECDSA]]] with the "salted hash" approach of SD-JWT, if there is sufficient interest.
Inputs used in two or more test vectors are given in this section. They include the unsigned document, general proof options, and cryptographic keys.
The common unsecured data document used for generating all test vectors that require this input is given below.
A general template for the proof options used by test vectors that require this input is given below.
For each specific test case the `cryptosuite` and `verificationMethod` fields need to be set. For example, for the `slhdsa128-rdfc-2024` cryptosuite using the appropriate public key information from section [[[#TestKeys]]] the specific proof options is given below.
Cryptographic keys for used to generate output for specific signature suites are given below. This includes public and private (secret) keys in hexadeximal format and the public key as a `publicKeyMultibase`.
The Proof Configuration algorithm output is dependent on the specific proof options as well as the parameters, hence an output test vector for Proof Configuration is given for each supported `cryptosuite`.
In addition to the common unsecured data document the Transform algorithm takes parameters |canonScheme| and |hashName|. Only in the case of |canonScheme| equal to `rdfc` does the |hashName| parameter matter. This is reflected in the set of Transformation output test vectors given below.
The Hashing algorithm takes as inputs the results of the Proof Configuration and Transformation algorithms. Since the Proof Configuration algorithm output is cryptosuite specific the Hashing algorithm output is given for each cryptosuite test case. The Hashing output for each cryptosuite test case is given in hexadecimal format below.
The first half of the hexadecimal Hashing result is the hash of the output of the Proof Configuration algorithm, while the second half of the hexidecimal value is the hash of the output from the Transformation algorithm and both can be useful information when debugging.
The Create Proof algorithm output is cryptosuite specific and uses the outputs of the Proof Configuration, Transformation, Hashing, and Proof Serialization algorithms. The output for each cryptosuite test case is given below.
The output of the Proof Serialization common algorithm is not given separately since it is contained in the `proofValue` attribute in the following examples and can be quite lengthy for some quantum safe signature algorithms.
The Quantum-Safe-SD utilize the same set of common inputs described in [[[#test-vector-common-inputs]]], this includes the unsigned document, proof options and the example keys for ML-DSA-44, SLH-DSA-SHA2-128s, and FALCON-512.
For the base proof transformation of Section [[[#base-proof-transformation-selective-disclosure]]], the example mandatory information specified by the issuer is given via an array of JSON pointers as shown below.
As part of the base proof transformation of Section [[[#base-proof-transformation-selective-disclosure]]] an HMAC key is required. We use the following HMAC key for all selective disclosure test vectors.
To create the derived proof in [[[#SD-Derived]]], the holder indicate what, if anything else, they wish to reveal to the verifier by specifying JSON pointers for selective disclosure. The example selective pointers is shown below:
The result of transform step, [[[#base-proof-transformation-selective-disclosure]]], from [[[#SD-Base]]] depend on the document, HMAC key, and mandatory pointers but not the specific signature algorithm. They result contains appropriately modified maps of mandatory and non-mandatory claims in N-Quad format as shown below.
The hashing step, [[[#base-proof-hashing-selective-disclosure]]], from [[[#SD-Base]]] consists of a signature/cryptosuite specific part proofHash and a cryptosuite independent part that includes the mandatoryHash, salts, and saltedHashes as shown below.
We use the same set of salts across all our examples resulting in the same set of saltedHashes. In practice salt values can not be reused, i.e., reuse of salts can compromise the security of the credential, e.g., leaking data on undisclosed claims.
The cryptosuite specific part of the hashing step, [[[#base-proof-hashing-selective-disclosure]]], from [[[#SD-Base]]] consists of a proofHash. These are summarized below.
The results of [[[#base-proof-serialization-selective-disclosure]]] is integrated into the final output of [[[#SD-Base]]] for each of the example cryptosuites are shown below. The signature values in hex are shown in [[[#example-pqc-signatures]]].
Signature values are generally based on non-deterministic algorithms so you can verify a signature value against its corresponding input message but you cannot compare two signature values to validate these test vectors, i.e., your generated signature value can be valid, while differing from what is presented here.
The first step in formulating a derived proof [[[#SD-Derived]]] is to [[[#Derived-Create-Disclosure-Data]]] based on the document, base proof, and selective pointers. This process creates an object containing the following items: signature, salts, saltedHashes, labelMap, mandatoryIndexes, selectiveIndexes and revealDocument. Except for the signature field these values are common across the cryptosuite test vectors and are shown in the two examples below.
The signature portion of the [[[#Derived-Create-Disclosure-Data]]] which is recovered from the base proof is shown below, where we have aggregated the different signature values.
The final ouput, i,e, the signed derived document, from [[[#SD-Derived]]] for each of our example cryptosuites is shown below.
This section contains the substantive changes that have been made to this specification over time.
Added cryptosuite algorithms for Stateless Hash-Based Signatures, Falcon, and SQISign.