Skip to content

Prevent deriving unserializable keys of depth > 255 #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ export class HDKey {
if (!opt || typeof opt !== 'object') {
throw new Error('HDKey.constructor must not be called directly');
}
if (typeof opt.depth !== 'undefined' && opt.depth >= 256) {
throw new Error('HDKey: opt.depth exceeds the serializable value 255');
}
this.versions = opt.versions || BITCOIN_VERSIONS;
this.depth = opt.depth || 0;
this.chainCode = opt.chainCode || null;
Expand Down
50 changes: 50 additions & 0 deletions test/hdkey.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,56 @@ const fixtures = [
},
];
describe('hdkey', () => {
it('Should throw an error when constructing a key of excesive depth', () => {
const seed = '000102030405060708090a0b0c0d0e0f';
var hdkey = HDKey.fromMasterSeed(hexToBytes(seed));

const optMaxDepth = {
versions: hdkey.versions,
chainCode: hdkey.chainCode,
// The depth is the maximum 255
depth: 255,
parentFingerprint: hdkey.fingerprint,
index: 0,
privateKey: hdkey.privateKey,
};
// no errors
new HDKey(optMaxDepth);

// Craft whatever key, but with excesive depth
const optTooDeep = {
versions: hdkey.versions,
chainCode: hdkey.chainCode,
// The depth is exceeding 255
depth: 256,
parentFingerprint: hdkey.fingerprint,
index: 0,
privateKey: hdkey.privateKey,
};
throws(() => new HDKey(optTooDeep));
});
it('Should throw an error when deriving keys of 256 depth', () => {
const seed = '000102030405060708090a0b0c0d0e0f';
var hdkey = HDKey.fromMasterSeed(hexToBytes(seed));

// deriving 255 children should work
for (let i = 0; i < 255; i++) {
hdkey = hdkey.deriveChild(0);
}
// deriving one more shall throw an error
throws(() => hdkey.deriveChild(0));
});
it('Should throw an error when deriving from path of length 256', () => {
const seed = '000102030405060708090a0b0c0d0e0f';
var hdkey = HDKey.fromMasterSeed(hexToBytes(seed));

// master key "lives" at 0th level, together with 255
// more level its 256, which is still serializable
hdkey.derive('m' + '/0'.repeat(255));
// but deriving one level deeper fails.
throws(() => hdkey.derive('m' + '/0'.repeat(256)));
});

it('Should derive private key correctly', () => {
const seed = 'fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542';
const hdkey = HDKey.fromMasterSeed(hexToBytes(seed));
Expand Down
Loading