diff --git a/index.html b/index.html
index e7f9476..b92355c 100644
--- a/index.html
+++ b/index.html
@@ -410,7 +410,7 @@
The `proofValue` property of the proof MUST be an ECDSA or deterministic ECDSA
signature produced according to [[FIPS-186-5]] using the curves and hashes as
-specified in section , encoded according to section 7
+specified in section , encoded according to section 7
of [[RFC4754]] (sometimes referred to as the IEEE P1363 format), and serialized
according to [[MULTIBASE]] using the base58-btc base encoding.
@@ -1020,6 +1020,1788 @@
+ jcs-ecdsa-2019
+
+
+The `jcs-ecdsa-2019` 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 algorithms in this
+section also include the verification of such a data integrity proof.
+
+
+
+
+
+
+
+ Transformation (jcs-ecdsa-2019)
+
+
+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 .
+
+
+
+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.
+
+
+
+ -
+If options.type is not set to the string
+`DataIntegrityProof` and options.cryptosuite is not
+set to the string `jcs-ecdsa-2019`, then a `PROOF_TRANSFORMATION_ERROR` MUST be
+raised.
+
+ -
+Let canonicalDocument be the result of applying the
+JSON Canonicalization Scheme [[RFC8785]] to the unsecuredDocument.
+
+ -
+Set output to the value of canonicalDocument.
+
+ -
+Return canonicalDocument as the transformed data document.
+
+
+
+
+
+ Hashing (jcs-ecdsa-2019)
+
+
+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 or
+Section . One must use the
+hash algorithm appropriate in security level to the curve used, i.e., for curve
+P-256 one uses SHA-256, and for curve P-384 one uses SHA-384.
+
+
+
+The required inputs to this algorithm are a transformed data document
+(transformedDocument) and a canonical proof configuration
+(canonicalProofConfig). A single hash data value represented as
+series of bytes is produced as output.
+
+
+
+ -
+Let transformedDocumentHash be the result of applying the SHA-256
+(SHA-2 with 256-bit output) or SHA-384 (SHA-2 with 384-bit output)
+cryptographic hashing algorithm [[RFC6234]] to the
+respective curve P-256 or curve P-384 transformedDocument.
+Respective transformedDocumentHash will be exactly 32 or 48 bytes
+in size.
+
+ -
+Let proofConfigHash be the result of applying the SHA-256
+(SHA-2 with 256-bit output) or SHA-384 (SHA-2 with 384-bit output)
+cryptographic hashing algorithm [[RFC6234]] to the
+respective curve P-256 or curve P-384 canonicalProofConfig.
+Respective proofConfigHash will be exactly 32 or 48 bytes in size.
+
+ -
+Let hashData be the result of concatenating proofConfigHash (the
+first hash) followed by transformedDocumentHash (the second hash).
+
+ -
+Return hashData as the hash data.
+
+
+
+
+
+
+ Proof Configuration (jcs-ecdsa-2019)
+
+
+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.
+
+
+
+ -
+Let proofConfig be an empty object.
+
+ -
+Set proofConfig.type to
+options.type.
+
+ -
+If options.cryptosuite is set, set
+proofConfig.cryptosuite to its value.
+
+ -
+If options.type is not set to `DataIntegrityProof` and
+proofConfig.cryptosuite is not set to `jcs-ecdsa-2019`, an
+`INVALID_PROOF_CONFIGURATION` error MUST be raised.
+
+ -
+Set proofConfig.created to
+options.created. If the value is not a valid
+[[XMLSCHEMA11-2]] datetime, an `INVALID_PROOF_DATETIME` error MUST be raised.
+
+ -
+Set proofConfig.verificationMethod to
+options.verificationMethod.
+
+ -
+Set proofConfig.proofPurpose to
+options.proofPurpose.
+
+ -
+Let canonicalProofConfig be the result of applying the
+JSON Canonicalization Scheme [[RFC8785]] to the proofConfig.
+
+ -
+Return canonicalProofConfig.
+
+
+
+
+
+
+ Proof Serialization (jcs-ecdsa-2019)
+
+
+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.
+
+
+
+ -
+Let 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.
+
+ -
+Let proofBytes be the result of applying the Elliptic Curve Digital
+Signature Algorithm (ECDSA) [[FIPS-186-5]], with hashData as the data
+to be signed using the private key specified by privateKeyBytes.
+proofBytes will be exactly 64 bytes in size for a P-256 key, and
+96 bytes in size for a P-384 key.
+
+ -
+Return proofBytes as the digital proof.
+
+
+
+
+
+
+ Proof Verification (jcs-ecdsa-2019)
+
+
+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.
+
+
+
+ -
+Let 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.
+
+ -
+Let verificationResult be the result of applying the verification
+algorithm, Elliptic Curve Digital Signature Algorithm (ECDSA) [[FIPS-186-5]],
+with hashData as the data to be verified against the
+proofBytes using the public key specified by
+publicKeyBytes.
+
+ -
+Return verificationResult as the verification result.
+
+
+
+
+
+
+
+ Selective Disclosure Functions
+
+
+The Working Group is seeking implementer feedback on these generalized selective
+disclosure functions as well as horizonal security review on the features from
+parties at W3C and IETF. Those reviews might result in significant changes to
+these functions, migration of these functions to the core Data Integrity
+specification (for use by other cryptographic suites), or the removal of the
+algorithm from the specification during the Candidate Recommendation phase.
+
+
+
+The following section contains a set of functions that are used throughout
+cryptographic suites that perform selective disclosure.
+
+
+
+ labelReplacementCanonize
+
+
+The following algorithm canonizes a JSON-LD document and replaces any blank node
+identifiers in the canonicalized document by applying a label replacement
+function, labelReplacementFunction. The required inputs are a JSON-LD
+document (document) and a label replacement functon
+(labelReplacementFunction). A N-Quads representation of the
+canonized result, with the replaced blank node labels, and a map from
+the old blank node IDs to the new blank node IDs, bnodeIdMap, is
+produced as output.
+
+
+
+ -
+Run the RDF Dataset Canonicalization Algorithm [[RDF-CANON]] on
+document, passing any custom options (such as a document loader), and
+get the canonicalized dataset as output, which includes a canonical bnode
+identifier map, canonicalIdMap.
+
+ -
+Pass canonicalIdMap to labelReplacementFunction to produce
+a new bnode identifier map, bnodeIdMap.
+
+ -
+Produce canonical N-Quads representation, canonized result, using
+canonicalized dataset along with bnodeIdMap and return it.
+
+
+
+
+
+
+ hmacIdCanonize
+
+
+The following algorithm creates a label replacement function that uses an
+HMAC to replace canonical blank node identifiers with their encoded HMAC
+digests. The required inputs are a canonical node identifier map,
+canonicalIdMap. A blank node identifier map, bnodeIdMap, is
+produced as output.
+
+
+
+ -
+Generate a new empty bnode identifier map, bnodeIdMap.
+
+ -
+For each map entry in canonicalIdMap:
+
+ -
+HMAC the canonical identifier from the entry to get an HMAC digest,
+digest.
+
+ -
+Generate a new string value, b64urlDigest, and initialize it to "u"
+followed by appending a base64url-no-pad encoded version of the digest
+value.
+
+ -
+Add this new entry to bnodeIdMap.
+
+
+
+ -
+Return bnodeIdMap.
+
+
+
+
+A different primitive could be created that sorted the resulting HMAC digests
+and assigned labels using a prefix and integers based on their sorted order
+instead. This primitive might be useful for index-based selective disclosure
+schemes such as BBS.
+
+
+
+
+
+ labelMapCanonize
+
+
+The following algorithm creates a label replacement function that uses a label
+map to replace canonical blank node identifiers with the associated value from
+the labeel map. The required inputs are a label map, labelMap. A
+function, labelMapReplacementFunction, is produced as output.
+
+
+
+ -
+Set labelMapReplacementFunction to a function that returns the
+reverse of labelMap.
+
+ -
+Return labelMapReplacementFunction.
+
+
+
+
+
+ skolemize
+
+
+The following algorithm replaces all blank node identifiers in an array of
+N-Quad statements with a URN. The required inputs are an array of N-Quad strings
+(inputNquads) and a URN scheme (urnScheme). An array of
+N-Quad strings, skolemizedNquads, is produced as output.
+
+
+
+ -
+Create a new array of N-Quad strings, skolemizedNquads.
+
+ -
+For each N-Quad string, s1, in the input array:
+
+ -
+Create a new string, s2, that is a copy of s1 replacing any
+occurrence of a blank node identifier with a URN ("urn:"), plus the input
+custom scheme (urnScheme), plus a colon (":"), and
+the value of the blank node identifier. For example, a regular expression
+of a similar form to the following would achieve the desired result:
+
s1.replace(/(_:([^\s]+))/g, '<urn:custom-scheme:$2>')
.
+
+ -
+Append s2 to skolemizedNquads.
+
+
+ -
+Return skolemizedNquads.
+
+
+
+
+
+ deskolemize
+
+
+The following algorithm replaces all custom scheme URNs in an array of
+N-Quad statements with a blank node identifier. The required inputs are an array of N-Quad strings
+(inputNquads) and a URN scheme (urnScheme). An array of
+N-Quad strings, deskolemizedNquads, is produced as output.
+
+
+
+ -
+Create a new array of N-Quad strings, deskolemizedNquads.
+
+ -
+For each N-Quad string, s1, in the inputNquads array:
+
+ -
+Create a new string, s2, that is a copy of s1 replacing any
+occurrence of a URN ("urn:"), plus the input
+custom scheme (urnScheme), plus a colon (":"), and
+the value of the blank node identifier with a blank node prefix ("_:"), plus
+the value of the blank node identifier. For example, a regular expression
+of a similar form to the following would achieve the desired result:
+
s1.replace(/(<urn:custom-scheme:([^>]+)>)/g, '_:$2').
.
+
+ -
+Append s2 to deskolemizedNquads.
+
+
+ -
+Return deskolemizedNquads.
+
+
+
+
+
+ toSkolemizedJSONLD
+
+
+The following algorithm converts an array of N-Quads to a skolemized
+JSON-LD document. The required inputs are an array of N-Quad strings
+(inputNquads). A JSON-LD document, skolemizedJSONLD, is
+produced as output.
+
+
+
+ -
+Initialize `skolemizedQuads` to the result of calling the algorithm in
+Section , with inputNQuads and
+"custom-scheme" as parameters. Implementations MAY choose a different
+urnSchemeName that is different than "custom-scheme" so long as the
+same scheme name is used in the algorithm in Section
+.
+
+ -
+Join `skolemizedQuads` into a single N-Quads string, `dataset`.
+
+ -
+Set skolemizedJSONLD to the result of the
+
+Serialize RDF as JSON-LD algorithm, passing any custom options (such as a
+document loader), to convert `dataset` from RDF to a JSON-LD document.
+
+ -
+Return skolemizedJSONLD.
+
+
+
+
+
+ toDeskolemizedRDF
+
+
+The following algorithm converts a skolemized JSON-LD document, such as one
+created using the algorithm in Section , to an
+array of deskolemized N-Quads. The required inputs are a JSON-LD document,
+skolemizedJSONLD. An array of deskolemized N-Quad strings
+(outputNquads) is produced as output.
+
+
+
+ -
+Initialize `skolemizedDataset` to the result of calling the
+
+Deserialize JSON-LD to RDF algorithm, passing any custom options (such as a
+document loader), to convert `skolemizedJSONLD` from JSON-LD to RDF in N-Quads
+format.
+
+ -
+Split `skolemizedDataset` into an array of individual N-Quads,
+`skolemizedNquads`.
+
+ -
+Set outputNquads to the result of calling the algorithm in Section
+ with `skolemizedNquads` and "custom-scheme" as
+parameters. Implementations MAY choose a different urnSchemeName that
+is different than "custom-scheme" so long as the same scheme name is used in
+the algorithm in Section .
+
+ -
+Return outputNquads.
+
+
+
+
+
+ jsonPointerToPaths
+
+
+The following algorithm converts a JSON Pointer [[RFC6901]] to an array of paths
+into a JSON tree. The required input is a JSON Pointer string
+(pointer). An array of paths (paths) is produced as output.
+
+
+
+ -
+Initialize `paths` to an empty array.
+
+ -
+Initialize `splitPath` to an array by splitting pointer on the
+"/" character and skipping the first, empty, split element. In Javascript
+notation, this step is equivalent to the following code:
+`pointer.split('/').slice(1)`
+
+ -
+For each `path` in `splitPath`:
+
+ -
+If `path` does not include `~`, then add `path` to `paths`, converting it to
+an integer if it parses as one, leaving it as a string if it does not.
+
+ -
+Otherwise, unescape any JSON pointer escape sequences in `path` and add the
+result to `paths`.
+
+
+
+ -
+Return `paths`.
+
+
+
+
+
+ createInitialFrame
+
+
+The following algorithm creates an initial JSON-LD frame based on a JSON-LD
+object. This is a helper function used within the algorithm in
+Section . The required input is a
+JSON-LD object (value). A JSON-LD frame frame is produced
+as output.
+
+
+
+ -
+Initialize frame to an empty object.
+
+ -
+If value has an `id` that is not a blank node identifier, set
+`frame.id` to its value. Note: All non-blank node identifiers in the path of
+any JSON Pointer MUST be included in the frame, this includes any root document
+identifier.
+
+ -
+If value.`type` is set, set frame.`type` to its value.
+Note: All `type`s in the path of any JSON Pointer MUST be included in the frame,
+this includes any root document `type`.
+
+ -
+Return frame.
+
+
+
+
+
+ jsonPointersToFrame
+
+
+The following algorithm converts an array of JSON Pointers and a JSON-LD
+document to a JSON-LD Frame to be used on that specific document. The required
+input is an array of JSON Pointers (pointers) and a JSON-LD document
+(document). A JSON-LD frame (frame) is produced as output.
+
+
+
+ -
+If `pointers` is empty, return `null`.
+
+ -
+Initialize `frame` to an initial frame passing `document` as `value` to
+the algorithm in Section .
+
+ -
+For each `pointer` in `pointers` walk the document from root to the pointer
+target value building the frame:
+
+
+ -
+Initialize `parentFrame` to `frame`.
+
+ -
+Initialize `parentValue` to `document`.
+
+ -
+Initialize `value` to `parentValue`.
+
+ -
+Initialize `valueFrame` to `parentFrame`.
+
+ -
+Parse the `pointer` into an array of `paths` using the algorithm in
+Section .
+
+ -
+For each `path` in `paths`:
+
+
+ -
+Set `parentFrame` to `valueFrame`.
+
+ -
+Set `parentValue` to `value`.
+
+ -
+Set `value` to `parentValue[path]`. If `value` is now undefined, throw an error
+indicating that the JSON pointer does not match the given `document`.
+
+ -
+Set `valueFrame` to `parentFrame[path]`.
+
+ -
+If `valueFrame` is undefined:
+
+
+ -
+If `value` is an array, set `valueFrame` to an empty array.
+
+ -
+Otherwise, set `valueFrame` to an initial frame passing `value` to
+the algorithm in Section .
+
+ -
+Set `parentFrame[path]` to `valueFrame`.
+
+
+
+ -
+Note: Next we generate the final `valueFrame`.
+
+ -
+If `value` is not an object, then a literal has been selected: Set `valueFrame`
+to `value`.
+
+ -
+Otherwise, if `value` is an array: Set `valueFrame` to the result of mapping
+every element in `value` to a deep copy of itself. If any element in `value` is
+also an `array`, throw an error indicating that arrays of arrays are not
+supported.
+
+ -
+Otherwise: Set `valueFrame` to an object that merges a shallow copy of
+`valueFrame` with a deep copy of `value`, e.g., `{...valueFrame,
+…deepCopy(value)}`.
+
+ -
+If `paths` has a length of zero, then the whole `document` has been selected by
+the `pointer`: Set `frame` to `valueFrame`.
+
+ -
+Otherwise, a partial selection has been made by the pointer:
+
+ -
+Get the last `path`, `lastPath`, from `paths`.
+
+ -
+Set `parentFrame[lastPath]` to `valueFrame`.
+
+
+ -
+Set `frame['@context']` to a deep copy of `document['@context']`.
+
+ -
+Return `frame`.
+
+
+
+
+
+
+ strictFrame
+
+
+The following algorithm performs a JSON-LD framing operation on a JSON-LD
+document with strict framing options. The required inputs are a JSON-LD Document
+(document) and a JSON-LD Frame (frame). A JSON-LD document
+(framedDocument) is generated as output.
+
+
+
+ -
+Set framedDocument to the result of the
+
+JSON-LD Framing algorithm, passing `document` and `frame`, and setting the
+options `requireAll`, `explicit`, and `omitGraph` to `true`. Any additional
+custom options passed, such as a document loader, is included as well.
+
+ -
+Return framedDocument.
+
+
+
+
+
+ groupNquads
+
+
+The following algorithm groups N-Quads into matching and non-matching groups.
+The inputs are an array of N-Quads (nquads, an optional skolemized
+JSON-LD document (skolemizedDocument), an optional JSON-LD frame
+(frame) , and any options, such as a document loader, to be passed to
+JSON-LD APIs. Each of the output groups (matching and non-matching) are
+expressed as a map that maps an index into nquads to the N-Quad value.
+This algorithm uses a JSON-LD frame to match specific N-Quads in the array of
+given nquads. It internally skolemizes and then deskolemizes any
+blank nodes around the framing operation to ensure blank node identifiers do not
+change, preventing the matching operation from working properly.
+An object containing a matching and nonmatching arrays of
+N-Quads are generated as output.
+
+
+
+ -
+Initialize `matching` to an empty map.
+
+ -
+Initialize `nonMatching` to an empty map.
+
+ -
+If `frame` is not given or `null`, then there are no matches so:
+
+ -
+Add each entry (index, element) in `nquads` to `nonMatching`.
+
+ -
+Return an object with "matching" set to `matching` and "nonMatching" set to
+`nonMatching`.
+
+
+
+ -
+If `skolemizedDocument` has not been given: Set `skolemizedDocument` to the
+result of calling "createSkolemizedDocument", passing `nquads` and any custom
+JSON-LD API options (such as a document loader).
+
+ -
+Initialize `framed` to the result of calling "strictFrame", passing
+`skolemizedDocument`, `frame`, and any custom JSON-LD API options. Note: This
+step filters the skolemized document to get only data that matches the frame as
+a new JSON-LD document.
+
+ -
+Initialize `matchingDeskolemized` to the result of calling "toDeskolemizedRDF",
+passing `framed` and any custom JSON-LD API options. Note: This step converts
+any matching data back to deskolemized N-Quads, matching their original
+expression.
+
+ -
+For each entry (`index`, `nq`) in `nquads`:
+
+ -
+If `matchingDeskolemized` includes `nq`, add the entry to `matching`.
+
+ -
+Otherwise, add the entry to `nonMatching`.
+
+
+
+ -
+Return an object with "matching" set to `matching` and "nonMatching" set to
+`nonMatching`.
+
+
+
+
+
+ filterAndGroupNquads
+
+
+The following algorithm filters N-Quads, given in an array of N-Quads and a
+JSON-LD filtering frame, and then groups the N-Quads that passed the filter into
+matching and non-matching groups based on another JSON-LD grouping frame. This
+function will internally perform skolemization and deskolemization around
+framing operations to ensure that any blank node identifiers do not change,
+which would prevent filtering and matching operations from working properly. The
+inputs to the algorithm are an array of N-Quads (nquads), a JSON-LD
+filtering frame (filterFrame), a JSON-LD grouping frame
+(groupFrame). Additionally, any custom JSON-LD API options are
+expected to be given as an input. An object containing two properties is
+provided as output; matching and nonmatching each hold arrays
+of their associated N-Quads.
+
+
+
+ -
+Initialize `skolemizedDocument` to the result of calling the algorithm in
+Section , passing `nquads` and any custom
+JSON-LD API options (such as a document loader).
+
+ -
+Initialize `filteredDocument` to the result of calling the algorithm in Section
+, passing `skolemizedDocument`, `filterFrame`, and
+any custom JSON-LD API options.
+
+ -
+Initialize `filteredNQuads` to the result of calling the algorithm in Section , passing `filteredDocument` and any custom
+JSON-LD API options.
+
+ -
+Note: These next two steps can be performed in parallel.
+
+
+ -
+Get the canonical blank node identifier map, `canonicalIdMap`, by calling
+[[RDF-CANON]], passing the joined `filteredNQuads`. Canonicalize `filteredNQuads
+Note: These two steps can be performed in parallel.
+
+ -
+Get the `groupResult` by calling the algorithm in Section
+, passing `filteredNQuads`, `filteredDocument`,
+`groupFrame`, and any custom JSON-LD API options.
+
+
+ -
+Note: Next generate matching and non-matching maps composed of original indexes
+to original N-Quads. The `groupResult` is different; it contains matching and
+non-matching maps using the `filteredNQuads` indexes. Both maps of indexes are
+useful to callers.
+
+ -
+Initialize `matching` to a new map.
+
+ -
+Initialize `nonMatching` to a new map.
+
+ -
+Initialize filteredMatches to the values in `groupResult.matching`.
+
+ -
+Initialize filteredNonMatches to the values in `groupResult.nonMatching`.
+
+ -
+For each entry (`index`, `nq`) in `nquads`:
+
+ -
+If `filteredMatches` includes `nq` then add the entry to `matching`.
+
+ -
+Otherwise, if `filteredNonMatching` includes `nq` then add the entry to
+`nonMatching`.
+
+
+
+ -
+Initialize `labelMap` to the reverse of `canonicalIdMap`. `labelMap` uses
+canonical blank node identifiers as keys and original blank node identifiers as
+values.
+
+ -
+Return an object with "filtered" set to `groupResult`, "labelMap" set to
+`labelMap`, "matching" to `matching`, and "nonMatching" to `nonMatching`.
+
+
+
+
+
+ hashMandatoryNQuads
+
+
+The following algorithm cryptographically hashes an array of mandatory to
+disclose N-Quads using a provided hashing API. The required input is an array of
+mandatory to disclose N-Quads (mandatory) and a hashing function
+(hasher). A cryptographic hash (mandatoryHash) is produced
+as output.
+
+
+
+ -
+Initialize `bytes` to the UTF-8 representation of the joined `mandatory`
+N-Quads.
+
+ -
+Initialize `mandatoryHash` to the result of using `hasher` to hash `bytes`.
+
+ -
+Return `mandatoryHash`.
+
+
+
+
+
+
+
+ ecdsa-sd-2023 Functions
+
+
+The Working Group is seeking implementer feedback on these cryptographic suite
+functions as well as horizonal security review on the feature from parties at
+W3C and IETF. Those reviews might result in significant changes to these
+algorithms, or the removal of the algorithms from the specification during the
+Candidate Recommendation phase.
+
+
+
+This section contains subalgorithms that are useful to the `ecdsa-sd-2023`
+cryptographic suite.
+
+
+
+ serializeSignData
+
+
+The following algorithm serializes the data that is to be signed by the private
+key associated with the base proof verification method. The required inputs are
+the proof options hash (proofHash), the proof-scoped multikey-encoded
+public key (publicKey), and the mandatory hash
+(mandatoryHash). A single sign data value,
+represented as series of bytes, is produced as output.
+
+
+
+ -
+Return the concatenation of proofHash, publicKey, and
+mandatoryHash, in that order, as sign data.
+
+
+
+
+
+
+ serializeBaseProofValue
+
+
+The following algorithm serializes the base proof value, including the
+base signature, public key, HMAC key, signatures, and mandatory pointers.
+The required inputs are a base signature baseSignature, a public key
+publicKey, an HMAC key hmacKey, an array of
+signatures, and an array of mandatoryPointers.
+A single base proof string value is produced as output.
+
+
+
+ -
+Initialize a byte array, `proofValue`, that starts with the ECDSA-SD base proof
+header bytes 0xd9, 0x5d, and 0x00.
+
+ -
+Initialize `components` to an array with five elements containing the values of:
+`baseSignature`, `publicKey`, `hmacKey`, `signatures`, and `mandatoryPointers`.
+
+ -
+CBOR-encode `components` and append it to `proofValue`.
+
+ -
+Initialize `baseProof` to a string with the multibase-base64url-no-pad-encoding
+of `proofValue`. That is, return a string starting with "u" and ending with the
+base64url-no-pad-encoded value of `proofValue`.
+
+ -
+Return `baseProof` as base proof.
+
+
+
+
+
+
+ parseBaseProofValue
+
+
+The following algorithm parses the components of an `ecdsa-sd-2023` 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 "baseSignature", "publicKey", "hmacKey",
+"signatures", and "mandatoryPointers", is produced as output.
+
+
+
+ -
+Ensure the `proofValue` string starts with `u`, indicating that it is a
+multibase-base64url-no-pad-encoded value, throwing an error if it does not.
+
+ -
+Initialize `decodedProofValue` to the result of base64url-no-pad-decoding the
+substring after the leading `u` in `proofValue`.
+
+ -
+Ensure that the `decodedProofValue` starts with the ECDSA-SD base proof header
+bytes 0xd9, 0x5d, and 0x00, throwing an error if it does not.
+
+ -
+Initialize `components` to an array that is the result of CBOR-decoding the
+bytes that follow the three-byte ECDSA-SD base proof header. Ensure the result
+is an array of five elements.
+
+ -
+Return an object with properties set to the five elements, using the names
+"baseSignature", "publicKey", "hmacKey", "signatures", and "mandatoryPointers",
+respectively.
+
+
+
+
+
+
+ createDisclosureData
+
+
+The following algorithm creates data to be used to generate a derived proof. The
+inputs include a JSON-LD document (document), an ECDSA-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 "baseSignature", "publicKey",
+"signatures" for "filteredSignatures", "labelMap", "mandatoryIndexes", and
+"revealDocument" fields.
+
+
+
+ -
+Initialize `baseSignature`, `publicKey`, `hmacKey`, `signatures`, and
+`mandatoryPointers` to the values of the associated properties in the object
+returned when calling the algorithm in Section
+, passing the `proofValue` from `proof`.
+
+ -
+Initialize `hmac` to an HMAC API using `hmacKey`. The HMAC uses the same hash
+algorithm used in the signature algorithm, i.e., SHA-256 for a P-256 curve.
+
+ -
+Initialize `nquads` to the result of calling the algorithm in Section
+, passing `document`, `hmac`, and any custom
+JSON-LD API options as parameters. Note: This step transforms the document into
+an array of canonical N-Quads with pseudorandom blank node identifiers based on
+`hmac`.
+
+ -
+Initialize `mandatoryFrame` to the result of calling the algorithm in Section , passing `document` and `mandatoryPointers` as
+`pointers`.
+
+ -
+Initialize `combinedFrame` to the result of calling the
+ primitive, passing `document` and the
+concatenation of `mandatoryPointers` and `selectivePointers` as `pointers`.
+
+ -
+If `mandatoryFrame` and `combinedFrame` are both `null`, then throw an error
+indicating that nothing is to be disclosed.
+
+ -
+Execute the following two steps in parallel (if the runtime environment allows
+for parallel execution, otherwise, execute the operations serially):
+
+ -
+Initialize `revealDocument` to the result of calling the algorithm in
+Section , passing `document`, `combinedFrame` as
+`frame`, and any custom JSON-LD API options.
+
+ -
+Initialize `filterAndGroupResult` to the result of calling the algorithm in
+Section , passing `nquads`, `combinedFrame` for
+`filterFrame`, `mandatoryFrame` for `groupFrame`, and any custom JSON-LD API
+options.
+
+
+
+ -
+Initialize `labelMap` to the value of "labelMap" in `filterAndGroupResult`.
+
+ -
+Initialize `relativeMandatory` to the value of "matching" in the value of
+"filtered" in `filterAndGroupResult`.
+
+ -
+Initialize `absoluteMandatory` to the value of "matching" in
+`filterAndGroupResult`.
+
+ -
+Initialize `absoluteNonMandatory` to the value of "nonMatching" in
+`filterAndGroupResult`.
+
+ -
+Initialize `mandatoryIndexes` to the keys from `relativeMandatory`.
+
+ -
+Choose the signatures that match the selectively disclosed statements, which
+requires shifting by any absolute mandatory indexes to cause the indexes in
+`signatures` to match with `absoluteNonMandatory` map keys:
+
+ -
+Initialize `index` to `0`.
+
+ -
+Initialize `filteredSignatures` to an empty array.
+
+ -
+For each `signature` in `signatures`:
+
+ -
+While `index` is in `absoluteMandatory`, increment `index`.
+
+ -
+If `index` is in `absoluteNonMandatory`, add `signature` to
+`filteredSignatures`.
+
+ -
+Increment `index`.
+
+
+
+
+
+ -
+Return an object with properties matching `baseSignature`, `publicKey`,
+"signatures" for `filteredSignatures`, `labelMap`, `mandatoryIndexes`, and
+`revealDocument`.
+
+
+
+
+
+
+ compressLabelMap
+
+
+The following algorithm compresses a label map. The required inputs are
+label map (labelMap). The output is a compressed label map.
+
+
+
+ -
+Initialize `map` to an empty map.
+
+ -
+For each entry (`k`, `v`) in `labelMap`:
+
+ -
+Add an entry to `map` with a key that is a base-10 integer parsed from the
+characters following the "c14n" prefix in `k` and a value that is a byte array
+resulting from base64url-no-pad-decoding the characters after the "u" prefix in
+ `v`.
+
+
+ -
+Return `map` as compressed label map.
+
+
+
+
+
+
+ decompressLabelMap
+
+
+The following algorithm decompresses a label map. The required input is a
+compressed label map (compressedLabelMap). The output is a
+decompressed label map.
+
+
+
+ -
+Initialize `map` to an empty map.
+
+ -
+For each entry (`k`, `v`) in `compressedLabelMap`:
+
+ -
+Add an entry to `map` with a key that adds the prefix "c14n" to `k` and a value
+that adds a prefix of "u" to the base64url-no-pad-encoded value for `v`.
+
+
+ -
+Return `map` as decompressed label map.
+
+
+
+
+
+
+ serializeDerivedProofValue
+
+
+The following algorithm serializes a derived proof value. The required inputs
+are a base signature (baseSignature), public key
+(publicKey), an array of signatures (signatures), a label
+map (labelMap), and an array of mandatory indexes
+(mandatoryIndexes). A single derived proof value, serialized
+as a byte string, is produced as output.
+
+
+
+ -
+Initialize `compressedLabelMap` to the result of calling the algorithm in
+Section , passing `labelMap` as the parameter.
+
+ -
+Initialize a byte array, `proofValue`, that starts with the ECDSA-SD disclosure
+proof header bytes `0xd9`, `0x5d`, and `0x01`.
+
+ -
+Initialize `components` to an array with five elements containing the values of:
+`baseSignature`, `publicKey`, `signatures`, `compressedLabelMap`, and
+`mandatoryIndexes`.
+
+ -
+CBOR-encode `components` and append it to `proofValue`.
+
+ -
+Return the derived proof as a string with the
+multibase-base64url-no-pad-encoding of `proofValue`. That is, return a string
+starting with "u" and ending with the base64url-no-pad-encoded value of
+`proofValue`.
+
+
+
+
+
+
+ parseDerivedProofValue
+
+
+The following algorithm parses the components of the derived proof value.
+The required inputs are a derived proof value (proofValue). A
+A single derived proof value value object is produced as output, which
+contains a set to five elements, using the names "baseSignature", "publicKey",
+"signatures", "labelMap", and "mandatoryIndexes".
+
+
+
+ -
+Ensure the `proofValue` string starts with `u`, indicating that it is a
+multibase-base64url-no-pad-encoded value, throwing an error if it does not.
+
+ -
+Initialize `decodedProofValue` to the result of base64url-no-pad-decoding the
+substring after the leading `u` in `proofValue`.
+
+ -
+Ensure that the `decodedProofValue` starts with the ECDSA-SD disclosure proof
+header bytes `0xd9`, `0x5d`, and `0x01`, throwing an error if it does not.
+
+ -
+Initialize `components` to an array that is the result of CBOR-decoding the
+bytes that follow the three-byte ECDSA-SD disclosure proof header. Ensure the
+result is an array of five elements. Ensure the result is an array of five
+elements: a byte array of length 64, a byte array of length 36, an array of byte
+arrays, each of length 64, a map of integers to byte arrays of length 32, and an
+array of integers, throwing an error if not.
+
+ -
+Replace the fourth element in `components` using the result of calling the
+algorithm in Section , passing the existing
+fourth element of `components` as `compressedLabelMap`.
+
+ -
+Return derived proof value as an object with properties set to the five
+elements, using the names "baseSignature", "publicKey", "signatures",
+"labelMap", and "mandatoryIndexes", respectively.
+
+
+
+
+
+
+ createVerifyData
+
+
+The following algorithm creates the data needed to perform verification of an
+ECDSA-SD-protected verifiable credential. The inputs include a JSON-LD
+document (document), an ECDSA-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: "baseSignature", "proofHash", "publicKey", "signatures", "nonMandatory",
+and "mandatoryHash".
+
+
+
+ -
+Initialize `proofHash` to the result of perform RDF Dataset Canonicalization
+[[RDF-CANON]] on the proof options. The hash used is the same as the one used in
+the signature algorithm, i.e., SHA-256 for a P-256 curve. Note: This step can be
+performed in parallel; it only needs to be completed before this algorithm needs
+to use the `proofHash` value.
+
+ -
+Initialize `baseSignature`, `publicKey`, `signatures`, `labelMap`, and
+`mandatoryIndexes`, to the values associated with their property names in the
+object returned when calling the algorithm in Section
+, passing `proofValue` from `proof`.
+
+ -
+Initialize `nquads` to the result of calling the "labelReplacementCanonize"
+primitive, passing `document`, the result of calling the "labelMapCanonize"
+primitive (passing `labelMap`) as `labelReplacementFunction`, and any custom
+JSON-LD API options. Note: This step transforms the document into an array of
+canonical N-Quads with pseudorandom blank node identifiers based on `labelMap`.
+
+ -
+Initialize `mandatory` to an empty array.
+
+ -
+Initialize `nonMandatory` to an empty array.
+
+ -
+For each entry (`index`, `nq`) in `nquads`, separate the N-Quads into mandatory
+and non-mandatory categories:
+
+ -
+If `mandatoryIndexes` includes `index`, add `nq` to `mandatory`.
+
+ -
+Otherwise, add `nq` to `nonMandatory`.
+
+
+ -
+Initialize `mandatoryHash` to the result of calling the "hashMandatory"
+primitive, passing `mandatory`.
+
+ -
+Return an object with properties matching `baseSignature`, `proofHash`,
+`publicKey`, `signatures`, `nonMandatory`, and `mandatoryHash`.
+
+
+
+
+
+
+
+
+ ecdsa-sd-2023
+
+
+The Working Group is seeking implementer feedback on this cryptographic suite
+as well as horizonal security review on the feature from parties at W3C and
+IETF. Those reviews might result in significant changes to this algorithm, or
+the removal of the algorithm from the specification during the Candidate
+Recommendation phase.
+
+
+
+The `ecdsa-sd-2023` cryptographic suite takes an input document, canonicalizes
+the document using the Universal 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.
+
+
+
+
+
+ Base Proof Transformation (ecdsa-sd-2023)
+
+
+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 .
+
+
+
+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.
+
+
+
+ -
+Initialize `hmac` to an HMAC API using a locally generated and exportable HMAC
+key. The HMAC uses the same hash algorithm used in the signature algorithm,
+which is detected via the verificationMethod provided to the
+function. i.e., SHA-256 for a P-256 curve.
+
+ -
+Initialize `nquads` to the result of calling the algorithm in Section
+, passing `unsecuredDocument`, the
+result of calling the algorithm in Section
+ (passing `hmac`) as the
+`labelReplacementFunction`, and any custom JSON-LD API options. Note: This step
+transforms the document into an array of canonical N-Quads with pseudorandom
+blank node identifiers based on `hmac`.
+
+ -
+Initialize `mandatoryFrame` to the result of calling the algorithm in Section
+, passing `document` and `mandatoryPointers` as
+`pointers`.
+
+ -
+Initialize `matching` and `nonMatching` to the result of calling the algorithm
+in Section , passing `nquads`, `mandatoryFrame` as
+`frame`, and any custom JSON-LD API options. Note: This step separates the
+N-Quads to mandatory (to disclose) and non-mandatory groups.
+
+ -
+Initialize `mandatory` to the values in the `matching` map.
+
+ -
+Initialize `nonMandatory` to the values in the `nonMatching` map.
+
+ -
+Initialize `hmacKey` to the result of exporting the HMAC key from `hmac`.
+
+ -
+Return an object with "mandatoryPointers" set to `mandatoryPointers`,
+"mandatory" set to `mandatory`, "nonMandatory" set to `nonMandatory`,
+and "hmacKey" set to `hmacKey`.
+
+
+
+
+
+ Base Proof Hashing (ecdsa-sd-2023)
+
+
+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 .
+
+
+
+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.
+
+
+
+ -
+Initialize `proofHash` to the result of calling the RDF Dataset Canonicalization
+algorithm [[RDF-CANON]] on `canonicalProofConfig` and then cryptographically
+hashing the result using the same hash that is used by the signature algorithm,
+i.e., SHA-256 for a P-256 curve. Note: This step can be performed in parallel;
+it only needs to be completed before this algorithm terminates as the result is
+part of the return value.
+
+ -
+Initialize `mandatoryHash` to the result of calling the the algorithm in Section
+, passing
+transformedDocument.`mandatory`.
+
+ -
+Initialize `hashData` as a deep copy of transformedDocument and
+add `proofHash` as "proofHash" and `mandatoryHash` as "mandatoryHash" to that
+object.
+
+ -
+Return `hashData` as hash data.
+
+
+
+
+
+
+ Base Proof Configuration (ecdsa-sd-2023)
+
+
+The following algorithm specifies how to generate a
+proof configuration from a set of proof options
+that is used as input to the
+base proof hashing algorithm.
+
+
+
+The required inputs to this algorithm are proof options
+(options). The proof options MUST contain a type identifier
+for the
+
+cryptographic suite (type) and MUST contain a cryptosuite
+identifier (cryptosuite). A proof configuration
+object is produced as output.
+
+
+
+ -
+Let proofConfig be an empty object.
+
+ -
+Set proofConfig.type to
+options.type.
+
+ -
+If options.cryptosuite is set, set
+proofConfig.cryptosuite to its value.
+
+ -
+If options.type is not set to `DataIntegrityProof` and
+proofConfig.cryptosuite is not set to `ecdsa-sd-2023`, an
+`INVALID_PROOF_CONFIGURATION` error MUST be raised.
+
+ -
+Set proofConfig.created to
+options.created. If the value is not a valid
+[[XMLSCHEMA11-2]] datetime, an `INVALID_PROOF_DATETIME` error MUST be raised.
+
+ -
+Set proofConfig.verificationMethod to
+options.verificationMethod.
+
+ -
+Set proofConfig.proofPurpose to
+options.proofPurpose.
+
+ -
+Set proofConfig.@context to
+unsecuredDocument.@context.
+
+ -
+Let canonicalProofConfig be the result of applying the
+Universal RDF Dataset Canonicalization Algorithm
+[[RDF-CANON]] to the proofConfig.
+
+ -
+Return canonicalProofConfig.
+
+
+
+
+
+
+ Base Proof Serialization (ecdsa-sd-2023)
+
+
+The following algorithm specifies how to create a base proof; called by an
+issuer of an ECDSA-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.
+
+
+
+ -
+Initialize `proofHash`, `mandatoryPointers`, `mandatoryHash`, `nonMandatory`,
+and `hmacKey` to the values associated with their property names
+hashData.
+
+ -
+Initialize `proofScopedKeyPair` to a locally generated P-256 ECDSA key pair.
+Note: This key pair is scoped to the specific proof; it is not used for anything
+else and the private key will be destroyed when this algorithm terminates.
+
+ -
+Initialize `signatures` to an array where each element holds the result of
+digitally signing the UTF-8 representation of each N-Quad string in
+`nonMandatory`, in order. The digital signature algorithm is ES256, i.e., uses a
+P-256 curve over a SHA-256 digest, and uses the private key from
+`proofScopedKeyPair`. Note: This step generates individual signatures for each
+statement that can be selectively disclosed using a local, proof-scoped key pair
+that binds them together; this key pair will be bound to the proof by a
+signature over its public key using the private key associated with the base
+proof verification method.
+
+ -
+Initialize `publicKey` to the multikey expression of the public key exported
+from `proofScopedKeyPair`. That is, an array of bytes starting with the bytes
+0x80 and 0x24 (which is the multikey p256-pub header (0x1200) expressed as a
+varint) followed by the compressed public key bytes (the compressed header with
+`2` for an even `y` coordinate and `3` for an odd one followed by the `x`
+coordinate of the public key).
+
+ -
+Initialize `toSign` to the result of calling the algorithm in Section
+, passing `proofHash`, `publicKey`, and
+`mandatoryHash` as parameters to the algorithm.
+
+ -
+Initialize `baseSignature` to the result of digitally signing `toSign` using the
+private key associated with the base proof verification method.
+
+ -
+Initialize `proofValue to the result of calling the algorithm in Section
+, passing `baseSignature`,
+`publicKey`, `hmacKey`, `signatures`, and `mandatoryPointers` as parameters
+to the algorithm.
+
+ -
+Return `proofValue` as digital proof.
+
+
+
+
+
+
+ Add Derived Proof (ecdsa-sd-2023)
+
+
+The following algorithm creates a selective disclosure derived proof; called by
+a holder of an `ecdsa-sd-2023`-protected verifiable credential.
+The derived proof is to be given to the verifier. The inputs include a
+JSON-LD document (document), an ECDSA-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.
+
+
+
+ -
+Initialize `baseSignature`, `publicKey`, `signatures`, `labelMap`,
+`mandatoryIndexes`, `revealDocument` to the values associated with their
+property names in the object returned when calling the algorithm in
+Section , passing the `document`, `proof`,
+`selectivePointers`, and any custom JSON-LD API options, such as a document
+loader.
+
+ -
+Initialize `newProof` to a shallow copy of `proof`.
+
+ -
+Replace `proofValue` in `newProof` with the result of calling the algorithm
+in Section , passing
+`baseSignature`, `publicKey`, `signatures`, `labelMap`, and `mandatoryIndexes`.
+
+ -
+Set the value of the "proof" property in `revealDocument` to `newProof`.
+
+ -
+If `revealDocument` has an `@context` field that includes a verifiable
+credential base context and it has a "credentialSubject" property that is a
+string, set the "credentialSubject" value to an object with an "id" value that
+matches the original string value.
+
+ -
+Return `revealDocument` as the selectively revealed document.
+
+
+
+
+
+
+ Verify Derived Proof (ecdsa-sd-2023)
+
+
+The following algorithm attempts verification of an `ecdsa-sd-2023` derived
+proof. This algorithm is called by a verifier of an ECDSA-SD-protected
+verifiable credential. The inputs include a JSON-LD document
+(document), an ECDSA-SD disclosure proof (proof), and any
+custom JSON-LD API options, such as a document loader. A single boolean
+verification result value is produced as output.
+
+
+
+ -
+Initialize `baseSignature`, `proofHash`, `publicKey`, `signatures`,
+`nonMandatory`, and `mandatoryHash` to the values associated with their property
+names in the object returned when calling the algorithm in Section
+, passing the `document`, `proof`, and any
+custom JSON-LD API options, such as a document loader.
+
+ -
+If the length of `signatures` does not match the length of `nonMandatory`, throw
+an error indicating that the signature count does not match the non-mandatory
+message count.
+
+ -
+Initialize `publicKeyBytes` to the public key bytes expressed in `publicKey`.
+Instructions on how to decode the public key value can be found in Section
+.
+
+ -
+Initialize `toVerify` to the result of calling the algorithm in Setion
+, passing `proofHash`, `publicKey`, and
+`mandatoryHash`.
+
+ -
+Initialize `verificationResult` be the result of applying the verification
+algorithm of the Elliptic Curve Digital Signature Algorithm (ECDSA) [FIPS-186-5],
+with `toVerify` as the data to be verified against the `baseSignature` using
+the public key specified by `publicKeyBytes`. If `verificationResult` is
+`false`, return `false`.
+
+ -
+For every entry (`index`, `signature`) in `signatures`, verify every signature
+for every selectively disclosed (non-mandatory) statement:
+
+ -
+Initialize `verificationResult` to the result of applying the verification
+algorithm Elliptic Curve Digital Signature Algorithm (ECDSA) [FIPS-186-5], with
+the UTF-8 representation of the value at `index` of `nonMandatory` as the data
+to be verified against `signature` using the public key specified by
+`publicKeyBytes`.
+
+ -
+If `verificationResult` is `false`, return `false`.
+
+
+
+
+ -
+Return `verificationResult` as verification result.
+
+
+
+
+
+
+