Comparing version 0.3.1 to 0.4.0
@@ -5,4 +5,14 @@ | ||
function Merkle (hashFunc) { | ||
var REGEXP = { | ||
'md5': /^[0-9a-f]{32}$/i, | ||
'sha1': /^[0-9a-f]{40}$/i, | ||
'ripemd160': /^[0-9a-f]{40}$/i, | ||
'sha256': /^[0-9a-f]{64}$/i, | ||
'sha512': /^[0-9a-f]{128}$/i, | ||
'whirlpool': /^[0-9a-f]{128}$/i, | ||
'DEFAULT': /^$/ | ||
}; | ||
function Merkle (hashFunc, hashFuncName) { | ||
var that = this; | ||
@@ -14,2 +24,3 @@ | ||
that.hashResultRegexp = REGEXP[hashFuncName] || REGEXP.DEFAULT; | ||
that.leaves = []; | ||
@@ -21,3 +32,4 @@ that.treeDepth = 0; | ||
function feed(anyData) { | ||
if(anyData && anyData.match(/^[\w\d]{40}$/)){ | ||
if(anyData && anyData.match(that.hashResultRegexp)){ | ||
// Push leaf without hashing it since it is already a hash | ||
that.leaves.push(anyData.toUpperCase()); | ||
@@ -29,3 +41,3 @@ } | ||
return that; | ||
}; | ||
} | ||
@@ -42,19 +54,19 @@ function depth() { | ||
return that.treeDepth; | ||
}; | ||
} | ||
function levels() { | ||
return depth() + 1; | ||
}; | ||
} | ||
function nodes() { | ||
return that.nodesCount; | ||
}; | ||
} | ||
function root() { | ||
return that.rows[0][0]; | ||
}; | ||
} | ||
function level(i) { | ||
return that.rows[i]; | ||
}; | ||
} | ||
@@ -74,3 +86,3 @@ function compute() { | ||
} | ||
}; | ||
} | ||
@@ -171,3 +183,3 @@ function getNodes(leaves) { | ||
} | ||
}); | ||
}, hashFuncName); | ||
}; |
{ | ||
"name": "merkle", | ||
"version": "0.3.1", | ||
"version": "0.4.0", | ||
"description": "Javascript implementation of merkle trees", | ||
@@ -5,0 +5,0 @@ "main": "merkle.js", |
# Merkle [](https://travis-ci.org/c-geek/merkle) [](http://badge.fury.io/js/merkle) [](https://github.com/c-geek/merkle/blob/master/LICENSE) | ||
Builds a Merkle tree using either sha1, md5 or none algorithm. | ||
Builds a Merkle tree using either sha512, sha256, ripemd160, whirlpool, sha1, md5 or none algorithms. | ||
@@ -104,2 +104,3 @@ ## Usage | ||
```js | ||
var sha256tree= merkle('sha256').sync(abcde); | ||
var sha1tree = merkle('sha1').sync(abcde); | ||
@@ -109,2 +110,5 @@ var md5tree = merkle('md5').sync(abcde); | ||
> sha256tree.root(); | ||
'16E6BEB3E080910740A2923D6091618CAA9968AEAD8A52D187D725D199548E2C' | ||
> sha1tree.root(); | ||
@@ -122,3 +126,3 @@ '114B6E61CB5BB93D862CA3C1DFA8B99E313E66E9' | ||
Installing it globally will introduce the `merkle` command: | ||
Installing it globally will introduce the `merkle` command (using sha1 as default): | ||
@@ -125,0 +129,0 @@ ```bash |
181
test/main.js
@@ -8,2 +8,6 @@ var should = require('should'); | ||
//data available for tests | ||
var abc = ['a', 'b', 'c']; | ||
var abcEmpty = ['a', 'b', 'c', '']; | ||
var abcc = ['a', 'b', 'c', 'c']; | ||
var abcde = ['a', 'b', 'c', 'd', 'e']; | ||
@@ -33,2 +37,24 @@ | ||
describe("merkle stream ['a', 'b', 'c', 'd', 'e'] with 'sha256')", function(){ | ||
var root = null; | ||
before(function (done) { | ||
var m = merkle('sha256'); | ||
m.pipe(es.mapSync(function (data) { | ||
root = data; | ||
done(); | ||
})); | ||
abcde.forEach(function(c){ | ||
m.write(c); | ||
}); | ||
m.end(); | ||
}); | ||
it("should have root '16E6BEB3E080910740A2923D6091618CAA9968AEAD8A52D187D725D199548E2C'", function(){ | ||
assert.equal(root, "16E6BEB3E080910740A2923D6091618CAA9968AEAD8A52D187D725D199548E2C"); | ||
}); | ||
}); | ||
describe("merkle stream ['a', 'b', 'c', 'd', 'e'] with 'md5')", function(){ | ||
@@ -140,3 +166,3 @@ | ||
it("tree shoulnt be null", function(){ | ||
it("tree shouldn't be null", function(){ | ||
should.exist(tree); | ||
@@ -155,1 +181,154 @@ }); | ||
}); | ||
describe("merkle('sha512').async(['a', 'b', 'c', 'd', 'e'])", function(){ | ||
var tree = merkle('sha512').sync(abcde); | ||
it("tree shoulnt be null", function(){ | ||
should.exist(tree); | ||
}); | ||
it("should have root '0F1DDB0F6F807FC6E00948C4DCD9035F83C2CD737F24BCEA278763DF60D90EFE4D7D126F42763A77FBDF520879B0D4A4699CD6AD36A839CF495E32AE35F8E5B7'", function(){ | ||
assert.equal(tree.root(), "0F1DDB0F6F807FC6E00948C4DCD9035F83C2CD737F24BCEA278763DF60D90EFE4D7D126F42763A77FBDF520879B0D4A4699CD6AD36A839CF495E32AE35F8E5B7"); | ||
}); | ||
it('should have depth 3, levels 4, nodes 6', function(){ | ||
assert.equal(tree.depth(), 3); | ||
assert.equal(tree.levels(), 4); | ||
assert.equal(tree.nodes(), 6); | ||
}); | ||
}); | ||
describe("merkle('ripemd160').async(['a', 'b', 'c', 'd', 'e'])", function(){ | ||
var tree = merkle('ripemd160').sync(abcde); | ||
it("tree shoulnt be null", function(){ | ||
should.exist(tree); | ||
}); | ||
it("should have root 'A915A61779C0EB390447CE88A989041D625756C6'", function(){ | ||
assert.equal(tree.root(), "A915A61779C0EB390447CE88A989041D625756C6"); | ||
}); | ||
it('should have depth 3, levels 4, nodes 6', function(){ | ||
assert.equal(tree.depth(), 3); | ||
assert.equal(tree.levels(), 4); | ||
assert.equal(tree.nodes(), 6); | ||
}); | ||
}); | ||
describe("merkle('whirlpool').async(['a', 'b', 'c', 'd', 'e'])", function(){ | ||
var tree = merkle('whirlpool').sync(abcde); | ||
it("tree shoulnt be null", function(){ | ||
should.exist(tree); | ||
}); | ||
it("should have root '57D1AB5281015F92DA7D3EAF740B643F5861565A03A4FC82126F21F69FD3C566FB0A1EA04F572E90FAE7C7AF4984CAE146DBA4618F4D1463A746822D4E21E5EB", function(){ | ||
assert.equal(tree.root(), "57D1AB5281015F92DA7D3EAF740B643F5861565A03A4FC82126F21F69FD3C566FB0A1EA04F572E90FAE7C7AF4984CAE146DBA4618F4D1463A746822D4E21E5EB"); | ||
}); | ||
it('should have depth 3, levels 4, nodes 6', function(){ | ||
assert.equal(tree.depth(), 3); | ||
assert.equal(tree.levels(), 4); | ||
assert.equal(tree.nodes(), 6); | ||
}); | ||
}); | ||
// tests for merkle tree construction vulnerbility https://bitcointalk.org/?topic=102395 | ||
describe("test vulnerbility of redundant leaves in tree construction using ['a', 'b', 'c'] vs ['a', 'b', 'c', 'c']", function(){ | ||
var treeAbc = merkle('sha256').sync(abc); | ||
var treeAbcc = merkle('sha256').sync(abcc); | ||
it("tree shoulnt be null", function(){ | ||
should.exist(treeAbc); | ||
should.exist(treeAbcc); | ||
}); | ||
it("should assert non equality in merkle tree roots of ['a', 'b', 'c'] vs ['a', 'b', 'c', 'c']", function(){ | ||
assert.notEqual(treeAbc.root(), treeAbcc.root()); | ||
}); | ||
}); | ||
// tests for merkle tree construction vulnerbility https://github.com/chainpoint/chainpoint/issues/8 | ||
describe("test vulnerbility of redundant leaves in tree construction using ['a', 'b', 'c'] vs ['a', 'b', 'c', '' ]", function(){ | ||
var treeAbc = merkle('sha256').sync(abc); | ||
var treeAbcEmpty = merkle('sha256').sync(abcEmpty); | ||
it("tree shoulnt be null", function(){ | ||
should.exist(treeAbc); | ||
should.exist(treeAbcEmpty); | ||
}); | ||
it("should assert non equality in merkle tree roots of ['a', 'b', 'c'] vs ['a', 'b', 'c', '' ]", function(){ | ||
assert.notEqual(treeAbc.root(), treeAbcEmpty.root()); | ||
}); | ||
}); | ||
describe("test already hashed leaves", function(){ | ||
describe("md5", function(){ | ||
var tree = merkle('md5').sync(['064705BD78652C090975702C9E02E229']); | ||
it("should have root '064705BD78652C090975702C9E02E229'", function(){ | ||
assert.equal(tree.root(), "064705BD78652C090975702C9E02E229"); | ||
}); | ||
}); | ||
describe("sha1", function(){ | ||
var tree = merkle('sha1').sync(['EFFDB5F96A28ACD2EB19DCB15D8F43AF762BD0AE']); | ||
it("should have root 'EFFDB5F96A28ACD2EB19DCB15D8F43AF762BD0AE'", function(){ | ||
assert.equal(tree.root(), "EFFDB5F96A28ACD2EB19DCB15D8F43AF762BD0AE"); | ||
}); | ||
}); | ||
describe("sha256", function(){ | ||
var tree = merkle('sha256').sync(['24D166CD6C8B826C779040B49D5B6708D649B236558E8744339DFEE6AFE11999']); | ||
it("should have root '24D166CD6C8B826C779040B49D5B6708D649B236558E8744339DFEE6AFE11999'", function(){ | ||
assert.equal(tree.root(), "24D166CD6C8B826C779040B49D5B6708D649B236558E8744339DFEE6AFE11999"); | ||
}); | ||
}); | ||
describe("sha512", function(){ | ||
var tree = merkle('sha512').sync(['DDEA8EEE5CB0D9F74B29866E3F4558BB2EAF75298D84B04BD074B2ABD103246C1FB0703A118F847F21B975A49FE18E3D284BCAF9728F20D99EB31A4F5468CA3C']); | ||
it("should have root 'DDEA8EEE5CB0D9F74B29866E3F4558BB2EAF75298D84B04BD074B2ABD103246C1FB0703A118F847F21B975A49FE18E3D284BCAF9728F20D99EB31A4F5468CA3C'", function(){ | ||
assert.equal(tree.root(), "DDEA8EEE5CB0D9F74B29866E3F4558BB2EAF75298D84B04BD074B2ABD103246C1FB0703A118F847F21B975A49FE18E3D284BCAF9728F20D99EB31A4F5468CA3C"); | ||
}); | ||
}); | ||
describe("ripemd160", function(){ | ||
var tree = merkle('ripemd160').sync(['7A96FE067027216ECEFBDE8163A3E4BCDAA365FE']); | ||
it("should have root '7A96FE067027216ECEFBDE8163A3E4BCDAA365FE'", function(){ | ||
assert.equal(tree.root(), "7A96FE067027216ECEFBDE8163A3E4BCDAA365FE"); | ||
}); | ||
}); | ||
describe("whirlpool", function(){ | ||
var tree = merkle('whirlpool').sync(['AF85293F325AC3048B93E3170DFF700DB760D988D87317E31C546C2A1DEE5C23EC4F169C8783B34B1F9653707918AF654A9CD5F86CE059770EA8595B22716D73']); | ||
it("should have root 'AF85293F325AC3048B93E3170DFF700DB760D988D87317E31C546C2A1DEE5C23EC4F169C8783B34B1F9653707918AF654A9CD5F86CE059770EA8595B22716D73'", function(){ | ||
assert.equal(tree.root(), "AF85293F325AC3048B93E3170DFF700DB760D988D87317E31C546C2A1DEE5C23EC4F169C8783B34B1F9653707918AF654A9CD5F86CE059770EA8595B22716D73"); | ||
}); | ||
}); | ||
}); |
23430
398
251