keypair refactor.
This commit is contained in:
parent
9b81126ea4
commit
882b18e188
335
lib/bcoin/hd.js
335
lib/bcoin/hd.js
@ -129,6 +129,12 @@ function Mnemonic(options) {
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject properties from options object.
|
||||
* @private
|
||||
* @param {Object} options
|
||||
*/
|
||||
|
||||
Mnemonic.prototype.fromOptions = function fromOptions(options) {
|
||||
if (!options)
|
||||
options = {};
|
||||
@ -147,65 +153,16 @@ Mnemonic.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(this.bits % 32 === 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate mnemonic from options.
|
||||
* @param {Object} options
|
||||
* @returns {Mnemonic}
|
||||
*/
|
||||
|
||||
Mnemonic.fromOptions = function fromOptions(options) {
|
||||
return new Mnemonic().fromOptions(options);
|
||||
};
|
||||
|
||||
Mnemonic.prototype.toJSON = function toJSON() {
|
||||
return {
|
||||
bits: this.bits,
|
||||
entropy: this.entropy ? this.entropy.toString('hex') : null,
|
||||
phrase: this.phrase,
|
||||
passphrase: this.passphrase,
|
||||
language: this.language,
|
||||
seed: this.seed ? this.seed.toString('hex') : null
|
||||
};
|
||||
};
|
||||
|
||||
Mnemonic.prototype.fromJSON = function fromJSON(json) {
|
||||
this.bits = json.bits;
|
||||
if (json.entropy)
|
||||
this.entropy = new Buffer(json.entropy, 'hex');
|
||||
this.phrase = json.phrase;
|
||||
this.passphrase = json.passphrase;
|
||||
this.language = json.language;
|
||||
if (json.seed)
|
||||
this.seed = new Buffer(json.seed, 'hex');
|
||||
return this;
|
||||
};
|
||||
|
||||
Mnemonic.fromJSON = function fromJSON(json) {
|
||||
return new Mnemonic().fromJSON(json);
|
||||
};
|
||||
|
||||
Mnemonic.prototype.toRaw = function toRaw(writer) {
|
||||
var p = new BufferWriter(writer);
|
||||
p.writeU16(this.bits);
|
||||
p.writeBytes(this.entropy);
|
||||
p.writeVarString(this.phrase, 'utf8');
|
||||
p.writeVarString(this.passphrase, 'utf8');
|
||||
p.writeVarString(this.language, 'utf8');
|
||||
p.writeBytes(this.seed);
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
return p;
|
||||
};
|
||||
|
||||
Mnemonic.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = new BufferReader(data);
|
||||
this.bits = p.readU16();
|
||||
this.entropy = p.readBytes(this.bits / 8);
|
||||
this.phrase = p.readVarString('utf8');
|
||||
this.passphrase = p.readVarString('utf8');
|
||||
this.language = p.readVarString('utf8');
|
||||
this.seed = p.readBytes(64);
|
||||
return this;
|
||||
};
|
||||
|
||||
Mnemonic.fromRaw = function fromRaw(data) {
|
||||
return new Mnemonic().fromRaw(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate the seed.
|
||||
* @returns {Buffer} pbkdf2 seed.
|
||||
@ -300,6 +257,96 @@ Mnemonic.getWordlist = function getWordlist(language) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert mnemonic to a json-friendly object.
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
Mnemonic.prototype.toJSON = function toJSON() {
|
||||
return {
|
||||
bits: this.bits,
|
||||
entropy: this.entropy ? this.entropy.toString('hex') : null,
|
||||
phrase: this.phrase,
|
||||
passphrase: this.passphrase,
|
||||
language: this.language,
|
||||
seed: this.seed ? this.seed.toString('hex') : null
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from json object.
|
||||
* @private
|
||||
* @param {Object} json
|
||||
*/
|
||||
|
||||
Mnemonic.prototype.fromJSON = function fromJSON(json) {
|
||||
this.bits = json.bits;
|
||||
this.entropy = new Buffer(json.entropy, 'hex');
|
||||
this.phrase = json.phrase;
|
||||
this.passphrase = json.passphrase;
|
||||
this.language = json.language;
|
||||
this.seed = new Buffer(json.seed, 'hex');
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate mnemonic from json object.
|
||||
* @param {Object} json
|
||||
* @returns {Mnemonic}
|
||||
*/
|
||||
|
||||
Mnemonic.fromJSON = function fromJSON(json) {
|
||||
return new Mnemonic().fromJSON(json);
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize mnemonic.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
Mnemonic.prototype.toRaw = function toRaw(writer) {
|
||||
var p = new BufferWriter(writer);
|
||||
|
||||
p.writeU16(this.bits);
|
||||
p.writeBytes(this.entropy);
|
||||
p.writeVarString(this.phrase, 'utf8');
|
||||
p.writeVarString(this.passphrase, 'utf8');
|
||||
p.writeVarString(this.language, 'utf8');
|
||||
p.writeBytes(this.seed);
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from serialized data.
|
||||
* @private
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
Mnemonic.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = new BufferReader(data);
|
||||
this.bits = p.readU16();
|
||||
this.entropy = p.readBytes(this.bits / 8);
|
||||
this.phrase = p.readVarString('utf8');
|
||||
this.passphrase = p.readVarString('utf8');
|
||||
this.language = p.readVarString('utf8');
|
||||
this.seed = p.readBytes(64);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate mnemonic from serialized data.
|
||||
* @param {Buffer} data
|
||||
* @returns {Mnemonic}
|
||||
*/
|
||||
|
||||
Mnemonic.fromRaw = function fromRaw(data) {
|
||||
return new Mnemonic().fromRaw(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether an object is a Mnemonic.
|
||||
* @param {Object} obj
|
||||
@ -401,6 +448,18 @@ HD.fromRaw = function fromRaw(data) {
|
||||
return HDPublicKey.fromRaw(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate HD key from extended serialized data.
|
||||
* @param {Buffer} data
|
||||
* @returns {HDPrivateKey|HDPublicKey}
|
||||
*/
|
||||
|
||||
HD.fromExtended = function fromExtended(data) {
|
||||
if (HDPrivateKey.hasPrefix(data))
|
||||
return HDPrivateKey.fromExtended(data);
|
||||
return HDPublicKey.fromRaw(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate an hdkey from any number of options.
|
||||
* @param {Object|Mnemonic|Buffer} options - mnemonic, mnemonic
|
||||
@ -571,6 +630,12 @@ function HDPrivateKey(options) {
|
||||
|
||||
utils.inherits(HDPrivateKey, HD);
|
||||
|
||||
/**
|
||||
* Inject properties from options object.
|
||||
* @private
|
||||
* @param {Object} options
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(options, 'No options for HD private key.');
|
||||
assert(options.depth <= 0xff, 'Depth is too high.');
|
||||
@ -590,6 +655,12 @@ HDPrivateKey.prototype.fromOptions = function fromOptions(options) {
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate HD private key from options object.
|
||||
* @param {Object} options
|
||||
* @returns {HDPrivateKey}
|
||||
*/
|
||||
|
||||
HDPrivateKey.fromOptions = function fromOptions(options) {
|
||||
return new HDPrivateKey().fromOptions(options);
|
||||
};
|
||||
@ -846,13 +917,10 @@ HDPrivateKey.prototype.equal = function equal(obj) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an hd private key from a seed.
|
||||
* @param {Buffer|Mnemonic|Object} options - A seed,
|
||||
* mnemonic, or mnemonic options.
|
||||
* @param {String?} network
|
||||
* @returns {Object} A "naked" key (a
|
||||
* plain javascript object which is suitable
|
||||
* for passing to the HDPrivateKey constructor).
|
||||
* Inject properties from seed.
|
||||
* @private
|
||||
* @param {Buffer} seed
|
||||
* @param {(Network|NetworkType)?} network
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.fromSeed = function fromSeed(seed, network) {
|
||||
@ -885,10 +953,9 @@ HDPrivateKey.prototype.fromSeed = function fromSeed(seed, network) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate an hd private key from a seed.
|
||||
* @param {Buffer|Mnemonic|Object} seed - A
|
||||
* seed, mnemonic, or mnemonic options.
|
||||
* @param {String?} network
|
||||
* Instantiate an hd private key from a 512 bit seed.
|
||||
* @param {Buffer} seed
|
||||
* @param {(Network|NetworkType)?} network
|
||||
* @returns {HDPrivateKey}
|
||||
*/
|
||||
|
||||
@ -897,10 +964,10 @@ HDPrivateKey.fromSeed = function fromSeed(seed, network) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate an hd private key from a mnemonic.
|
||||
* Inject properties from a mnemonic.
|
||||
* @private
|
||||
* @param {Mnemonic|Object} mnemonic
|
||||
* @param {String?} network
|
||||
* @returns {HDPrivateKey}
|
||||
* @param {(Network|NetworkType)?} network
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.fromMnemonic = function fromMnemonic(mnemonic, network) {
|
||||
@ -936,19 +1003,22 @@ HDPrivateKey.prototype.fromMnemonic = function fromMnemonic(mnemonic, network) {
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate an hd private key from a mnemonic.
|
||||
* @param {Mnemonic|Object} mnemonic
|
||||
* @param {(Network|NetworkType)?} network
|
||||
* @returns {HDPrivateKey}
|
||||
*/
|
||||
|
||||
HDPrivateKey.fromMnemonic = function fromMnemonic(mnemonic, network) {
|
||||
return new HDPrivateKey().fromMnemonic(mnemonic, network);
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate an hd private key from a key and/or entropy bytes.
|
||||
* @param {Object?} options
|
||||
* @param {Buffer?} options.privateKey
|
||||
* @param {Buffer?} options.entropy
|
||||
* @param {String?} network
|
||||
* @returns {Object} A "naked" key (a
|
||||
* plain javascript object which is suitable
|
||||
* for passing to the HDPrivateKey constructor).
|
||||
* Inject properties from privateKey and entropy.
|
||||
* @private
|
||||
* @param {Object} options
|
||||
* @param {(Network|NetworkType)?} network
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.generate = function _generate(options, network) {
|
||||
@ -985,7 +1055,7 @@ HDPrivateKey.prototype.generate = function _generate(options, network) {
|
||||
* @param {Object?} options
|
||||
* @param {Buffer?} options.privateKey
|
||||
* @param {Buffer?} options.entropy
|
||||
* @param {String?} network
|
||||
* @param {(Network|NetworkType)?} network
|
||||
* @returns {HDPrivateKey}
|
||||
*/
|
||||
|
||||
@ -994,9 +1064,9 @@ HDPrivateKey.generate = function generate(options, network) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse a base58 extended private key.
|
||||
* Inject properties from base58 key.
|
||||
* @private
|
||||
* @param {Base58String} xkey
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.fromBase58 = function fromBase58(xkey) {
|
||||
@ -1006,9 +1076,9 @@ HDPrivateKey.prototype.fromBase58 = function fromBase58(xkey) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse a raw serialized key.
|
||||
* Inject properties from serialized data.
|
||||
* @private
|
||||
* @param {Buffer} raw
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.fromRaw = function fromRaw(raw) {
|
||||
@ -1041,7 +1111,7 @@ HDPrivateKey.prototype.fromRaw = function fromRaw(raw) {
|
||||
|
||||
/**
|
||||
* Serialize key to a base58 string.
|
||||
* @param {Network|String} network
|
||||
* @param {(Network|NetworkType)?} network
|
||||
* @returns {Base58String}
|
||||
*/
|
||||
|
||||
@ -1051,7 +1121,7 @@ HDPrivateKey.prototype.toBase58 = function toBase58(network) {
|
||||
|
||||
/**
|
||||
* Serialize the key.
|
||||
* @param {Network|NetworkType} network
|
||||
* @param {(Network|NetworkType)?} network
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
@ -1079,7 +1149,56 @@ HDPrivateKey.prototype.toRaw = function toRaw(network, writer) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate a transaction from a base58 string.
|
||||
* Serialize the key in "extended"
|
||||
* format (includes the mnemonic).
|
||||
* @param {(Network|NetworkType)?} network
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.toExtended = function toExtended(network, writer) {
|
||||
var p = new BufferWriter(writer);
|
||||
|
||||
this.toRaw(network, p);
|
||||
|
||||
if (this.mnemonic) {
|
||||
p.writeU8(1);
|
||||
this.mnemonic.toRaw(p);
|
||||
} else {
|
||||
p.writeU8(0);
|
||||
}
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from extended serialized data.
|
||||
* @private
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.fromExtended = function fromExtended(data) {
|
||||
var p = new BufferReader(data);
|
||||
this.fromRaw(p);
|
||||
if (p.readU8() === 1)
|
||||
this.mnemonic = Mnemonic.fromRaw(p);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate key from "extended" serialized data.
|
||||
* @param {Buffer} data
|
||||
* @returns {HDPrivateKey}
|
||||
*/
|
||||
|
||||
HDPrivateKey.fromExtended = function fromExtended(data) {
|
||||
return new HDPrivateKey().fromExtended(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate an HD private key from a base58 string.
|
||||
* @param {Base58String} xkey
|
||||
* @returns {HDPrivateKey}
|
||||
*/
|
||||
@ -1111,9 +1230,9 @@ HDPrivateKey.prototype.toJSON = function toJSON() {
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a deserialized JSON HDPrivateKey object.
|
||||
* Inject properties from json object.
|
||||
* @private
|
||||
* @param {Object} json
|
||||
* @returns {Object} A "naked" HDPrivateKey.
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.fromJSON = function fromJSON(json) {
|
||||
@ -1129,7 +1248,7 @@ HDPrivateKey.prototype.fromJSON = function fromJSON(json) {
|
||||
|
||||
/**
|
||||
* Instantiate an HDPrivateKey from a jsonified key object.
|
||||
* @param {Object} json - The jsonified transaction object.
|
||||
* @param {Object} json - The jsonified key object.
|
||||
* @returns {HDPrivateKey}
|
||||
*/
|
||||
|
||||
@ -1145,9 +1264,9 @@ HDPrivateKey.fromJSON = function fromJSON(json) {
|
||||
|
||||
HDPrivateKey.isHDPrivateKey = function isHDPrivateKey(obj) {
|
||||
return obj
|
||||
&& obj.privateKey
|
||||
&& Buffer.isBuffer(obj.chainCode)
|
||||
&& typeof obj.derive === 'function';
|
||||
&& typeof obj.derive === 'function'
|
||||
&& typeof obj.toExtended === 'function'
|
||||
&& obj.chainCode !== undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1195,6 +1314,12 @@ function HDPublicKey(options) {
|
||||
|
||||
utils.inherits(HDPublicKey, HD);
|
||||
|
||||
/**
|
||||
* Inject properties from options object.
|
||||
* @private
|
||||
* @param {Object} options
|
||||
*/
|
||||
|
||||
HDPublicKey.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(options, 'No options for HDPublicKey');
|
||||
assert(options.depth <= 0xff, 'Depth is too high.');
|
||||
@ -1211,6 +1336,12 @@ HDPublicKey.prototype.fromOptions = function fromOptions(options) {
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate HD public key from options object.
|
||||
* @param {Object} options
|
||||
* @returns {HDPublicKey}
|
||||
*/
|
||||
|
||||
HDPublicKey.fromOptions = function fromOptions(options) {
|
||||
return new HDPublicKey().fromOptions(options);
|
||||
};
|
||||
@ -1388,7 +1519,6 @@ HDPublicKey.prototype.equal = function equal(obj) {
|
||||
|
||||
/**
|
||||
* Convert key to a more json-friendly object.
|
||||
* @method
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
@ -1399,9 +1529,9 @@ HDPublicKey.prototype.toJSON = function toJSON() {
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a deserialized JSON HDPublicKey object.
|
||||
* Inject properties from json object.
|
||||
* @private
|
||||
* @param {Object} json
|
||||
* @returns {Object} A "naked" HDPublicKey.
|
||||
*/
|
||||
|
||||
HDPublicKey.prototype.fromJSON = function fromJSON(json) {
|
||||
@ -1412,7 +1542,6 @@ HDPublicKey.prototype.fromJSON = function fromJSON(json) {
|
||||
|
||||
/**
|
||||
* Instantiate an HDPrivateKey from a jsonified key object.
|
||||
* @method
|
||||
* @param {Object} json - The jsonified transaction object.
|
||||
* @returns {HDPrivateKey}
|
||||
*/
|
||||
@ -1468,9 +1597,9 @@ HDPublicKey.hasPrefix = function hasPrefix(data) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse a base58 extended public key.
|
||||
* Inject properties from a base58 key.
|
||||
* @private
|
||||
* @param {Base58String} xkey
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
HDPublicKey.prototype.fromBase58 = function fromBase58(xkey) {
|
||||
@ -1480,9 +1609,9 @@ HDPublicKey.prototype.fromBase58 = function fromBase58(xkey) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse a raw serialized key.
|
||||
* Inject properties from serialized data.
|
||||
* @private
|
||||
* @param {Buffer} raw
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
HDPublicKey.prototype.fromRaw = function fromRaw(raw) {
|
||||
@ -1550,7 +1679,7 @@ HDPublicKey.prototype.toRaw = function toRaw(network, writer) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate a transaction from a base58 string.
|
||||
* Instantiate an HD public key from a base58 string.
|
||||
* @param {Base58String} xkey
|
||||
* @returns {HDPublicKey}
|
||||
*/
|
||||
@ -1577,9 +1706,9 @@ HDPublicKey.fromRaw = function fromRaw(data) {
|
||||
|
||||
HDPublicKey.isHDPublicKey = function isHDPublicKey(obj) {
|
||||
return obj
|
||||
&& !obj.privateKey
|
||||
&& Buffer.isBuffer(obj.chainCode)
|
||||
&& typeof obj.derive === 'function';
|
||||
&& typeof obj.derive === 'function'
|
||||
&& typeof obj.toExtended !== 'function'
|
||||
&& obj.chainCode !== undefined;
|
||||
};
|
||||
|
||||
[HDPrivateKey, HDPublicKey].forEach(function(HD) {
|
||||
|
||||
@ -29,11 +29,25 @@ function KeyPair(options) {
|
||||
if (!(this instanceof KeyPair))
|
||||
return new KeyPair(options);
|
||||
|
||||
this.network = null;
|
||||
this.compressed = true;
|
||||
this.privateKey = null;
|
||||
this._publicKey = null;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject properties from options object.
|
||||
* @private
|
||||
* @param {Object} options
|
||||
*/
|
||||
|
||||
KeyPair.prototype.fromOptions = function fromOptions(options) {
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
this.options = options;
|
||||
this.key = null;
|
||||
this.compressed = options.compressed !== false;
|
||||
this.network = bcoin.network.get(options.network);
|
||||
|
||||
@ -45,15 +59,31 @@ function KeyPair(options) {
|
||||
|
||||
this.privateKey = options.privateKey;
|
||||
this._publicKey = options.publicKey;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a keypair.
|
||||
* Instantiate key pair from options object.
|
||||
* @param {Object} options
|
||||
* @returns {KeyPair}
|
||||
*/
|
||||
|
||||
KeyPair.generate = function() {
|
||||
return new KeyPair({ privateKey: bcoin.ec.generatePrivateKey() });
|
||||
KeyPair.fromOptions = function fromOptions(options) {
|
||||
return new KeyPair().fromOptions(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a keypair.
|
||||
* @param {(Network|NetworkType)?} network
|
||||
* @returns {KeyPair}
|
||||
*/
|
||||
|
||||
KeyPair.generate = function(network) {
|
||||
var key = new KeyPair();
|
||||
key.network = bcoin.network.get(network);
|
||||
key.privateKey = bcoin.ec.generatePrivateKey();
|
||||
return key;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -127,85 +157,105 @@ KeyPair.prototype.getPublicKey = function getPublicKey(enc) {
|
||||
|
||||
/**
|
||||
* Convert key to a CBitcoinSecret.
|
||||
* @returns {Base58String}
|
||||
* @param {(Network|NetworkType)?} network
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
KeyPair.prototype.toSecret = function toSecret(network) {
|
||||
KeyPair.prototype.toRaw = function toRaw(network, writer) {
|
||||
var p = new BufferWriter(writer);
|
||||
|
||||
if (!network)
|
||||
network = this.network;
|
||||
|
||||
return KeyPair.toSecret(this.getPrivateKey(), this.compressed, network);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert key to a CBitcoinSecret.
|
||||
* @param {Buffer} privateKey
|
||||
* @param {Boolean?} compressed
|
||||
* @returns {Base58String}
|
||||
*/
|
||||
|
||||
KeyPair.toSecret = function toSecret(privateKey, compressed, network) {
|
||||
var p = new BufferWriter();
|
||||
|
||||
network = bcoin.network.get(network);
|
||||
p.writeU8(network.prefixes.privkey);
|
||||
p.writeBytes(privateKey);
|
||||
|
||||
if (compressed !== false)
|
||||
p.writeU8(network.prefixes.privkey);
|
||||
p.writeBytes(this.getPrivateKey());
|
||||
|
||||
if (this.compressed)
|
||||
p.writeU8(1);
|
||||
|
||||
p.writeChecksum();
|
||||
|
||||
return utils.toBase58(p.render());
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse a serialized CBitcoinSecret.
|
||||
* @param {Base58String} secret
|
||||
* @returns {Object} A "naked" keypair object.
|
||||
* Convert key to a CBitcoinSecret.
|
||||
* @param {(Network|NetworkType)?} network
|
||||
* @returns {Base58String}
|
||||
*/
|
||||
|
||||
KeyPair.parseSecret = function parseSecret(secret) {
|
||||
var data = utils.fromBase58(secret);
|
||||
KeyPair.prototype.toSecret = function toSecret(network) {
|
||||
return utils.toBase58(this.toRaw(network));
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from serialized CBitcoinSecret.
|
||||
* @private
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
KeyPair.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = new BufferReader(data, true);
|
||||
var compressed = false;
|
||||
var i, prefix, type, privateKey;
|
||||
var i, prefix, version, type, privateKey;
|
||||
|
||||
prefix = p.readU8();
|
||||
version = p.readU8();
|
||||
|
||||
for (i = 0; i < network.types.length; i++) {
|
||||
type = network.types[i];
|
||||
prefix = network[type].prefixes.privkey;
|
||||
if (data.version === prefix)
|
||||
if (version === prefix)
|
||||
break;
|
||||
}
|
||||
|
||||
assert(i < network.types.length, 'Network not found.');
|
||||
|
||||
privateKey = p.readBytes(32);
|
||||
this.network = bcoin.network.get(type);
|
||||
this.privateKey = p.readBytes(32);
|
||||
|
||||
if (p.left() > 4) {
|
||||
assert(p.readU8() === 1, 'Bad compression flag.');
|
||||
compressed = true;
|
||||
this.compressed = true;
|
||||
}
|
||||
|
||||
p.verifyChecksum();
|
||||
|
||||
return {
|
||||
network: type,
|
||||
privateKey: privateKey,
|
||||
compressed: compressed
|
||||
};
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate a transaction from a serialized CBitcoinSecret.
|
||||
* Inject properties from serialized CBitcoinSecret.
|
||||
* @private
|
||||
* @param {Base58String} secret
|
||||
* @returns {Keypair}
|
||||
*/
|
||||
|
||||
KeyPair.prototype.fromSecret = function fromSecret(secret) {
|
||||
return this.fromRaw(utils.fromBase58(secret));
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate a key pair from a serialized CBitcoinSecret.
|
||||
* @param {Buffer} data
|
||||
* @returns {KeyPair}
|
||||
*/
|
||||
|
||||
KeyPair.fromRaw = function fromRaw(data) {
|
||||
return new KeyPair().fromRaw(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate a key pair from a serialized CBitcoinSecret.
|
||||
* @param {Base58String} secret
|
||||
* @returns {KeyPair}
|
||||
*/
|
||||
|
||||
KeyPair.fromSecret = function fromSecret(secret) {
|
||||
return new KeyPair(KeyPair.parseSecret(secret));
|
||||
return new KeyPair().fromSecret(secret);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -214,68 +264,57 @@ KeyPair.fromSecret = function fromSecret(secret) {
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
KeyPair.prototype.toJSON = function toJSON(passphrase) {
|
||||
var json = {
|
||||
v: 1,
|
||||
name: 'keypair',
|
||||
encrypted: passphrase ? true : false
|
||||
KeyPair.prototype.toJSON = function toJSON() {
|
||||
return {
|
||||
network: this.network.type,
|
||||
compressed: this.compressed,
|
||||
privateKey: this.privateKey ? this.toSecret() : null,
|
||||
publicKey: this.getPublicKey('base58')
|
||||
};
|
||||
|
||||
if (this.key.privateKey) {
|
||||
json.privateKey = passphrase
|
||||
? utils.encrypt(this.toSecret(), passphrase).toString('hex')
|
||||
: this.toSecret();
|
||||
return json;
|
||||
}
|
||||
|
||||
json.publicKey = this.getPublicKey('base58');
|
||||
|
||||
return json;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a deserialized JSON keypair object.
|
||||
* Inject properties from json object.
|
||||
* @private
|
||||
* @param {Object} json
|
||||
* @returns {Object} A "naked" keypair (a
|
||||
* plain javascript object which is suitable
|
||||
* for passing to the KeyPair constructor).
|
||||
*/
|
||||
|
||||
KeyPair.parseJSON = function parseJSON(json, passphrase) {
|
||||
var privateKey, publicKey;
|
||||
KeyPair.prototype.fromJSON = function fromJSON(json) {
|
||||
this.network = bcoin.network.get(json.network);
|
||||
this.compressed = json.compressed;
|
||||
|
||||
assert.equal(json.v, 1);
|
||||
assert.equal(json.name, 'keypair');
|
||||
|
||||
if (json.encrypted && !passphrase)
|
||||
throw new Error('Cannot decrypt key.');
|
||||
|
||||
if (json.privateKey) {
|
||||
privateKey = json.privateKey;
|
||||
if (json.encrypted)
|
||||
privateKey = utils.decrypt(privateKey, passphrase).toString('utf8');
|
||||
return KeyPair.parseSecret(privateKey);
|
||||
}
|
||||
if (json.privateKey)
|
||||
return this.fromSecret(json.privateKey);
|
||||
|
||||
if (json.publicKey) {
|
||||
publicKey = utils.fromBase58(json.publicKey);
|
||||
return {
|
||||
publicKey: publicKey,
|
||||
compressed: publicKey[0] !== 0x04
|
||||
};
|
||||
this.publicKey = utils.fromBase58(json.publicKey);
|
||||
this.compressed = this.publicKey[0] !== 0x04;
|
||||
return this;
|
||||
}
|
||||
|
||||
assert(false, 'Could not parse KeyPair JSON.');
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate a transaction from a jsonified keypair object.
|
||||
* @param {Object} json - The jsonified transaction object.
|
||||
* Instantiate a key pair from a jsonified object.
|
||||
* @param {Object} json - The jsonified key pair object.
|
||||
* @returns {KeyPair}
|
||||
*/
|
||||
|
||||
KeyPair.fromJSON = function fromJSON(json, passphrase) {
|
||||
return new KeyPair(KeyPair.parseJSON(json, passphrase));
|
||||
KeyPair.fromJSON = function fromJSON(passphrase) {
|
||||
return new KeyPair().fromJSON(json);
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether an object is a key pair.
|
||||
* @param {Object?} obj
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
KeyPair.isKeyPair = function isKeyPair(obj) {
|
||||
return obj
|
||||
&& obj._privateKey !== undefined
|
||||
&& typeof obj.fromSecret === 'function';
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -597,6 +597,8 @@ KeyRing.prototype.toJSON = function toJSON() {
|
||||
*/
|
||||
|
||||
KeyRing.prototype.fromJSON = function fromJSON(json) {
|
||||
var i;
|
||||
|
||||
this.nework = bcoin.network.get(json.network);
|
||||
this.type = json.type;
|
||||
this.m = json.m;
|
||||
@ -607,7 +609,10 @@ KeyRing.prototype.fromJSON = function fromJSON(json) {
|
||||
this.change = json.change;
|
||||
this.index = json.index;
|
||||
this.key = utils.fromBase58(json.key);
|
||||
this.keys = json.keys.map(utils.fromBase58);
|
||||
|
||||
for (i = 0; i < json.keys.length; i++)
|
||||
this.keys.push(utils.fromBase58(json.keys[i]));
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -671,7 +676,6 @@ KeyRing.prototype.fromRaw = function fromRaw(data) {
|
||||
this.change = p.readU32();
|
||||
this.index = p.readU32();
|
||||
this.key = p.readVarBytes();
|
||||
this.keys = [];
|
||||
|
||||
count = p.readU8();
|
||||
|
||||
|
||||
@ -1402,7 +1402,7 @@ Wallet.prototype.inspect = function inspect() {
|
||||
network: this.network.type,
|
||||
initialized: this.initialized,
|
||||
accountDepth: this.accountDepth,
|
||||
master: this.master.toJSON(),
|
||||
master: this.master,
|
||||
account: this.account
|
||||
};
|
||||
};
|
||||
@ -2192,7 +2192,6 @@ Account.prototype.fromJSON = function fromJSON(json) {
|
||||
this.receiveDepth = json.receiveDepth;
|
||||
this.changeDepth = json.changeDepth;
|
||||
this.accountKey = bcoin.hd.fromBase58(json.accountKey);
|
||||
this.keys = [];
|
||||
|
||||
for (i = 0; i < json.keys.length; i++)
|
||||
this.keys.push(bcoin.hd.fromBase58(key));
|
||||
@ -2255,7 +2254,6 @@ Account.prototype.fromRaw = function fromRaw(data) {
|
||||
this.receiveDepth = p.readU32();
|
||||
this.changeDepth = p.readU32();
|
||||
this.accountKey = bcoin.hd.fromRaw(p.readBytes(82));
|
||||
this.keys = [];
|
||||
|
||||
count = p.readU8();
|
||||
|
||||
@ -2313,12 +2311,10 @@ function MasterKey(options) {
|
||||
return new MasterKey(options);
|
||||
|
||||
this.encrypted = false;
|
||||
this.xprivkey = null;
|
||||
this.phrase = null;
|
||||
this.passphrase = null;
|
||||
this.key = null;
|
||||
this.iv = null;
|
||||
this.ciphertext = null;
|
||||
this.key = null;
|
||||
|
||||
this.timer = null;
|
||||
this._destroy = this.destroy.bind(this);
|
||||
this.locker = new bcoin.locker(this);
|
||||
@ -2332,9 +2328,6 @@ function MasterKey(options) {
|
||||
|
||||
MasterKey.prototype.fromOptions = function fromOptions(options) {
|
||||
this.encrypted = !!options.encrypted;
|
||||
this.xprivkey = options.xprivkey;
|
||||
this.phrase = options.phrase;
|
||||
this.passphrase = options.passphrase;
|
||||
this.iv = options.iv;
|
||||
this.ciphertext = options.ciphertext;
|
||||
this.key = options.key || null;
|
||||
@ -2362,7 +2355,7 @@ MasterKey.fromOptions = function fromOptions(options) {
|
||||
|
||||
MasterKey.prototype.toKey = function toKey(passphrase, timeout, callback) {
|
||||
var self = this;
|
||||
var unlock, data;
|
||||
var unlock;
|
||||
|
||||
unlock = this.locker.lock(toKey, [passphrase, timeout, callback]);
|
||||
|
||||
@ -2384,16 +2377,13 @@ MasterKey.prototype.toKey = function toKey(passphrase, timeout, callback) {
|
||||
return callback(err);
|
||||
|
||||
try {
|
||||
data = MasterKey.fromRaw(data);
|
||||
self.key = bcoin.hd.fromExtended(data);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
self.key = data.key;
|
||||
self.start(timeout);
|
||||
|
||||
data.destroy();
|
||||
|
||||
return callback(null, self.key);
|
||||
});
|
||||
};
|
||||
@ -2481,12 +2471,16 @@ MasterKey.prototype.decrypt = function decrypt(passphrase, callback) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
try {
|
||||
self.key = bcoin.hd.fromExtended(data);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
self.encrypted = false;
|
||||
self.iv = null;
|
||||
self.ciphertext = null;
|
||||
|
||||
self.fromRaw(data);
|
||||
|
||||
return callback();
|
||||
});
|
||||
};
|
||||
@ -2514,7 +2508,8 @@ MasterKey.prototype.encrypt = function encrypt(passphrase, callback) {
|
||||
return callback();
|
||||
|
||||
iv = bcoin.ec.random(16);
|
||||
data = this.toRaw();
|
||||
data = this.key.toExtended();
|
||||
this.stop();
|
||||
|
||||
utils.encrypt(data, passphrase, iv, function(err, data) {
|
||||
if (err)
|
||||
@ -2525,23 +2520,13 @@ MasterKey.prototype.encrypt = function encrypt(passphrase, callback) {
|
||||
self.iv = iv;
|
||||
self.ciphertext = data;
|
||||
|
||||
self.xprivkey.fill(0);
|
||||
self.xprivkey = null;
|
||||
|
||||
if (self.phrase) {
|
||||
self.phrase.fill(0);
|
||||
self.phrase = null;
|
||||
self.passphrase.fill(0);
|
||||
self.passphrase = null;
|
||||
}
|
||||
|
||||
return callback();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize the key in the form of:
|
||||
* `[enc-flag][iv?][ciphertext?][phrase-marker][phrase?][passphrase?][xprivkey]`
|
||||
* `[enc-flag][iv?][ciphertext?][extended-key?]`
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
@ -2560,16 +2545,7 @@ MasterKey.prototype.toRaw = function toRaw(writer) {
|
||||
}
|
||||
|
||||
p.writeU8(0);
|
||||
|
||||
if (this.phrase) {
|
||||
p.writeU8(1);
|
||||
p.writeVarBytes(this.phrase);
|
||||
p.writeVarBytes(this.passphrase);
|
||||
} else {
|
||||
p.writeU8(0);
|
||||
}
|
||||
|
||||
p.writeBytes(this.xprivkey);
|
||||
p.writeVarBytes(this.key.toExtended());
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
@ -2594,13 +2570,7 @@ MasterKey.prototype.fromRaw = function fromRaw(raw) {
|
||||
return this;
|
||||
}
|
||||
|
||||
if (p.readU8() === 1) {
|
||||
this.phrase = p.readVarBytes();
|
||||
this.passphrase = p.readVarBytes();
|
||||
}
|
||||
|
||||
this.xprivkey = p.readBytes(82);
|
||||
this.key = bcoin.hd.fromRaw(this.xprivkey);
|
||||
this.key = bcoin.hd.fromExtended(p.readVarBytes());
|
||||
|
||||
return this;
|
||||
};
|
||||
@ -2624,15 +2594,7 @@ MasterKey.prototype.fromKey = function fromKey(key) {
|
||||
this.encrypted = false;
|
||||
this.iv = null;
|
||||
this.ciphertext = null;
|
||||
|
||||
if (key.mnemonic) {
|
||||
this.phrase = new Buffer(key.mnemonic.phrase, 'utf8');
|
||||
this.passphrase = new Buffer(key.mnemonic.passphrase, 'utf8');
|
||||
}
|
||||
|
||||
this.xprivkey = key.toRaw();
|
||||
this.key = key;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -2652,26 +2614,20 @@ MasterKey.fromKey = function fromKey(key) {
|
||||
*/
|
||||
|
||||
MasterKey.prototype.toJSON = function toJSON() {
|
||||
var phrase, passphrase, xprivkey, iv, ciphertext;
|
||||
var iv, ciphertext, key;
|
||||
|
||||
if (this.encrypted) {
|
||||
iv = this.iv.toString('hex');
|
||||
ciphertext = this.ciphertext.toString('hex');
|
||||
} else {
|
||||
if (this.phrase) {
|
||||
phrase = this.phrase.toString('utf8');
|
||||
passphrase = this.passphrase.toString('utf8');
|
||||
}
|
||||
xprivkey = utils.toBase58(this.xprivkey);
|
||||
key = this.key.toJSON();
|
||||
}
|
||||
|
||||
return {
|
||||
encrypted: this.encrypted,
|
||||
iv: iv,
|
||||
ciphertext: ciphertext,
|
||||
phrase: phrase,
|
||||
passphrase: passphrase,
|
||||
xprivkey: xprivkey
|
||||
key: key
|
||||
};
|
||||
};
|
||||
|
||||
@ -2688,12 +2644,7 @@ MasterKey.prototype.fromJSON = function fromJSON(json) {
|
||||
this.iv = new Buffer(json.iv, 'hex');
|
||||
this.ciphertext = new Buffer(json.ciphertext, 'hex');
|
||||
} else {
|
||||
if (json.phrase) {
|
||||
this.phrase = new Buffer(json.phrase, 'utf8');
|
||||
this.passphrase = new Buffer(json.passphrase, 'utf8');
|
||||
}
|
||||
this.xprivkey = utils.fromBase58(json.xprivkey);
|
||||
this.key = bcoin.hd.fromRaw(this.xprivkey);
|
||||
this.key = bcoin.hd.fromJSON(json.key);
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -2715,7 +2666,10 @@ MasterKey.fromJSON = function fromJSON(json) {
|
||||
*/
|
||||
|
||||
MasterKey.prototype.inspect = function inspect() {
|
||||
return this.toJSON();
|
||||
var json = this.toJSON();
|
||||
if (this.key)
|
||||
json.key = this.key.toJSON();
|
||||
return json;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user