Refactor HDPublicKey path validation

This commit is contained in:
Yemel Jardi 2015-01-06 12:08:42 -03:00
parent f78ebeb46c
commit 0beed6efa4
2 changed files with 44 additions and 30 deletions

View File

@ -65,20 +65,23 @@ function HDPublicKey(arg) {
} }
} }
/** /**
* Verifies that a given path is valid. * Verifies that a given path is valid.
* *
* @param {string|number} arg * @param {string|number} arg
* @return {boolean} * @return {boolean}
*/ */
HDPublicKey.prototype.isValidPath = function(arg) { HDPublicKey.isValidPath = function(arg) {
try { if (_.isString(arg)) {
this.derive(arg); var indexes = HDPrivateKey._getDerivationIndexes(arg);
return true; return indexes !== null && _.all(indexes, HDPublicKey.isValidPath);
} catch (err) {
return false;
} }
if (_.isNumber(arg)) {
return arg >= 0 && arg < HDPublicKey.Hardened;
}
return false;
}; };
/** /**
@ -149,25 +152,16 @@ HDPublicKey.prototype._deriveFromString = function (path) {
/* jshint maxcomplexity: 8 */ /* jshint maxcomplexity: 8 */
if (_.contains(path, "'")) { if (_.contains(path, "'")) {
throw new hdErrors.InvalidIndexCantDeriveHardened(); throw new hdErrors.InvalidIndexCantDeriveHardened();
} } else if (!HDPublicKey.isValidPath(path)) {
var steps = path.split('/');
// Special cases:
if (_.contains(HDPublicKey.RootElementAlias, path)) {
return this;
}
if (!_.contains(HDPublicKey.RootElementAlias, steps[0])) {
throw new hdErrors.InvalidPath(path); throw new hdErrors.InvalidPath(path);
} }
steps = steps.slice(1);
var result = this; var indexes = HDPrivateKey._getDerivationIndexes(path);
for (var step in steps) { var derived = indexes.reduce(function(prev, index) {
var index = parseInt(steps[step]); return prev._deriveWithNumber(index);
result = result._deriveWithNumber(index); }, this);
}
return result; return derived;
}; };
/** /**

View File

@ -221,20 +221,40 @@ describe('HDPublicKey interface', function() {
}); });
it('validates correct paths', function() { it('validates correct paths', function() {
var publicKey = new HDPublicKey(xpubkey); var valid;
var valid = publicKey.isValidPath('m/123/12');
valid = HDPublicKey.isValidPath('m/123/12');
valid.should.equal(true); 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); valid.should.equal(true);
}); });
it('validates illegal paths', function() { it('rejects illegal paths', function() {
var publicKey = new HDPublicKey(xpubkey); var valid;
var valid = publicKey.isValidPath('m/-1/12');
valid = HDPublicKey.isValidPath('m/-1/12');
valid.should.equal(false); 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); valid.should.equal(false);
}); });