keypair refactor.

This commit is contained in:
Christopher Jeffrey 2016-06-25 04:42:42 -07:00
parent 9b81126ea4
commit 882b18e188
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
4 changed files with 387 additions and 261 deletions

View File

@ -129,6 +129,12 @@ function Mnemonic(options) {
this.fromOptions(options); this.fromOptions(options);
} }
/**
* Inject properties from options object.
* @private
* @param {Object} options
*/
Mnemonic.prototype.fromOptions = function fromOptions(options) { Mnemonic.prototype.fromOptions = function fromOptions(options) {
if (!options) if (!options)
options = {}; options = {};
@ -147,65 +153,16 @@ Mnemonic.prototype.fromOptions = function fromOptions(options) {
assert(this.bits % 32 === 0); assert(this.bits % 32 === 0);
}; };
/**
* Instantiate mnemonic from options.
* @param {Object} options
* @returns {Mnemonic}
*/
Mnemonic.fromOptions = function fromOptions(options) { Mnemonic.fromOptions = function fromOptions(options) {
return new Mnemonic().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. * Generate the seed.
* @returns {Buffer} pbkdf2 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. * Test whether an object is a Mnemonic.
* @param {Object} obj * @param {Object} obj
@ -401,6 +448,18 @@ HD.fromRaw = function fromRaw(data) {
return HDPublicKey.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. * Generate an hdkey from any number of options.
* @param {Object|Mnemonic|Buffer} options - mnemonic, mnemonic * @param {Object|Mnemonic|Buffer} options - mnemonic, mnemonic
@ -571,6 +630,12 @@ function HDPrivateKey(options) {
utils.inherits(HDPrivateKey, HD); utils.inherits(HDPrivateKey, HD);
/**
* Inject properties from options object.
* @private
* @param {Object} options
*/
HDPrivateKey.prototype.fromOptions = function fromOptions(options) { HDPrivateKey.prototype.fromOptions = function fromOptions(options) {
assert(options, 'No options for HD private key.'); assert(options, 'No options for HD private key.');
assert(options.depth <= 0xff, 'Depth is too high.'); assert(options.depth <= 0xff, 'Depth is too high.');
@ -590,6 +655,12 @@ HDPrivateKey.prototype.fromOptions = function fromOptions(options) {
return this; return this;
}; };
/**
* Instantiate HD private key from options object.
* @param {Object} options
* @returns {HDPrivateKey}
*/
HDPrivateKey.fromOptions = function fromOptions(options) { HDPrivateKey.fromOptions = function fromOptions(options) {
return new HDPrivateKey().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. * Inject properties from seed.
* @param {Buffer|Mnemonic|Object} options - A seed, * @private
* mnemonic, or mnemonic options. * @param {Buffer} seed
* @param {String?} network * @param {(Network|NetworkType)?} network
* @returns {Object} A "naked" key (a
* plain javascript object which is suitable
* for passing to the HDPrivateKey constructor).
*/ */
HDPrivateKey.prototype.fromSeed = function fromSeed(seed, 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. * Instantiate an hd private key from a 512 bit seed.
* @param {Buffer|Mnemonic|Object} seed - A * @param {Buffer} seed
* seed, mnemonic, or mnemonic options. * @param {(Network|NetworkType)?} network
* @param {String?} network
* @returns {HDPrivateKey} * @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 {Mnemonic|Object} mnemonic
* @param {String?} network * @param {(Network|NetworkType)?} network
* @returns {HDPrivateKey}
*/ */
HDPrivateKey.prototype.fromMnemonic = function fromMnemonic(mnemonic, network) { HDPrivateKey.prototype.fromMnemonic = function fromMnemonic(mnemonic, network) {
@ -936,19 +1003,22 @@ HDPrivateKey.prototype.fromMnemonic = function fromMnemonic(mnemonic, network) {
return this; 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) { HDPrivateKey.fromMnemonic = function fromMnemonic(mnemonic, network) {
return new HDPrivateKey().fromMnemonic(mnemonic, network); return new HDPrivateKey().fromMnemonic(mnemonic, network);
}; };
/** /**
* Generate an hd private key from a key and/or entropy bytes. * Inject properties from privateKey and entropy.
* @param {Object?} options * @private
* @param {Buffer?} options.privateKey * @param {Object} options
* @param {Buffer?} options.entropy * @param {(Network|NetworkType)?} network
* @param {String?} network
* @returns {Object} A "naked" key (a
* plain javascript object which is suitable
* for passing to the HDPrivateKey constructor).
*/ */
HDPrivateKey.prototype.generate = function _generate(options, network) { HDPrivateKey.prototype.generate = function _generate(options, network) {
@ -985,7 +1055,7 @@ HDPrivateKey.prototype.generate = function _generate(options, network) {
* @param {Object?} options * @param {Object?} options
* @param {Buffer?} options.privateKey * @param {Buffer?} options.privateKey
* @param {Buffer?} options.entropy * @param {Buffer?} options.entropy
* @param {String?} network * @param {(Network|NetworkType)?} network
* @returns {HDPrivateKey} * @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 * @param {Base58String} xkey
* @returns {Object}
*/ */
HDPrivateKey.prototype.fromBase58 = function fromBase58(xkey) { 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 * @param {Buffer} raw
* @returns {Object}
*/ */
HDPrivateKey.prototype.fromRaw = function fromRaw(raw) { HDPrivateKey.prototype.fromRaw = function fromRaw(raw) {
@ -1041,7 +1111,7 @@ HDPrivateKey.prototype.fromRaw = function fromRaw(raw) {
/** /**
* Serialize key to a base58 string. * Serialize key to a base58 string.
* @param {Network|String} network * @param {(Network|NetworkType)?} network
* @returns {Base58String} * @returns {Base58String}
*/ */
@ -1051,7 +1121,7 @@ HDPrivateKey.prototype.toBase58 = function toBase58(network) {
/** /**
* Serialize the key. * Serialize the key.
* @param {Network|NetworkType} network * @param {(Network|NetworkType)?} network
* @returns {Buffer} * @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 * @param {Base58String} xkey
* @returns {HDPrivateKey} * @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 * @param {Object} json
* @returns {Object} A "naked" HDPrivateKey.
*/ */
HDPrivateKey.prototype.fromJSON = function fromJSON(json) { HDPrivateKey.prototype.fromJSON = function fromJSON(json) {
@ -1129,7 +1248,7 @@ HDPrivateKey.prototype.fromJSON = function fromJSON(json) {
/** /**
* Instantiate an HDPrivateKey from a jsonified key object. * Instantiate an HDPrivateKey from a jsonified key object.
* @param {Object} json - The jsonified transaction object. * @param {Object} json - The jsonified key object.
* @returns {HDPrivateKey} * @returns {HDPrivateKey}
*/ */
@ -1145,9 +1264,9 @@ HDPrivateKey.fromJSON = function fromJSON(json) {
HDPrivateKey.isHDPrivateKey = function isHDPrivateKey(obj) { HDPrivateKey.isHDPrivateKey = function isHDPrivateKey(obj) {
return obj return obj
&& obj.privateKey && typeof obj.derive === 'function'
&& Buffer.isBuffer(obj.chainCode) && typeof obj.toExtended === 'function'
&& typeof obj.derive === 'function'; && obj.chainCode !== undefined;
}; };
/** /**
@ -1195,6 +1314,12 @@ function HDPublicKey(options) {
utils.inherits(HDPublicKey, HD); utils.inherits(HDPublicKey, HD);
/**
* Inject properties from options object.
* @private
* @param {Object} options
*/
HDPublicKey.prototype.fromOptions = function fromOptions(options) { HDPublicKey.prototype.fromOptions = function fromOptions(options) {
assert(options, 'No options for HDPublicKey'); assert(options, 'No options for HDPublicKey');
assert(options.depth <= 0xff, 'Depth is too high.'); assert(options.depth <= 0xff, 'Depth is too high.');
@ -1211,6 +1336,12 @@ HDPublicKey.prototype.fromOptions = function fromOptions(options) {
return this; return this;
}; };
/**
* Instantiate HD public key from options object.
* @param {Object} options
* @returns {HDPublicKey}
*/
HDPublicKey.fromOptions = function fromOptions(options) { HDPublicKey.fromOptions = function fromOptions(options) {
return new HDPublicKey().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. * Convert key to a more json-friendly object.
* @method
* @returns {Object} * @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 * @param {Object} json
* @returns {Object} A "naked" HDPublicKey.
*/ */
HDPublicKey.prototype.fromJSON = function fromJSON(json) { HDPublicKey.prototype.fromJSON = function fromJSON(json) {
@ -1412,7 +1542,6 @@ HDPublicKey.prototype.fromJSON = function fromJSON(json) {
/** /**
* Instantiate an HDPrivateKey from a jsonified key object. * Instantiate an HDPrivateKey from a jsonified key object.
* @method
* @param {Object} json - The jsonified transaction object. * @param {Object} json - The jsonified transaction object.
* @returns {HDPrivateKey} * @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 * @param {Base58String} xkey
* @returns {Object}
*/ */
HDPublicKey.prototype.fromBase58 = function fromBase58(xkey) { 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 * @param {Buffer} raw
* @returns {Object}
*/ */
HDPublicKey.prototype.fromRaw = function fromRaw(raw) { 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 * @param {Base58String} xkey
* @returns {HDPublicKey} * @returns {HDPublicKey}
*/ */
@ -1577,9 +1706,9 @@ HDPublicKey.fromRaw = function fromRaw(data) {
HDPublicKey.isHDPublicKey = function isHDPublicKey(obj) { HDPublicKey.isHDPublicKey = function isHDPublicKey(obj) {
return obj return obj
&& !obj.privateKey && typeof obj.derive === 'function'
&& Buffer.isBuffer(obj.chainCode) && typeof obj.toExtended !== 'function'
&& typeof obj.derive === 'function'; && obj.chainCode !== undefined;
}; };
[HDPrivateKey, HDPublicKey].forEach(function(HD) { [HDPrivateKey, HDPublicKey].forEach(function(HD) {

View File

@ -29,11 +29,25 @@ function KeyPair(options) {
if (!(this instanceof KeyPair)) if (!(this instanceof KeyPair))
return new KeyPair(options); 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) if (!options)
options = {}; options = {};
this.options = options;
this.key = null;
this.compressed = options.compressed !== false; this.compressed = options.compressed !== false;
this.network = bcoin.network.get(options.network); this.network = bcoin.network.get(options.network);
@ -45,15 +59,31 @@ function KeyPair(options) {
this.privateKey = options.privateKey; this.privateKey = options.privateKey;
this._publicKey = options.publicKey; this._publicKey = options.publicKey;
}
return this;
};
/** /**
* Generate a keypair. * Instantiate key pair from options object.
* @param {Object} options
* @returns {KeyPair} * @returns {KeyPair}
*/ */
KeyPair.generate = function() { KeyPair.fromOptions = function fromOptions(options) {
return new KeyPair({ privateKey: bcoin.ec.generatePrivateKey() }); 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. * 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) if (!network)
network = this.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); 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.writeU8(1);
p.writeChecksum(); p.writeChecksum();
return utils.toBase58(p.render()); if (!writer)
p = p.render();
return p;
}; };
/** /**
* Parse a serialized CBitcoinSecret. * Convert key to a CBitcoinSecret.
* @param {Base58String} secret * @param {(Network|NetworkType)?} network
* @returns {Object} A "naked" keypair object. * @returns {Base58String}
*/ */
KeyPair.parseSecret = function parseSecret(secret) { KeyPair.prototype.toSecret = function toSecret(network) {
var data = utils.fromBase58(secret); 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 p = new BufferReader(data, true);
var compressed = false; 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++) { for (i = 0; i < network.types.length; i++) {
type = network.types[i]; type = network.types[i];
prefix = network[type].prefixes.privkey; prefix = network[type].prefixes.privkey;
if (data.version === prefix) if (version === prefix)
break; break;
} }
assert(i < network.types.length, 'Network not found.'); 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) { if (p.left() > 4) {
assert(p.readU8() === 1, 'Bad compression flag.'); assert(p.readU8() === 1, 'Bad compression flag.');
compressed = true; this.compressed = true;
} }
p.verifyChecksum(); p.verifyChecksum();
return { return this;
network: type,
privateKey: privateKey,
compressed: compressed
};
}; };
/** /**
* Instantiate a transaction from a serialized CBitcoinSecret. * Inject properties from serialized CBitcoinSecret.
* @private
* @param {Base58String} secret * @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) { 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} * @returns {Object}
*/ */
KeyPair.prototype.toJSON = function toJSON(passphrase) { KeyPair.prototype.toJSON = function toJSON() {
var json = { return {
v: 1, network: this.network.type,
name: 'keypair', compressed: this.compressed,
encrypted: passphrase ? true : false 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 * @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) { KeyPair.prototype.fromJSON = function fromJSON(json) {
var privateKey, publicKey; this.network = bcoin.network.get(json.network);
this.compressed = json.compressed;
assert.equal(json.v, 1); if (json.privateKey)
assert.equal(json.name, 'keypair'); return this.fromSecret(json.privateKey);
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.publicKey) { if (json.publicKey) {
publicKey = utils.fromBase58(json.publicKey); this.publicKey = utils.fromBase58(json.publicKey);
return { this.compressed = this.publicKey[0] !== 0x04;
publicKey: publicKey, return this;
compressed: publicKey[0] !== 0x04
};
} }
assert(false, 'Could not parse KeyPair JSON.'); assert(false, 'Could not parse KeyPair JSON.');
}; };
/** /**
* Instantiate a transaction from a jsonified keypair object. * Instantiate a key pair from a jsonified object.
* @param {Object} json - The jsonified transaction object. * @param {Object} json - The jsonified key pair object.
* @returns {KeyPair} * @returns {KeyPair}
*/ */
KeyPair.fromJSON = function fromJSON(json, passphrase) { KeyPair.fromJSON = function fromJSON(passphrase) {
return new KeyPair(KeyPair.parseJSON(json, 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';
}; };
/* /*

View File

@ -597,6 +597,8 @@ KeyRing.prototype.toJSON = function toJSON() {
*/ */
KeyRing.prototype.fromJSON = function fromJSON(json) { KeyRing.prototype.fromJSON = function fromJSON(json) {
var i;
this.nework = bcoin.network.get(json.network); this.nework = bcoin.network.get(json.network);
this.type = json.type; this.type = json.type;
this.m = json.m; this.m = json.m;
@ -607,7 +609,10 @@ KeyRing.prototype.fromJSON = function fromJSON(json) {
this.change = json.change; this.change = json.change;
this.index = json.index; this.index = json.index;
this.key = utils.fromBase58(json.key); 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; return this;
}; };
@ -671,7 +676,6 @@ KeyRing.prototype.fromRaw = function fromRaw(data) {
this.change = p.readU32(); this.change = p.readU32();
this.index = p.readU32(); this.index = p.readU32();
this.key = p.readVarBytes(); this.key = p.readVarBytes();
this.keys = [];
count = p.readU8(); count = p.readU8();

View File

@ -1402,7 +1402,7 @@ Wallet.prototype.inspect = function inspect() {
network: this.network.type, network: this.network.type,
initialized: this.initialized, initialized: this.initialized,
accountDepth: this.accountDepth, accountDepth: this.accountDepth,
master: this.master.toJSON(), master: this.master,
account: this.account account: this.account
}; };
}; };
@ -2192,7 +2192,6 @@ Account.prototype.fromJSON = function fromJSON(json) {
this.receiveDepth = json.receiveDepth; this.receiveDepth = json.receiveDepth;
this.changeDepth = json.changeDepth; this.changeDepth = json.changeDepth;
this.accountKey = bcoin.hd.fromBase58(json.accountKey); this.accountKey = bcoin.hd.fromBase58(json.accountKey);
this.keys = [];
for (i = 0; i < json.keys.length; i++) for (i = 0; i < json.keys.length; i++)
this.keys.push(bcoin.hd.fromBase58(key)); this.keys.push(bcoin.hd.fromBase58(key));
@ -2255,7 +2254,6 @@ Account.prototype.fromRaw = function fromRaw(data) {
this.receiveDepth = p.readU32(); this.receiveDepth = p.readU32();
this.changeDepth = p.readU32(); this.changeDepth = p.readU32();
this.accountKey = bcoin.hd.fromRaw(p.readBytes(82)); this.accountKey = bcoin.hd.fromRaw(p.readBytes(82));
this.keys = [];
count = p.readU8(); count = p.readU8();
@ -2313,12 +2311,10 @@ function MasterKey(options) {
return new MasterKey(options); return new MasterKey(options);
this.encrypted = false; this.encrypted = false;
this.xprivkey = null;
this.phrase = null;
this.passphrase = null;
this.key = null;
this.iv = null; this.iv = null;
this.ciphertext = null; this.ciphertext = null;
this.key = null;
this.timer = null; this.timer = null;
this._destroy = this.destroy.bind(this); this._destroy = this.destroy.bind(this);
this.locker = new bcoin.locker(this); this.locker = new bcoin.locker(this);
@ -2332,9 +2328,6 @@ function MasterKey(options) {
MasterKey.prototype.fromOptions = function fromOptions(options) { MasterKey.prototype.fromOptions = function fromOptions(options) {
this.encrypted = !!options.encrypted; this.encrypted = !!options.encrypted;
this.xprivkey = options.xprivkey;
this.phrase = options.phrase;
this.passphrase = options.passphrase;
this.iv = options.iv; this.iv = options.iv;
this.ciphertext = options.ciphertext; this.ciphertext = options.ciphertext;
this.key = options.key || null; this.key = options.key || null;
@ -2362,7 +2355,7 @@ MasterKey.fromOptions = function fromOptions(options) {
MasterKey.prototype.toKey = function toKey(passphrase, timeout, callback) { MasterKey.prototype.toKey = function toKey(passphrase, timeout, callback) {
var self = this; var self = this;
var unlock, data; var unlock;
unlock = this.locker.lock(toKey, [passphrase, timeout, callback]); unlock = this.locker.lock(toKey, [passphrase, timeout, callback]);
@ -2384,16 +2377,13 @@ MasterKey.prototype.toKey = function toKey(passphrase, timeout, callback) {
return callback(err); return callback(err);
try { try {
data = MasterKey.fromRaw(data); self.key = bcoin.hd.fromExtended(data);
} catch (e) { } catch (e) {
return callback(e); return callback(e);
} }
self.key = data.key;
self.start(timeout); self.start(timeout);
data.destroy();
return callback(null, self.key); return callback(null, self.key);
}); });
}; };
@ -2481,12 +2471,16 @@ MasterKey.prototype.decrypt = function decrypt(passphrase, callback) {
if (err) if (err)
return callback(err); return callback(err);
try {
self.key = bcoin.hd.fromExtended(data);
} catch (e) {
return callback(e);
}
self.encrypted = false; self.encrypted = false;
self.iv = null; self.iv = null;
self.ciphertext = null; self.ciphertext = null;
self.fromRaw(data);
return callback(); return callback();
}); });
}; };
@ -2514,7 +2508,8 @@ MasterKey.prototype.encrypt = function encrypt(passphrase, callback) {
return callback(); return callback();
iv = bcoin.ec.random(16); iv = bcoin.ec.random(16);
data = this.toRaw(); data = this.key.toExtended();
this.stop();
utils.encrypt(data, passphrase, iv, function(err, data) { utils.encrypt(data, passphrase, iv, function(err, data) {
if (err) if (err)
@ -2525,23 +2520,13 @@ MasterKey.prototype.encrypt = function encrypt(passphrase, callback) {
self.iv = iv; self.iv = iv;
self.ciphertext = data; 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(); return callback();
}); });
}; };
/** /**
* Serialize the key in the form of: * Serialize the key in the form of:
* `[enc-flag][iv?][ciphertext?][phrase-marker][phrase?][passphrase?][xprivkey]` * `[enc-flag][iv?][ciphertext?][extended-key?]`
* @returns {Buffer} * @returns {Buffer}
*/ */
@ -2560,16 +2545,7 @@ MasterKey.prototype.toRaw = function toRaw(writer) {
} }
p.writeU8(0); p.writeU8(0);
p.writeVarBytes(this.key.toExtended());
if (this.phrase) {
p.writeU8(1);
p.writeVarBytes(this.phrase);
p.writeVarBytes(this.passphrase);
} else {
p.writeU8(0);
}
p.writeBytes(this.xprivkey);
if (!writer) if (!writer)
p = p.render(); p = p.render();
@ -2594,13 +2570,7 @@ MasterKey.prototype.fromRaw = function fromRaw(raw) {
return this; return this;
} }
if (p.readU8() === 1) { this.key = bcoin.hd.fromExtended(p.readVarBytes());
this.phrase = p.readVarBytes();
this.passphrase = p.readVarBytes();
}
this.xprivkey = p.readBytes(82);
this.key = bcoin.hd.fromRaw(this.xprivkey);
return this; return this;
}; };
@ -2624,15 +2594,7 @@ MasterKey.prototype.fromKey = function fromKey(key) {
this.encrypted = false; this.encrypted = false;
this.iv = null; this.iv = null;
this.ciphertext = 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; this.key = key;
return this; return this;
}; };
@ -2652,26 +2614,20 @@ MasterKey.fromKey = function fromKey(key) {
*/ */
MasterKey.prototype.toJSON = function toJSON() { MasterKey.prototype.toJSON = function toJSON() {
var phrase, passphrase, xprivkey, iv, ciphertext; var iv, ciphertext, key;
if (this.encrypted) { if (this.encrypted) {
iv = this.iv.toString('hex'); iv = this.iv.toString('hex');
ciphertext = this.ciphertext.toString('hex'); ciphertext = this.ciphertext.toString('hex');
} else { } else {
if (this.phrase) { key = this.key.toJSON();
phrase = this.phrase.toString('utf8');
passphrase = this.passphrase.toString('utf8');
}
xprivkey = utils.toBase58(this.xprivkey);
} }
return { return {
encrypted: this.encrypted, encrypted: this.encrypted,
iv: iv, iv: iv,
ciphertext: ciphertext, ciphertext: ciphertext,
phrase: phrase, key: key
passphrase: passphrase,
xprivkey: xprivkey
}; };
}; };
@ -2688,12 +2644,7 @@ MasterKey.prototype.fromJSON = function fromJSON(json) {
this.iv = new Buffer(json.iv, 'hex'); this.iv = new Buffer(json.iv, 'hex');
this.ciphertext = new Buffer(json.ciphertext, 'hex'); this.ciphertext = new Buffer(json.ciphertext, 'hex');
} else { } else {
if (json.phrase) { this.key = bcoin.hd.fromJSON(json.key);
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);
} }
return this; return this;
@ -2715,7 +2666,10 @@ MasterKey.fromJSON = function fromJSON(json) {
*/ */
MasterKey.prototype.inspect = function inspect() { MasterKey.prototype.inspect = function inspect() {
return this.toJSON(); var json = this.toJSON();
if (this.key)
json.key = this.key.toJSON();
return json;
}; };
/** /**