Add static verify method

This commit is contained in:
Miguel Mota 2021-07-04 01:23:15 -07:00
parent c9517a5005
commit 49ee00c1c0
No known key found for this signature in database
GPG Key ID: 67EC1161588A00F9
5 changed files with 49 additions and 12 deletions

View File

@ -170,7 +170,7 @@ Class reprensenting a Merkle Tree
### constructor
\+ **new MerkleTree**(`leaves`: any[], `hashAlgorithm`: any, `options`: [Options](#options)): *[MerkleTree](_index_.merkletree.md)*
\+ **new MerkleTree**(`leaves`: any[], `hashFn`: any, `options`: [Options](#options)): *[MerkleTree](_index_.merkletree.md)*
**`desc`** Constructs a Merkle Tree.
All nodes and leaves are stored as Buffers.
@ -196,7 +196,7 @@ const tree = new MerkleTree(leaves, sha256)
Name | Type | Default | Description |
------ | ------ | ------ | ------ |
`leaves` | any[] | - | Array of hashed leaves. Each leaf must be a Buffer. |
`hashAlgorithm` | any | SHA256 | Algorithm used for hashing leaves and nodes |
`hashFn` | any | SHA256 | Hash function to use for hashing leaves and nodes |
`options` | [Options](#options) | {} | Additional options |
**Returns:** *[MerkleTree](_index_.merkletree.md)*
@ -973,7 +973,7 @@ ___
**hashLeaves**? : *boolean*
If set to `true`, the leaves will hashed using the set hashing algorithms.
If set to `true`, the leaves will hashed using the set hashing functions.
___
@ -1025,7 +1025,7 @@ npm test
## Notes
As is, this implemenation is vulnerable to a [second pre-image attack](https://en.wikipedia.org/wiki/Merkle_tree#Second_preimage_attack). Use a difference hashing algorithm function for leaves and nodes, so that `H(x) != H'(x)`.
As is, this implemenation is vulnerable to a [second pre-image attack](https://en.wikipedia.org/wiki/Merkle_tree#Second_preimage_attack). Use a difference hashing function for leaves and nodes, so that `H(x) != H'(x)`.
Also, as is, this implementation is vulnerable to a forgery attack for an unbalanced tree, where the last leaf node can be duplicated to create an artificial balanced tree, resulting in the same Merkle root hash. Do not accept unbalanced tree to prevent this.

View File

@ -42,7 +42,7 @@ var tree
function compute () {
const value = getInputValue()
const leaves = parseInput(value)
const hash = getHashFn()
const hashFn = getHashFn()
const fillDefaultHash = getDefaultFillHashInput()
const _options = Object.assign({}, options, {
fillDefaultHash: options.fillDefaultHash ? fillDefaultHash : undefined
@ -50,7 +50,7 @@ function compute () {
console.log('input leaves:', leaves)
console.log('hash:', getHashType())
console.log('options:', _options)
tree = new window.MerkleTree(leaves, hash, _options)
tree = new window.MerkleTree(leaves, hashFn, _options)
const hexRoot = tree.getHexRoot()
const hexLeaves = tree.getHexLeaves()
const hexLayers = tree.getHexLayers()
@ -111,13 +111,11 @@ function setVerified (verified) {
function verify () {
setVerified('')
if (!tree) {
return
}
const proof = getVerifyProof()
const leaf = getVerifyLeaf()
const root = getVerifyRoot()
const verified = tree.verify(proof, leaf, root)
const hashFn = getHashFn()
const verified = window.MerkleTree.verify(proof, leaf, root, hashFn, options)
setVerified(`${verified}`)
}

View File

@ -1,6 +1,6 @@
{
"name": "merkletreejs",
"version": "0.2.21",
"version": "0.2.22",
"description": "Construct Merkle Trees and verify proofs",
"main": "dist/index.js",
"types": "dist/index.d.ts",

View File

@ -48,7 +48,7 @@ export class MerkleTree extends Base {
* All nodes and leaves are stored as Buffers.
* Lonely leaf nodes are promoted to the next level up without being hashed again.
* @param {Buffer[]} leaves - Array of hashed leaves. Each leaf must be a Buffer.
* @param {Function} hashFunction - Algorithm used for hashing leaves and nodes
* @param {Function} hashFunction - Hash function to use for hashing leaves and nodes
* @param {Object} options - Additional options
* @example
*```js
@ -376,6 +376,9 @@ export class MerkleTree extends Base {
*```
*/
getProof (leaf: Buffer | string, index?: number):any[] {
if (typeof leaf === 'undefined') {
throw new Error('leaf is required')
}
leaf = this.bufferify(leaf)
const proof = []
@ -892,6 +895,27 @@ export class MerkleTree extends Base {
return objs[0]
}
/**
* verify
* @desc Returns true if the proof path (array of hashes) can connect the target node
* to the Merkle root.
* @param {Object[]} proof - Array of proof objects that should connect
* target node to Merkle root.
* @param {Buffer} targetNode - Target node Buffer
* @param {Buffer} root - Merkle root Buffer
* @param {Function} hashFunction - Hash function for hashing leaves and nodes
* @param {Object} options - Additional options
* @return {Boolean}
* @example
*```js
*const verified = MerkleTree.verify(proof, leaf, root, sha256, options)
*```
*/
static verify (proof: any[], targetNode: Buffer | string, root: Buffer | string, hashFn = SHA256, options: Options = {}):boolean {
const tree = new MerkleTree([], hashFn, options)
return tree.verify(proof, targetNode, root)
}
/**
* getMultiProof
* @desc Returns the multiproof for given tree indices.

View File

@ -88,6 +88,21 @@ test('sha256 with sort pairs option', t => {
t.equal(tree.getRoot().toString('hex'), root)
})
test('sha256 - static verify', t => {
t.plan(2)
const leaves = ['a', 'b', 'c'].map(x => sha256(Buffer.from(x)))
const tree = new MerkleTree(leaves, sha256)
const leaf = sha256(Buffer.from('a'))
const badLeaf = sha256(Buffer.from('o'))
const proof = tree.getProof(leaf)
const badProof = tree.getProof(badLeaf)
const root = tree.getRoot()
t.equal(MerkleTree.verify(proof, leaf, root, sha256), true)
t.equal(MerkleTree.verify(badProof, leaf, root, sha256), false)
})
test('sha256 verify with positional hex proof and no pairSort', t => {
t.plan(1)