Merge pull request #1317 from braydonf/hdpubkey-hardened-error

Restore error when trying to derive a hardened path with HDPublicKey.
This commit is contained in:
Patrick Nagurny 2015-08-18 13:59:38 -04:00
commit 095cf32966
3 changed files with 61 additions and 61 deletions

View File

@ -164,6 +164,9 @@ module.exports = [{
}, { }, {
name: 'InvalidPath', name: 'InvalidPath',
message: 'Invalid derivation path, it should look like: "m/1/100", got "{0}"' message: 'Invalid derivation path, it should look like: "m/1/100", got "{0}"'
}, {
name: 'InvalidIndexCantDeriveHardened',
message: 'Invalid argument: creating a hardened path requires an HDPrivateKey'
}, { }, {
name: 'MustSupplyArgument', name: 'MustSupplyArgument',
message: 'Must supply an argument to create a HDPublicKey' message: 'Must supply an argument to create a HDPublicKey'

View File

@ -108,9 +108,9 @@ HDPublicKey.isValidPath = function(arg) {
* *
* @param {string|number} arg * @param {string|number} arg
*/ */
HDPublicKey.prototype.derive = function (arg) { HDPublicKey.prototype.derive = function(arg, hardened) {
if (_.isNumber(arg)) { if (_.isNumber(arg)) {
return this._deriveWithNumber(arg); return this._deriveWithNumber(arg, hardened);
} else if (_.isString(arg)) { } else if (_.isString(arg)) {
return this._deriveFromString(arg); return this._deriveFromString(arg);
} else { } else {
@ -118,8 +118,8 @@ HDPublicKey.prototype.derive = function (arg) {
} }
}; };
HDPublicKey.prototype._deriveWithNumber = function (index) { HDPublicKey.prototype._deriveWithNumber = function(index, hardened) {
if (index >= HDPublicKey.Hardened) { if (index >= HDPublicKey.Hardened || hardened) {
throw new hdErrors.InvalidIndexCantDeriveHardened(); throw new hdErrors.InvalidIndexCantDeriveHardened();
} }
if (index < 0) { if (index < 0) {
@ -150,7 +150,7 @@ HDPublicKey.prototype._deriveWithNumber = function (index) {
return derived; return derived;
}; };
HDPublicKey.prototype._deriveFromString = function (path) { 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();
@ -175,7 +175,7 @@ HDPublicKey.prototype._deriveFromString = function (path) {
* network provided matches the network serialized. * network provided matches the network serialized.
* @return {boolean} * @return {boolean}
*/ */
HDPublicKey.isValidSerialized = function (data, network) { HDPublicKey.isValidSerialized = function(data, network) {
return _.isNull(HDPublicKey.getSerializedError(data, network)); return _.isNull(HDPublicKey.getSerializedError(data, network));
}; };
@ -188,7 +188,7 @@ HDPublicKey.isValidSerialized = function (data, network) {
* network provided matches the network serialized. * network provided matches the network serialized.
* @return {errors|null} * @return {errors|null}
*/ */
HDPublicKey.getSerializedError = function (data, network) { HDPublicKey.getSerializedError = function(data, network) {
/* jshint maxcomplexity: 10 */ /* jshint maxcomplexity: 10 */
/* jshint maxstatements: 20 */ /* jshint maxstatements: 20 */
if (!(_.isString(data) || BufferUtil.isBuffer(data))) { if (!(_.isString(data) || BufferUtil.isBuffer(data))) {
@ -203,7 +203,7 @@ HDPublicKey.getSerializedError = function (data, network) {
return new errors.InvalidB58Checksum(data); return new errors.InvalidB58Checksum(data);
} }
if (data.length !== HDPublicKey.DataSize) { if (data.length !== HDPublicKey.DataSize) {
return new errors.InvalidLength(data); return new hdErrors.InvalidLength(data);
} }
if (!_.isUndefined(network)) { if (!_.isUndefined(network)) {
var error = HDPublicKey._validateNetwork(data, network); var error = HDPublicKey._validateNetwork(data, network);
@ -218,7 +218,7 @@ HDPublicKey.getSerializedError = function (data, network) {
return null; return null;
}; };
HDPublicKey._validateNetwork = function (data, networkArg) { HDPublicKey._validateNetwork = function(data, networkArg) {
var network = Network.get(networkArg); var network = Network.get(networkArg);
if (!network) { if (!network) {
return new errors.InvalidNetworkArgument(networkArg); return new errors.InvalidNetworkArgument(networkArg);
@ -241,7 +241,7 @@ HDPublicKey.prototype._buildFromPrivate = function (arg) {
return this._buildFromBuffers(args); return this._buildFromBuffers(args);
}; };
HDPublicKey.prototype._buildFromObject = function (arg) { HDPublicKey.prototype._buildFromObject = function(arg) {
/* jshint maxcomplexity: 10 */ /* jshint maxcomplexity: 10 */
// TODO: Type validation // TODO: Type validation
var buffers = { var buffers = {
@ -257,7 +257,7 @@ HDPublicKey.prototype._buildFromObject = function (arg) {
return this._buildFromBuffers(buffers); return this._buildFromBuffers(buffers);
}; };
HDPublicKey.prototype._buildFromSerialized = function (arg) { HDPublicKey.prototype._buildFromSerialized = function(arg) {
var decoded = Base58Check.decode(arg); var decoded = Base58Check.decode(arg);
var buffers = { var buffers = {
version: decoded.slice(HDPublicKey.VersionStart, HDPublicKey.VersionEnd), version: decoded.slice(HDPublicKey.VersionStart, HDPublicKey.VersionEnd),
@ -289,7 +289,7 @@ HDPublicKey.prototype._buildFromSerialized = function (arg) {
* representation * representation
* @return {HDPublicKey} this * @return {HDPublicKey} this
*/ */
HDPublicKey.prototype._buildFromBuffers = function (arg) { HDPublicKey.prototype._buildFromBuffers = function(arg) {
/* jshint maxcomplexity: 8 */ /* jshint maxcomplexity: 8 */
/* jshint maxstatements: 20 */ /* jshint maxstatements: 20 */
@ -333,7 +333,7 @@ HDPublicKey.prototype._buildFromBuffers = function (arg) {
return this; return this;
}; };
HDPublicKey._validateBufferArguments = function (arg) { HDPublicKey._validateBufferArguments = function(arg) {
var checkBuffer = function(name, size) { var checkBuffer = function(name, size) {
var buff = arg[name]; var buff = arg[name];
assert(BufferUtil.isBuffer(buff), name + ' argument is not a buffer, it\'s ' + typeof buff); assert(BufferUtil.isBuffer(buff), name + ' argument is not a buffer, it\'s ' + typeof buff);
@ -367,7 +367,7 @@ HDPublicKey.fromObject = function(arg) {
* Returns the base58 checked representation of the public key * Returns the base58 checked representation of the public key
* @return {string} a string starting with "xpub..." in livenet * @return {string} a string starting with "xpub..." in livenet
*/ */
HDPublicKey.prototype.toString = function () { HDPublicKey.prototype.toString = function() {
return this.xpubkey; return this.xpubkey;
}; };

View File

@ -24,31 +24,22 @@ var derived_0_1_200000 = 'xpub6BqyndF6rkBNTV6LXwiY8Pco8aqctqq7tGEUdA8fmGDTnDJphn
describe('HDPublicKey interface', function() { describe('HDPublicKey interface', function() {
var expectFail = function(func, errorType) { var expectFail = function(func, errorType) {
var got = null; (function() {
var error = null;
try {
func(); func();
} catch (e) { }).should.throw(errorType);
error = e;
got = e instanceof errorType;
}
if (!error instanceof errorType) {
console.log('Error', typeof error);
}
// expect(got).to.equal(true);
}; };
var expectDerivationFail = function(argument, error) { var expectDerivationFail = function(argument, error) {
return expectFail(function() { (function() {
var pubkey = new HDPublicKey(xpubkey); var pubkey = new HDPublicKey(xpubkey);
xpubkey.derive(argument); pubkey.derive(argument);
}, error); }).should.throw(error);
}; };
var expectFailBuilding = function(argument, error) { var expectFailBuilding = function(argument, error) {
return expectFail(function() { (function() {
return new HDPublicKey(argument); return new HDPublicKey(argument);
}, error); }).should.throw(error);
}; };
describe('creation formats', function() { describe('creation formats', function() {
@ -225,55 +216,61 @@ describe('HDPublicKey interface', function() {
it('doesn\'t allow other parameters like m\' or M\' or "s"', function() { it('doesn\'t allow other parameters like m\' or M\' or "s"', function() {
/* jshint quotmark: double */ /* jshint quotmark: double */
expectDerivationFail("m'", hdErrors.InvalidDerivationArgument); expectDerivationFail("m'", hdErrors.InvalidIndexCantDeriveHardened);
expectDerivationFail("M'", hdErrors.InvalidDerivationArgument); expectDerivationFail("M'", hdErrors.InvalidIndexCantDeriveHardened);
expectDerivationFail("1", hdErrors.InvalidDerivationArgument); expectDerivationFail("1", hdErrors.InvalidPath);
expectDerivationFail("S", hdErrors.InvalidDerivationArgument); expectDerivationFail("S", hdErrors.InvalidPath);
}); });
it('can\'t derive hardened keys', function() { it('can\'t derive hardened keys', function() {
expectFail(function() { expectFail(function() {
return new HDPublicKey(xpubkey).derive(HDPublicKey.Hardened); return new HDPublicKey(xpubkey).derive(HDPublicKey.Hardened);
}, hdErrors.InvalidDerivationArgument); }, hdErrors.InvalidIndexCantDeriveHardened);
}); });
it('validates correct paths', function() { it('can\'t derive hardened keys via second argument', function() {
var valid; expectFail(function() {
return new HDPublicKey(xpubkey).derive(5, true);
}, hdErrors.InvalidIndexCantDeriveHardened);
});
valid = HDPublicKey.isValidPath('m/123/12'); it('validates correct paths', function() {
valid.should.equal(true); var valid;
valid = HDPublicKey.isValidPath('m'); valid = HDPublicKey.isValidPath('m/123/12');
valid.should.equal(true); valid.should.equal(true);
valid = HDPublicKey.isValidPath(123); valid = HDPublicKey.isValidPath('m');
valid.should.equal(true); valid.should.equal(true);
});
it('rejects illegal paths', function() { valid = HDPublicKey.isValidPath(123);
var valid; valid.should.equal(true);
});
valid = HDPublicKey.isValidPath('m/-1/12'); it('rejects illegal paths', function() {
valid.should.equal(false); var valid;
valid = HDPublicKey.isValidPath("m/0'/12"); valid = HDPublicKey.isValidPath('m/-1/12');
valid.should.equal(false); valid.should.equal(false);
valid = HDPublicKey.isValidPath("m/8000000000/12"); valid = HDPublicKey.isValidPath("m/0'/12");
valid.should.equal(false); valid.should.equal(false);
valid = HDPublicKey.isValidPath('bad path'); valid = HDPublicKey.isValidPath("m/8000000000/12");
valid.should.equal(false); valid.should.equal(false);
valid = HDPublicKey.isValidPath(-1); valid = HDPublicKey.isValidPath('bad path');
valid.should.equal(false); valid.should.equal(false);
valid = HDPublicKey.isValidPath(8000000000); valid = HDPublicKey.isValidPath(-1);
valid.should.equal(false); valid.should.equal(false);
valid = HDPublicKey.isValidPath(HDPublicKey.Hardened); valid = HDPublicKey.isValidPath(8000000000);
valid.should.equal(false); valid.should.equal(false);
});
valid = HDPublicKey.isValidPath(HDPublicKey.Hardened);
valid.should.equal(false);
});
it('should use the cache', function() { it('should use the cache', function() {
var pubkey = new HDPublicKey(xpubkey); var pubkey = new HDPublicKey(xpubkey);