From 0beed6efa4be562474bd382b72af891ab581d401 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Tue, 6 Jan 2015 12:08:42 -0300 Subject: [PATCH] Refactor HDPublicKey path validation --- lib/hdpublickey.js | 40 +++++++++++++++++----------------------- test/hdpublickey.js | 34 +++++++++++++++++++++++++++------- 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/lib/hdpublickey.js b/lib/hdpublickey.js index 979faf965..64da85a9b 100644 --- a/lib/hdpublickey.js +++ b/lib/hdpublickey.js @@ -65,20 +65,23 @@ function HDPublicKey(arg) { } } - /** * Verifies that a given path is valid. * * @param {string|number} arg * @return {boolean} */ -HDPublicKey.prototype.isValidPath = function(arg) { - try { - this.derive(arg); - return true; - } catch (err) { - return false; +HDPublicKey.isValidPath = function(arg) { + if (_.isString(arg)) { + var indexes = HDPrivateKey._getDerivationIndexes(arg); + return indexes !== null && _.all(indexes, HDPublicKey.isValidPath); } + + if (_.isNumber(arg)) { + return arg >= 0 && arg < HDPublicKey.Hardened; + } + + return false; }; /** @@ -149,25 +152,16 @@ HDPublicKey.prototype._deriveFromString = function (path) { /* jshint maxcomplexity: 8 */ if (_.contains(path, "'")) { throw new hdErrors.InvalidIndexCantDeriveHardened(); - } - - var steps = path.split('/'); - - // Special cases: - if (_.contains(HDPublicKey.RootElementAlias, path)) { - return this; - } - if (!_.contains(HDPublicKey.RootElementAlias, steps[0])) { + } else if (!HDPublicKey.isValidPath(path)) { throw new hdErrors.InvalidPath(path); } - steps = steps.slice(1); - var result = this; - for (var step in steps) { - var index = parseInt(steps[step]); - result = result._deriveWithNumber(index); - } - return result; + var indexes = HDPrivateKey._getDerivationIndexes(path); + var derived = indexes.reduce(function(prev, index) { + return prev._deriveWithNumber(index); + }, this); + + return derived; }; /** diff --git a/test/hdpublickey.js b/test/hdpublickey.js index dd73aca7a..f67b1e426 100644 --- a/test/hdpublickey.js +++ b/test/hdpublickey.js @@ -221,20 +221,40 @@ describe('HDPublicKey interface', function() { }); it('validates correct paths', function() { - var publicKey = new HDPublicKey(xpubkey); - var valid = publicKey.isValidPath('m/123/12'); + var valid; + + valid = HDPublicKey.isValidPath('m/123/12'); valid.should.equal(true); - var valid = publicKey.isValidPath(123, true); + valid = HDPublicKey.isValidPath('m'); + valid.should.equal(true); + + valid = HDPublicKey.isValidPath(123); valid.should.equal(true); }); - it('validates illegal paths', function() { - var publicKey = new HDPublicKey(xpubkey); - var valid = publicKey.isValidPath('m/-1/12'); + it('rejects illegal paths', function() { + var valid; + + valid = HDPublicKey.isValidPath('m/-1/12'); valid.should.equal(false); - var valid = publicKey.isValidPath(HDPublicKey.Hardened); + valid = HDPublicKey.isValidPath("m/0'/12"); + valid.should.equal(false); + + valid = HDPublicKey.isValidPath("m/8000000000/12"); + valid.should.equal(false); + + valid = HDPublicKey.isValidPath('bad path'); + valid.should.equal(false); + + valid = HDPublicKey.isValidPath(-1); + valid.should.equal(false); + + valid = HDPublicKey.isValidPath(8000000000); + valid.should.equal(false); + + valid = HDPublicKey.isValidPath(HDPublicKey.Hardened); valid.should.equal(false); });