This specification describes the Merkle Proof Signature Suite created in 2019 for the Linked Data Proofs specification.
This is an experimental specification and is undergoing regular revisions. It is not fit for production deployment.
This specification describes the Merkle Proof Signature Suite created in 2019 for the Linked Data Proofs [[LD-PROOFS]] specification. It uses the RDF Dataset CANONICALIZATION Algorithm [[RDF-DATASET-CANONICALIZATION]] to transform the input document into its canonical form. It uses SHA-256 [[RFC6234]] as the message digest algorithm and ECDSA signature algorithm with a secp256k1 curve described in [[LDS-ECDSA-SECP256K1-2019]] as the proof algorithm.
The following terms are used to describe concepts involved in the generation and verification of the Linked Data Proof 2019 proof suite.
The 2019 Merkle Proof proof suite MUST be used in conjunction with the signing and verification algorithms in the Linked Data Proofs [[LD-PROOFS]] specification. The suite consists of the following algorithms:
Parameter | Value | Specification |
---|---|---|
canonicalizationAlgorithm | https://w3id.org/security#GCA2015 | [[RDF-DATASET-CANONICALIZATION]] |
digestAlgorithm | https://tools.ietf.org/html/rfc6234 | [[RFC6234]] |
signatureAlgorithm | https://w3c-ccg.github.io/lds-ecdsa-secp256k1-2019 | [[LDS-ECDSA-SECP256K1-2019]] |
This signature suite uses the root hash of the Merkle Tree defined in [[RFC6962]] and [[LDS-ECDSA-SECP256K1-2019]]. The signature algorithm uses the Merkle Tree root hash, stored in the input data of a Bitcoin or Ethereum transaction with ECDSA signature.
The digital signature algorithm defined in Section 7.1: Signature Algorithm takes an array of tbs, a privateKey, and options as inputs and produces a proofValue as an output.
data
field of the transaction.
targetHash
merkleRoot
targetHash
to merkleRoot
in the
Merkle Tree, as proof
. The should not include the endpoints of the path (targetHash
and
merkleRoot
)
blink
(Blockchain Links specification).
The URL format of a Blockchain Link is the following:
blink:::[:]
base58btc
encoding and
return the result string as proofValue.
The proofValue object descrined in the previous step must be encoded using CBOR before encoding the result using base58btc
.
merkleRoot
: 0targetHash
: 1anchors
: 2
BLOCKCHAIN
: 0NETWORK
: 1TRANSACTION
: 2BlOCK
: 3 (optional)path
: 3
left
: 0right
: 1btc
: 0
mainnet
: 1testnet
: 3eth
: 1
mainnet
: 1ropsten
: 3rinkeby
: 4Prior to verifying the signature, proofValue object must be reconstructed from CBOR / multo-base encoded string.
In order to do that, a reverse algorithm to Compressing and encoding proofValue using CBOR must be applied.
The digital signature algorithm defined in Section 7.2: Signature Verification Algorithm takes the value to be verified, a tbv, the public key to the signature algorithm and returns a boolean value.
targetHash
, path
, and merkleRoot
form a valid Merkle Path.
targetHash
matches the JSON-LD canonicalized, SHA256 Hash of tbv.
merkleRoot
matches what is stored in the transaction at blink URL (Blockchain Link).
true
, otherwise return false
.
The following section describes security considerations that developers implementing this specification should be aware of in order to create secure software.
A simple example of a decoded proofValue:
"proofValue": { "path": [ { "right": "51b4e22ed024ec7f38dc68b0bf78c87eda525ab0896b75d2064bdb9fc60b2698" }, { "right": "61c56cca660b2e616d0bd62775e728f50275ae44adf12d1bfb9b9c507a14766b" } ], "merkleRoot": "3c9ee831b8705f2fbe09f8b3a92247eed88cdc90418c024924be668fdc92e781", "targetHash": "c65c6184e3d5a945ddb5437e93ea312411fd33aa1def22b0746d6ecd4aa30f20", "anchors": [ "blink:btc:testnet:582733d7cef8035d87cecc9ebbe13b3a2f6cc52583fbcd2b9709f20a6b8b56b3" ] }
An example of CDDL for CBOR-encoded proofValue:
84 # array(4) 82 # array(2) 03 # unsigned(3) 82 # array(2) 82 # array(2) 01 # unsigned(1) 58 22 # bytes(34) 582051B4E22ED024EC7F38DC68B0BF78C87EDA525AB0896B75D2064BDB9FC60B2698 # "X Q\xB4\xE2.\xD0$\xEC\x7F8\xDCh\xB0\xBFx\xC8~\xDARZ\xB0\x89ku\xD2\x06K\xDB\x9F\xC6\v&\x98" 82 # array(2) 01 # unsigned(1) 58 22 # bytes(34) 582061C56CCA660B2E616D0BD62775E728F50275AE44ADF12D1BFB9B9C507A14766B # "X a\xC5l\xCAf\v.am\v\xD6'u\xE7(\xF5\x02u\xAED\xAD\xF1-\e\xFB\x9B\x9CPz\x14vk" 82 # array(2) 00 # unsigned(0) 58 22 # bytes(34) 58203C9EE831B8705F2FBE09F8B3A92247EED88CDC90418C024924BE668FDC92E781 # "X <\x9E\xE81\xB8p_/\xBE\t\xF8\xB3\xA9\"G\xEE\xD8\x8C\xDC\x90A\x8C\x02I$\xBEf\x8F\xDC\x92\xE7\x81" 82 # array(2) 01 # unsigned(1) 58 22 # bytes(34) 5820C65C6184E3D5A945DDB5437E93EA312411FD33AA1DEF22B0746D6ECD4AA30F20 # "X \xC6\\a\x84\xE3\xD5\xA9E\xDD\xB5C~\x93\xEA1$\x11\xFD3\xAA\x1D\xEF\"\xB0tmn\xCDJ\xA3\x0F " 82 # array(2) 02 # unsigned(2) 81 # array(1) 83 # array(3) 82 # array(2) 00 # unsigned(0) 00 # unsigned(0) 82 # array(2) 01 # unsigned(1) 03 # unsigned(3) 82 # array(2) 02 # unsigned(2) 58 22 # bytes(34) 5820582733D7CEF8035D87CECC9EBBE13B3A2F6CC52583FBCD2B9709F20A6B8B56B3 # "X X'3\xD7\xCE\xF8\x03]\x87\xCE\xCC\x9E\xBB\xE1;:/l\xC5%\x83\xFB\xCD+\x97\t\xF2\nk\x8BV\xB3"
A simple example of a Merkle Proof Signature Suite 2019 signature (proofValue encoded):
"proof": { "@context": ["https://w3id.org/security/v2"], "type": "MerkleProof2019", "creator": "did:example:abcdefghij0123456789", "created": "2019-10-16T20:21:34Z", "domain": "example.org", "nonce": "2bbgh3dgjg2302d-d2b3gi423d42", "proofValue": "z6nGv6rMRybRe9CuMzbQbdu7sA858v1d13JU3hoAr1x93cheinB35kDXqCvaA93WTLWGtLZMdQSvvNCxEMZPhLvDa4CbUYkm4pCwBe7kCZAsuwHZwHxgyzCbRUWFbMXHhkVSHoPYmPzfi4arfHKMgKSurZ7oqe3GHRdi78TbHGvA65edK8JBEdTUt8SpCdc7wz5qiwj3THtcNAXfgK4LmCAu4fq8CnjLcMtGoEdfXfjy3turtaTapyM3katuYKAzbJF3FiE8i8NXBsiBnEbvKk7k" }