formatting changes.
This commit is contained in:
parent
b1e7cde3dd
commit
37e1c8a2ef
167
lib/bcoin/hd.js
167
lib/bcoin/hd.js
@ -68,9 +68,9 @@ var ec = elliptic.curves.secp256k1;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function HDSeed(options) {
|
function HDSeed(options) {
|
||||||
if (!(this instanceof HDSeed)) {
|
if (!(this instanceof HDSeed))
|
||||||
return new HDSeed(options);
|
return new HDSeed(options);
|
||||||
}
|
|
||||||
this.bits = options.bits || 128;
|
this.bits = options.bits || 128;
|
||||||
this.entropy = options.entropy || HDSeed._entropy(this.bits / 8);
|
this.entropy = options.entropy || HDSeed._entropy(this.bits / 8);
|
||||||
this.mnemonic = options.mnemonic || HDSeed._mnemonic(this.entropy);
|
this.mnemonic = options.mnemonic || HDSeed._mnemonic(this.entropy);
|
||||||
@ -131,21 +131,17 @@ var PATH_ROOTS = ['m', 'M', 'm\'', 'M\''];
|
|||||||
function HDPriv(options) {
|
function HDPriv(options) {
|
||||||
var data;
|
var data;
|
||||||
|
|
||||||
if (!(this instanceof HDPriv)) {
|
if (!(this instanceof HDPriv))
|
||||||
return new HDPriv(options);
|
return new HDPriv(options);
|
||||||
}
|
|
||||||
|
|
||||||
if (!options) {
|
if (!options)
|
||||||
options = { seed: new HDSeed({ passphrase: '' }) };
|
options = { seed: new HDSeed({ passphrase: '' }) };
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof options === 'string' && options.indexOf('xprv') === 0) {
|
if (typeof options === 'string' && options.indexOf('xprv') === 0)
|
||||||
options = { xkey: options };
|
options = { xkey: options };
|
||||||
}
|
|
||||||
|
|
||||||
if (options.passphrase) {
|
if (options.passphrase)
|
||||||
options.seed = new HDSeed({ passphrase: options.passphrase });
|
options.seed = new HDSeed({ passphrase: options.passphrase });
|
||||||
}
|
|
||||||
|
|
||||||
if (options.seed) {
|
if (options.seed) {
|
||||||
if (typeof options.seed === 'object' && !(options.seed instanceof HDSeed)) {
|
if (typeof options.seed === 'object' && !(options.seed instanceof HDSeed)) {
|
||||||
@ -168,53 +164,60 @@ function HDPriv(options) {
|
|||||||
|
|
||||||
HDPriv.prototype._normalize = function(data, version) {
|
HDPriv.prototype._normalize = function(data, version) {
|
||||||
var b;
|
var b;
|
||||||
|
|
||||||
data.version = version || VERSION.xprivkey;
|
data.version = version || VERSION.xprivkey;
|
||||||
data.version = +data.version;
|
data.version = +data.version;
|
||||||
|
|
||||||
data.depth = +data.depth;
|
data.depth = +data.depth;
|
||||||
|
|
||||||
if (typeof data.parentFingerPrint === 'number') {
|
if (typeof data.parentFingerPrint === 'number') {
|
||||||
b = [];
|
b = [];
|
||||||
utils.writeU32BE(b, data.parentFingerPrint, 0);
|
utils.writeU32BE(b, data.parentFingerPrint, 0);
|
||||||
data.parentFingerPrint = b;
|
data.parentFingerPrint = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.childIndex = +data.childIndex;
|
data.childIndex = +data.childIndex;
|
||||||
if (typeof data.chainCode === 'string') {
|
|
||||||
|
if (typeof data.chainCode === 'string')
|
||||||
data.chainCode = utils.toArray(data.chainCode, 'hex');
|
data.chainCode = utils.toArray(data.chainCode, 'hex');
|
||||||
}
|
|
||||||
data.privateKey = data.privateKey || data.priv;
|
data.privateKey = data.privateKey || data.priv;
|
||||||
if (data.privateKey) {
|
if (data.privateKey) {
|
||||||
if (data.privateKey.getPrivate) {
|
if (data.privateKey.getPrivate)
|
||||||
data.privateKey = data.privateKey.getPrivate().toArray();
|
data.privateKey = data.privateKey.getPrivate().toArray();
|
||||||
} else if (typeof data.privateKey === 'string') {
|
else if (typeof data.privateKey === 'string')
|
||||||
data.privateKey = utils.toArray(data.privateKey, 'hex');
|
data.privateKey = utils.toArray(data.privateKey, 'hex');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data.publicKey = data.publicKey || data.pub;
|
data.publicKey = data.publicKey || data.pub;
|
||||||
if (data.publicKey) {
|
if (data.publicKey) {
|
||||||
if (data.publicKey.getPublic) {
|
if (data.publicKey.getPublic)
|
||||||
data.publicKey = data.privateKey.getPublic(true, 'array');
|
data.publicKey = data.privateKey.getPublic(true, 'array');
|
||||||
} else if (typeof data.publicKey === 'string') {
|
else if (typeof data.publicKey === 'string')
|
||||||
data.publicKey = utils.toArray(data.publicKey, 'hex');
|
data.publicKey = utils.toArray(data.publicKey, 'hex');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof data.checksum === 'number') {
|
if (typeof data.checksum === 'number') {
|
||||||
b = [];
|
b = [];
|
||||||
utils.writeU32BE(b, data.checksum, 0);
|
utils.writeU32BE(b, data.checksum, 0);
|
||||||
data.checksum = b;
|
data.checksum = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
HDPriv.prototype._seed = function(seed) {
|
HDPriv.prototype._seed = function(seed) {
|
||||||
if (seed instanceof HDSeed) {
|
if (seed instanceof HDSeed)
|
||||||
seed = seed.seed;
|
seed = seed.seed;
|
||||||
}
|
|
||||||
if (typeof seed === 'string' && /^[0-9a-f]+$/i.test(seed)) {
|
if (typeof seed === 'string' && /^[0-9a-f]+$/i.test(seed))
|
||||||
seed = utils.toArray(seed, 'hex');
|
seed = utils.toArray(seed, 'hex');
|
||||||
}
|
|
||||||
if (seed.length < MIN_ENTROPY || seed.length > MAX_ENTROPY) {
|
if (seed.length < MIN_ENTROPY || seed.length > MAX_ENTROPY)
|
||||||
throw new Error;
|
throw new Error('entropy not in range');
|
||||||
}
|
|
||||||
var hash = sha512hmac(seed, 'Bitcoin seed');
|
var hash = sha512hmac(seed, 'Bitcoin seed');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// version: VERSION.xprivkey,
|
// version: VERSION.xprivkey,
|
||||||
depth: 0,
|
depth: 0,
|
||||||
@ -230,6 +233,7 @@ HDPriv.prototype._unbuild = function(xkey) {
|
|||||||
var raw = utils.fromBase58(xkey);
|
var raw = utils.fromBase58(xkey);
|
||||||
var data = {};
|
var data = {};
|
||||||
var off = 0;
|
var off = 0;
|
||||||
|
|
||||||
data.version = utils.readU32BE(raw, off);
|
data.version = utils.readU32BE(raw, off);
|
||||||
off += 4;
|
off += 4;
|
||||||
data.depth = raw[off];
|
data.depth = raw[off];
|
||||||
@ -245,16 +249,18 @@ HDPriv.prototype._unbuild = function(xkey) {
|
|||||||
off += data.privateKey.length;
|
off += data.privateKey.length;
|
||||||
data.checksum = utils.readU32BE(raw, off);
|
data.checksum = utils.readU32BE(raw, off);
|
||||||
off += 4;
|
off += 4;
|
||||||
|
|
||||||
var hash = utils.dsha256(raw.slice(0, -4));
|
var hash = utils.dsha256(raw.slice(0, -4));
|
||||||
if (data.checksum !== utils.readU32BE(hash, 0)) {
|
if (data.checksum !== utils.readU32BE(hash, 0))
|
||||||
throw new Error('checksum mismatch');
|
throw new Error('checksum mismatch');
|
||||||
}
|
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
HDPriv.prototype._build = function(data) {
|
HDPriv.prototype._build = function(data) {
|
||||||
var sequence = [];
|
var sequence = [];
|
||||||
var off = 0;
|
var off = 0;
|
||||||
|
|
||||||
utils.writeU32BE(sequence, data.version, off);
|
utils.writeU32BE(sequence, data.version, off);
|
||||||
off += 4;
|
off += 4;
|
||||||
sequence[off] = data.depth;
|
sequence[off] = data.depth;
|
||||||
@ -300,24 +306,22 @@ HDPriv.prototype._build = function(data) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
HDPriv.prototype.derive = function(index, hard) {
|
HDPriv.prototype.derive = function(index, hard) {
|
||||||
if (typeof index === 'string') {
|
if (typeof index === 'string')
|
||||||
return this.deriveString(index);
|
return this.deriveString(index);
|
||||||
}
|
|
||||||
|
|
||||||
hard = index >= HARDENED ? true : hard;
|
hard = index >= HARDENED ? true : hard;
|
||||||
if (index < HARDENED && hard === true) {
|
if (index < HARDENED && hard === true)
|
||||||
index += HARDENED;
|
index += HARDENED;
|
||||||
}
|
|
||||||
|
|
||||||
var index_ = [];
|
var index_ = [];
|
||||||
utils.writeU32BE(index_, index, 0);
|
utils.writeU32BE(index_, index, 0);
|
||||||
|
|
||||||
var data;
|
var data;
|
||||||
if (hard) {
|
if (hard)
|
||||||
data = [0].concat(this.privateKey).concat(index_);
|
data = [0].concat(this.privateKey).concat(index_);
|
||||||
} else {
|
else
|
||||||
data = [].concat(this.publicKey).concat(index_);
|
data = [].concat(this.publicKey).concat(index_);
|
||||||
}
|
|
||||||
var hash = sha512hmac(data, this.chainCode);
|
var hash = sha512hmac(data, this.chainCode);
|
||||||
var leftPart = new bn(hash.slice(0, 32));
|
var leftPart = new bn(hash.slice(0, 32));
|
||||||
var chainCode = hash.slice(32, 64);
|
var chainCode = hash.slice(32, 64);
|
||||||
@ -327,7 +331,10 @@ HDPriv.prototype.derive = function(index, hard) {
|
|||||||
//var privateKey = leftPart.add(new bn(this.privateKey)).mod(ec.curve.n).toArray();
|
//var privateKey = leftPart.add(new bn(this.privateKey)).mod(ec.curve.n).toArray();
|
||||||
|
|
||||||
// Use this as a workaround:
|
// Use this as a workaround:
|
||||||
var n = new bn('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 'hex');
|
var n = new bn(
|
||||||
|
'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141',
|
||||||
|
'hex'
|
||||||
|
);
|
||||||
var privateKey = leftPart.add(new bn(this.privateKey)).mod(n).toArray();
|
var privateKey = leftPart.add(new bn(this.privateKey)).mod(n).toArray();
|
||||||
|
|
||||||
return new HDPriv({
|
return new HDPriv({
|
||||||
@ -346,27 +353,26 @@ HDPriv._getIndexes = function(path) {
|
|||||||
var root = steps.shift();
|
var root = steps.shift();
|
||||||
var indexes = [];
|
var indexes = [];
|
||||||
|
|
||||||
if (~PATH_ROOTS.indexOf(path)) {
|
if (~PATH_ROOTS.indexOf(path))
|
||||||
return indexes;
|
return indexes;
|
||||||
}
|
|
||||||
|
|
||||||
if (!~PATH_ROOTS.indexOf(root)) {
|
if (!~PATH_ROOTS.indexOf(root))
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < steps.length; i++) {
|
for (var i = 0; i < steps.length; i++) {
|
||||||
var step = steps[i];
|
var step = steps[i];
|
||||||
var hard = step[step.length - 1] === '\'';
|
var hard = step[step.length - 1] === '\'';
|
||||||
if (hard) {
|
|
||||||
|
if (hard)
|
||||||
step = step.slice(0, -1);
|
step = step.slice(0, -1);
|
||||||
}
|
|
||||||
if (!step || step[0] === '-') {
|
if (!step || step[0] === '-')
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
var index = +step;
|
var index = +step;
|
||||||
if (hard) {
|
if (hard)
|
||||||
index += HARDENED;
|
index += HARDENED;
|
||||||
}
|
|
||||||
indexes.push(index);
|
indexes.push(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,9 +396,8 @@ HDPriv.isValidPath = function(path, hard) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
HDPriv.prototype.deriveString = function(path) {
|
HDPriv.prototype.deriveString = function(path) {
|
||||||
if (!HDPriv.isValidPath(path)) {
|
if (!HDPriv.isValidPath(path))
|
||||||
throw new Error('invalid path');
|
throw new Error('invalid path');
|
||||||
}
|
|
||||||
|
|
||||||
var indexes = HDPriv._getIndexes(path);
|
var indexes = HDPriv._getIndexes(path);
|
||||||
|
|
||||||
@ -406,21 +411,18 @@ HDPriv.prototype.deriveString = function(path) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function HDPub(options) {
|
function HDPub(options) {
|
||||||
if (!(this instanceof HDPub)) {
|
if (!(this instanceof HDPub))
|
||||||
return new HDPriv(options);
|
return new HDPriv(options);
|
||||||
}
|
|
||||||
|
|
||||||
var data;
|
var data;
|
||||||
|
|
||||||
if (typeof options === 'string' && options.indexOf('xpub') === 0) {
|
if (typeof options === 'string' && options.indexOf('xpub') === 0)
|
||||||
options = { xkey: options };
|
options = { xkey: options };
|
||||||
}
|
|
||||||
|
|
||||||
if (options.xkey) {
|
if (options.xkey)
|
||||||
data = this._unbuild(options.xkey);
|
data = this._unbuild(options.xkey);
|
||||||
} else {
|
else
|
||||||
data = options;
|
data = options;
|
||||||
}
|
|
||||||
|
|
||||||
data = this._normalize(data, VERSION.xpubkey);
|
data = this._normalize(data, VERSION.xpubkey);
|
||||||
|
|
||||||
@ -435,6 +437,7 @@ HDPub.prototype._unbuild = function(xkey) {
|
|||||||
var raw = utils.fromBase58(xkey);
|
var raw = utils.fromBase58(xkey);
|
||||||
var data = {};
|
var data = {};
|
||||||
var off = 0;
|
var off = 0;
|
||||||
|
|
||||||
data.version = utils.readU32BE(raw, off);
|
data.version = utils.readU32BE(raw, off);
|
||||||
off += 4;
|
off += 4;
|
||||||
data.depth = raw[off];
|
data.depth = raw[off];
|
||||||
@ -449,16 +452,18 @@ HDPub.prototype._unbuild = function(xkey) {
|
|||||||
off += data.publicKey.length;
|
off += data.publicKey.length;
|
||||||
data.checksum = utils.readU32BE(raw, off);
|
data.checksum = utils.readU32BE(raw, off);
|
||||||
off += 4;
|
off += 4;
|
||||||
|
|
||||||
var hash = utils.dsha256(raw.slice(0, -4));
|
var hash = utils.dsha256(raw.slice(0, -4));
|
||||||
if (data.checksum !== utils.readU32BE(hash, 0)) {
|
if (data.checksum !== utils.readU32BE(hash, 0))
|
||||||
throw new Error('checksum mismatch');
|
throw new Error('checksum mismatch');
|
||||||
}
|
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
HDPub.prototype._build = function(data) {
|
HDPub.prototype._build = function(data) {
|
||||||
var sequence = [];
|
var sequence = [];
|
||||||
var off = 0;
|
var off = 0;
|
||||||
|
|
||||||
utils.writeU32BE(sequence, data.version, off);
|
utils.writeU32BE(sequence, data.version, off);
|
||||||
off += 4;
|
off += 4;
|
||||||
sequence[off] = data.depth;
|
sequence[off] = data.depth;
|
||||||
@ -475,11 +480,10 @@ HDPub.prototype._build = function(data) {
|
|||||||
utils.copy(checksum, sequence, off, true);
|
utils.copy(checksum, sequence, off, true);
|
||||||
off += 4;
|
off += 4;
|
||||||
|
|
||||||
if (!data.checksum || !data.checksum.length) {
|
if (!data.checksum || !data.checksum.length)
|
||||||
data.checksum = checksum;
|
data.checksum = checksum;
|
||||||
} else if (utils.toHex(checksum) !== utils.toHex(data.checksum)) {
|
else if (utils.toHex(checksum) !== utils.toHex(data.checksum))
|
||||||
throw new Error;
|
throw new Error('checksum mismatch');
|
||||||
}
|
|
||||||
|
|
||||||
var xpubkey = utils.toBase58(sequence);
|
var xpubkey = utils.toBase58(sequence);
|
||||||
|
|
||||||
@ -503,16 +507,14 @@ HDPub.prototype._build = function(data) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
HDPub.prototype.derive = function(index, hard) {
|
HDPub.prototype.derive = function(index, hard) {
|
||||||
if (typeof index === 'string') {
|
if (typeof index === 'string')
|
||||||
return this.deriveString(index);
|
return this.deriveString(index);
|
||||||
}
|
|
||||||
|
|
||||||
if (index >= HARDENED || hard) {
|
if (index >= HARDENED || hard)
|
||||||
throw new Error;
|
throw new Error('invalid index');
|
||||||
}
|
|
||||||
if (index < 0) {
|
if (index < 0)
|
||||||
throw new Error;
|
throw new Error('invalid path');
|
||||||
}
|
|
||||||
|
|
||||||
var index_ = [];
|
var index_ = [];
|
||||||
utils.writeU32BE(index_, index, 0);
|
utils.writeU32BE(index_, index, 0);
|
||||||
@ -541,18 +543,18 @@ HDPub.isValidPath = function(arg) {
|
|||||||
var indexes = HDPriv._getIndexes(arg);
|
var indexes = HDPriv._getIndexes(arg);
|
||||||
return indexes !== null && indexes.every(HDPub.isValidPath);
|
return indexes !== null && indexes.every(HDPub.isValidPath);
|
||||||
}
|
}
|
||||||
if (typeof arg === 'number') {
|
|
||||||
|
if (typeof arg === 'number')
|
||||||
return arg >= 0 && arg < HARDENED;
|
return arg >= 0 && arg < HARDENED;
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
HDPub.prototype.deriveString = function(path) {
|
HDPub.prototype.deriveString = function(path) {
|
||||||
if (~path.indexOf('\'')) {
|
if (~path.indexOf('\''))
|
||||||
throw new Error('cannot derive hardened');
|
throw new Error('cannot derive hardened');
|
||||||
} else if (!HDPub.isValidPath(path)) {
|
else if (!HDPub.isValidPath(path))
|
||||||
throw new Error('invalid path');
|
throw new Error('invalid path');
|
||||||
}
|
|
||||||
|
|
||||||
var indexes = HDPriv._getIndexes(path);
|
var indexes = HDPriv._getIndexes(path);
|
||||||
|
|
||||||
@ -601,25 +603,20 @@ function pbkdf2(key, salt, iterations, dkLen) {
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var hLen = 64;
|
var hLen = 64;
|
||||||
if (dkLen > (Math.pow(2, 32) - 1) * hLen) {
|
if (dkLen > (Math.pow(2, 32) - 1) * hLen)
|
||||||
throw Error('Requested key length too long');
|
throw Error('Requested key length too long');
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof key !== 'string' && typeof key.length !== 'number') {
|
if (typeof key !== 'string' && typeof key.length !== 'number')
|
||||||
throw new TypeError('key must a string or array');
|
throw new TypeError('key must a string or array');
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof salt !== 'string' && typeof salt.length !== 'number') {
|
if (typeof salt !== 'string' && typeof salt.length !== 'number')
|
||||||
throw new TypeError('salt must a string or array');
|
throw new TypeError('salt must a string or array');
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof key === 'string') {
|
if (typeof key === 'string')
|
||||||
key = utils.toArray(key, null);
|
key = utils.toArray(key, null);
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof salt === 'string') {
|
if (typeof salt === 'string')
|
||||||
salt = utils.toArray(salt, null);
|
salt = utils.toArray(salt, null);
|
||||||
}
|
|
||||||
|
|
||||||
var DK = new Array(dkLen);
|
var DK = new Array(dkLen);
|
||||||
var U = new Array(hLen);
|
var U = new Array(hLen);
|
||||||
@ -630,6 +627,7 @@ function pbkdf2(key, salt, iterations, dkLen) {
|
|||||||
var r = dkLen - (l - 1) * hLen;
|
var r = dkLen - (l - 1) * hLen;
|
||||||
|
|
||||||
utils.copy(salt.slice(0, salt.length), block1, 0);
|
utils.copy(salt.slice(0, salt.length), block1, 0);
|
||||||
|
|
||||||
for (var i = 1; i <= l; i++) {
|
for (var i = 1; i <= l; i++) {
|
||||||
block1[salt.length + 0] = (i >> 24 & 0xff);
|
block1[salt.length + 0] = (i >> 24 & 0xff);
|
||||||
block1[salt.length + 1] = (i >> 16 & 0xff);
|
block1[salt.length + 1] = (i >> 16 & 0xff);
|
||||||
@ -643,9 +641,8 @@ function pbkdf2(key, salt, iterations, dkLen) {
|
|||||||
for (var j = 1; j < iterations; j++) {
|
for (var j = 1; j < iterations; j++) {
|
||||||
U = sha512hmac(U, key);
|
U = sha512hmac(U, key);
|
||||||
|
|
||||||
for (var k = 0; k < hLen; k++) {
|
for (var k = 0; k < hLen; k++)
|
||||||
T[k] ^= U[k];
|
T[k] ^= U[k];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var destPos = (i - 1) * hLen;
|
var destPos = (i - 1) * hLen;
|
||||||
|
|||||||
@ -284,9 +284,8 @@ TX.prototype.scriptOutput = function(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
keys = keys.map(function(key) {
|
keys = keys.map(function(key) {
|
||||||
if (typeof key === 'string') {
|
if (typeof key === 'string')
|
||||||
return utils.toKeyArray(key);
|
return utils.toKeyArray(key);
|
||||||
}
|
|
||||||
return key;
|
return key;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user