diff --git a/src/hdnode.js b/src/hdnode.js index ff97d467b..62cac56e7 100644 --- a/src/hdnode.js +++ b/src/hdnode.js @@ -206,6 +206,8 @@ HDNode.prototype.toBase58 = function (__isPrivate) { // https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#child-key-derivation-ckd-functions HDNode.prototype.derive = function (index) { + typeforce(types.UInt32, index) + var isHardened = index >= HDNode.HIGHEST_BIT var data = new Buffer(37) @@ -277,6 +279,8 @@ HDNode.prototype.derive = function (index) { } HDNode.prototype.deriveHardened = function (index) { + typeforce(types.UInt31, index) + // Only derives hardened private keys by default return this.derive(index + HDNode.HIGHEST_BIT) } diff --git a/src/types.js b/src/types.js index 1a8ca8691..7ddf8c851 100644 --- a/src/types.js +++ b/src/types.js @@ -12,9 +12,13 @@ function Hash256bit (value) { return nBuffer(value, 32) } function Buffer256bit (value) { return nBuffer(value, 32) } var UINT53_MAX = Math.pow(2, 53) - 1 +var UINT31_MAX = Math.pow(2, 31) - 1 function UInt2 (value) { return (value & 3) === value } function UInt8 (value) { return (value & 0xff) === value } function UInt32 (value) { return (value >>> 0) === value } +function UInt31 (value) { + return UInt32(value) && value <= UINT31_MAX +} function UInt53 (value) { return typeforce.Number(value) && value >= 0 && @@ -51,6 +55,7 @@ var types = { Network: Network, UInt2: UInt2, UInt8: UInt8, + UInt31: UInt31, UInt32: UInt32, UInt53: UInt53 } diff --git a/test/hdnode.js b/test/hdnode.js index e8f3184a8..4e9f1cf68 100644 --- a/test/hdnode.js +++ b/test/hdnode.js @@ -327,5 +327,47 @@ describe('HDNode', function () { master.deriveHardened(c.m) }, /Could not derive hardened child key/) }) + + it('throws on negative indexes', function () { + var f = fixtures.valid[0] + var master = HDNode.fromBase58(f.master.base58, NETWORKS_LIST) + + assert.throws(function () { + master.deriveHardened(-1) + }, /Expected UInt31/) + assert.throws(function () { + master.derive(-1) + }, /Expected UInt32/) + }) + + it('throws on high indexes', function () { + var f = fixtures.valid[0] + var master = HDNode.fromBase58(f.master.base58, NETWORKS_LIST) + + assert.throws(function () { + master.deriveHardened(0x80000000) + }, /Expected UInt31/) + assert.throws(function () { + master.derive(0x100000000) + }, /Expected UInt32/) + }) + + it('throws on non-numbers', function () { + var f = fixtures.valid[0] + var master = HDNode.fromBase58(f.master.base58, NETWORKS_LIST) + + assert.throws(function () { + master.deriveHardened() + }, /Expected UInt31/) + assert.throws(function () { + master.derive() + }, /Expected UInt32/) + assert.throws(function () { + master.deriveHardened('foo') + }, /Expected UInt31/) + assert.throws(function () { + master.derive('foo') + }, /Expected UInt32/) + }) }) })