| JWP-MDT | December 2021 | |
| Steele | Informational | [Page] |
Merkleproofs have been around for a long time, but there has never been a standardd JSON encoding for them.¶
Summary of merkle proofs¶
Challenges with proof size¶
This document describes the Json Web Proof Merkle Disclosure Token. An encoding for merkle proofs inspired by JWT.¶
The scheme features many important properties:¶
Deterministic nonce generation for membership proofs.¶
Encoding merkle root and related proof data use JWA.¶
Compressing membership proofs¶
Verifying membership proofs¶
These properties allow the scheme to be used in applications where privacy and data minimization techniques are desired and/or required.¶
This scheme is meant to expose interfaces compatible with BBS+ Signature Scheme. Many of the same benefits from that scheme apply here:¶
A recent emerging use case applies signature schemes in verifiable credentials. One problem with using simple signature schemes like ECSDA or ED25519 is a holder must disclose the entire signed message and signature for verification. Circuit based logic can be applied to verify these in zero-knowledge like SNARKS or Bulletproofs with R1CS but tend to be complicated. BBS+ on the other hand adds, to verifiable credentials or any other application, the ability to do very efficient zero-knowledge proofs. A holder gains the ability to choose which claims to reveal to a relying party without the need for any additional complicated logic.¶
The keywords MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL, when they appear in this document, are to be interpreted as described in [RFC2119].¶
//TODO¶
This document is organized as follows:¶
The following terminology is used throughout this document:¶
The secret key for the signature scheme.¶
The public key for the signature scheme.¶
The set of messages to be signed or verified.¶
The set of messages to be signed or verified paired with their deterministic nonce.¶
The protected header to be signed by the JWA scheme.¶
The protected payload to be signed by the JWA scheme.¶
The digital signature output.¶
A cryptographic nonce¶
A set membership proof, represented as a path in a merkle proof from a leaf to a root.¶
A set of membership proofs, encoded as JSON.¶
proofs compressed and encoded as base64url.¶
The funtion that takes a message, index and rootNonce and assigns a deterministic nonce for the message.¶
const calculateMessageNonce = (
message: string,
index: number,
rootNonce: string
) => {
return sha256(message + index + rootNonce);
};
¶
A boolean representing a proof verification, success as true, failure as false.¶
The function that takes JSON encoded path based membership proofs and returns a compressed representation of them. Inverse of expandProofs.¶
The function that takes a compressed representation of membership proofs and return them in JSON. Inverse of compressProofs.¶
The function that takes a set of messages and a rootNonce and produces a merkle root and membership proofs for each message.¶
The function that takes a set of disclosureIndexes, proofs, messages and a rootNonce and produces compressedProofs represenetation of the messages indentified by disclosureIndexes.¶
The function that takes a set messages, proofs and a merkle root, and returns true when all messages have a membership proof that is true, and false otherwise.¶
Not exactly the same thing, but probably better than comparing to vanilla JWA.¶
This section defines core operations used by the schemes defined in Section 3. These operations MUST NOT be used except as described in that section.¶
The core operations in this section depend on several parameters:¶
KeyValidate checks if the public key is valid.¶
As an optimization, implementations MAY cache the result of KeyValidate in order to avoid unnecessarily repeating validation for known keys.¶
result = KeyValidate(PK)¶
Inputs:¶
PK, a public key¶
Outputs:¶
result, either VALID or INVALID¶
Procedure:¶
// TODO¶
Generate proof computes set membership proofs and a signature from SK, over a vector of messages.¶
{ root, nonce, proofs, signature } = generateProof((message\[i\],...,message\[L\]), SK)
¶
Inputs:¶
Outputs:¶
Procedure:¶
// TODO¶
Derive proof transforms the output of generate proof filtering the set membership proofs to match the intended messages to be disclosed and applying the nonce algorithm. This process is also referred to as generating a selective disclosure proof.¶
{ root, proofs, signature } = deriveProof(
(disclosureIndexes[i],...,disclosureIndexes[L]),
(message[i],...,message[L]),
(proof[i],...,proof[L]),
root,
nonce,
signature
)
¶
Inputs:¶
disclosureIndexes[i],...,disclosureIndexes[L], octet integer.¶
message[i],...,message[L], octet strings.¶
proof[i],...,proof[L], octet strings.¶
root, octet string.¶
nonce, octet string.¶
signature, octet string.¶
Outputs:¶
root, octet string, unchanged by function.¶
proofs, octet string.¶
signature, octet string, unchanged by function.¶
Procedure:¶
//TODO¶
Verify checks that a proof is valid for the octet string messages under the public key.¶
verification = Verify((message[i],...,message[L]), (proof[i],...,proof[L]), root, signature, PK)¶
Inputs:¶
message[i],...,message[L], octet strings.¶
proof[i],...,proof[L], octet strings.¶
root, octet string.¶
signature, octet string.¶
PK, a public key¶
Outputs:¶
verification, either VALID or INVALID.¶
Procedure:¶
// TODO¶
{
// From JWP "Protected Header"
// always disclosed
"protected": {
"kid": "did:example:123#key-0"
"root": "SflKxwRJSM...",
"alg": "MDP+ES256+JP", // merkle disclosure with json pointer
"zip": "DEF"
"signature": "SflKxwRJSM", // over the entire protected header.
},
// From JWP "Payloads" and "Proof"
// selectively disclosed
"payloads": [ { message }, ...]
"proof": [ { path }, ... ],
// never disclosed
"nonce": "0IjoxNTE2MjM5..."
}
¶
{
// From JWP "Protected Header"
// always disclosed
"protected": {
"kid": "did:example:123#key-0"
"root": "SflKxwRJSM...",
"alg": "MDP+ES256+JP", // merkle disclosure with json pointer
"zip": "DEF"
"signature": "SflKxwRJSM", // over the entire protected header.
},
// From JWP "Payloads" and "Proof"
// selectively disclosed
"payloads": [ { message }, ...]
"proof": [ { path }, ... ],
}
¶
//TODO¶
All algorithms in Section 2 that operate on public keys require first validating those keys. For the sign, verify and proof schemes, the use of KeyValidate is REQUIRED.¶
If the root nonc associatd with a merkle root is disclosed, a verifier or attacker can compute adjcacent membership proofs from sets of disclosed proofs.¶
Implementations of the signing algorithm SHOULD protect the secret key from side-channel attacks. One method for protecting against certain side-channel attacks is ensuring that the implementation executes exactly the same sequence of instructions and performs exactly the same memory accesses, for any value of the secret key. ( this copied verbatum form here).¶
It is recommended that the all nonces are from a trusted source of randomness.¶
TODO: comment on JOSE / COSE.¶
This document does not make any requests of IANA.¶
TODO:¶
Request for JOSE and COSE...:¶
//TODO¶