diff --git a/lib/bcoin/hd.js b/lib/bcoin/hd.js index 263aca86..53bc5a96 100644 --- a/lib/bcoin/hd.js +++ b/lib/bcoin/hd.js @@ -1958,23 +1958,21 @@ HDPublicKey.isHDPublicKey = function isHDPublicKey(obj) { * Get private key. * @memberof HDPrivateKey# * @memberof HDPublicKey# + * @method * @returns {Buffer} */ - HD.prototype.getPrivateKey = function getPrivateKey() { - return KeyPair.prototype.getPrivateKey.apply(this, arguments); - }; + HD.prototype.getPrivateKey = KeyPair.prototype.getPrivateKey; /** * Get public key. * @memberof HDPrivateKey# * @memberof HDPublicKey# + * @method * @returns {Buffer} */ - HD.prototype.getPublicKey = function getPublicKey() { - return KeyPair.prototype.getPublicKey.apply(this, arguments); - }; + HD.prototype.getPublicKey = KeyPair.prototype.getPublicKey; /** * Sign message. @@ -1984,9 +1982,7 @@ HDPublicKey.isHDPublicKey = function isHDPublicKey(obj) { * @returns {Buffer} */ - HD.prototype.sign = function sign() { - return KeyPair.prototype.sign.apply(this, arguments); - }; + HD.prototype.sign = KeyPair.prototype.sign; /** * Verify message. @@ -1994,13 +1990,19 @@ HDPublicKey.isHDPublicKey = function isHDPublicKey(obj) { * @memberof HDPublicKey# * @param {Buffer} msg * @param {Buffer} sig - * @param {Buffer} key * @returns {Boolean} */ - HD.prototype.verify = function verify() { - return KeyPair.prototype.verify.apply(this, arguments); - }; + HD.prototype.verify = KeyPair.prototype.verify; + + /** + * Whether the key prefers a + * compressed public key. + * Always true. + * @memberof HDPrivateKey# + * @memberof HDPublicKey# + * @type {Boolean} + */ HD.prototype.compressed = true; }); @@ -2019,8 +2021,8 @@ HDPrivateKey.prototype.toKeyPair = function toKeyPair() { * @returns {Base58String} */ -HDPrivateKey.prototype.toSecret = function toSecret() { - return this.toKeyPair().toSecret(); +HDPrivateKey.prototype.toSecret = function toSecret(network) { + return this.toKeyPair().toSecret(network); }; /* diff --git a/lib/bcoin/keypair.js b/lib/bcoin/keypair.js index 25f4571a..d995c3bf 100644 --- a/lib/bcoin/keypair.js +++ b/lib/bcoin/keypair.js @@ -49,26 +49,17 @@ function KeyPair(options) { */ KeyPair.prototype.fromOptions = function fromOptions(options) { - assert(options.privateKey || options.publicKey); - assert(!options.privateKey || Buffer.isBuffer(options.privateKey)); - assert(!options.publicKey || Buffer.isBuffer(options.publicKey)); - - if (options.compressed != null) - this.compressed = options.compressed; - - if (options.network) - this.network = bcoin.network.get(options.network); - - this.privateKey = options.privateKey; - this.publicKey = options.publicKey; - - if (!this.publicKey) { - this.publicKey = bcoin.ec.publicKeyCreate( - this.privateKey, this.compressed - ); + if (options.privateKey) { + return this.fromPrivate( + options.privateKey, + options.compressed, + options.network); } - return this; + if (options.publicKey) + return this.fromPublic(options.publicKey, options.network); + + throw new Error('Must provide a key.'); }; /** @@ -95,6 +86,61 @@ KeyPair.generate = function(network) { return key; }; +/** + * Inject data from private key. + * @private + * @param {Buffer} privateKey + * @param {Boolean?} compressed + * @param {(NetworkType|Network}) network + */ + +KeyPair.prototype.fromPrivate = function fromPrivate(privateKey, compressed, network) { + assert(Buffer.isBuffer(privateKey)); + this.network = bcoin.network.get(network); + this.privateKey = privateKey; + this.compressed = compressed !== false; + this.publicKey = bcoin.ec.publicKeyCreate(this.privateKey, this.compressed); + return this; +}; + +/** + * Instantiate key pair from a private key. + * @param {Buffer} privateKey + * @param {Boolean?} compressed + * @param {(NetworkType|Network}) network + * @returns {KeyPair} + */ + +KeyPair.fromPrivate = function fromPrivate(privateKey, compressed, network) { + return new KeyPair().fromPrivate(privateKey, compressed, network); +}; + +/** + * Inject data from public key. + * @private + * @param {Buffer} privateKey + * @param {(NetworkType|Network}) network + */ + +KeyPair.prototype.fromPublic = function fromPublic(publicKey, network) { + assert(Buffer.isBuffer(publicKey)); + this.network = bcoin.network.get(network); + this.publicKey = publicKey; + this.compressed = publicKey[0] <= 0x03; + return this; +}; + +/** + * Instantiate key pair from a public key. + * @param {Buffer} publicKey + * @param {(NetworkType|Network}) network + * @returns {KeyPair} + */ + +KeyPair.fromPublic = function fromPublic(publicKey, network) { + return new KeyPair().fromPublic(publicKey, network); +}; + /** * Sign a message. * @param {Buffer} msg @@ -102,6 +148,7 @@ KeyPair.generate = function(network) { */ KeyPair.prototype.sign = function sign(msg) { + assert(this.privateKey, 'Cannot sign without private key.'); return bcoin.ec.sign(msg, this.getPrivateKey()); }; @@ -160,6 +207,8 @@ KeyPair.prototype.getPublicKey = function getPublicKey(enc) { KeyPair.prototype.toRaw = function toRaw(network, writer) { var p = new BufferWriter(writer); + assert(this.privateKey, 'Cannot serialize without private key.'); + if (!network) network = this.network; @@ -197,7 +246,7 @@ KeyPair.prototype.toSecret = function toSecret(network) { KeyPair.prototype.fromRaw = function fromRaw(data) { var p = new BufferReader(data, true); - var i, prefix, version, type; + var i, prefix, version, type, key, compressed; version = p.readU8(); @@ -210,23 +259,20 @@ KeyPair.prototype.fromRaw = function fromRaw(data) { assert(i < network.types.length, 'Network not found.'); - this.network = bcoin.network.get(type); - this.privateKey = p.readBytes(32); + key = p.readBytes(32); if (p.left() > 4) { assert(p.readU8() === 1, 'Bad compression flag.'); - this.compressed = true; + compressed = true; } else { - this.compressed = false; + compressed = false; } p.verifyChecksum(); - this.publicKey = bcoin.ec.publicKeyCreate( - this.privateKey, this.compressed - ); + assert(bcoin.ec.privateKeyVerify(key)); - return this; + return this.fromPrivate(key, compressed, type); }; /** @@ -281,16 +327,15 @@ KeyPair.prototype.toJSON = function toJSON() { */ KeyPair.prototype.fromJSON = function fromJSON(json) { - this.network = bcoin.network.get(json.network); - this.compressed = json.compressed; + var key; if (json.privateKey) return this.fromSecret(json.privateKey); if (json.publicKey) { - this.publicKey = utils.fromBase58(json.publicKey); - this.compressed = this.publicKey[0] !== 0x04; - return this; + key = utils.fromBase58(json.publicKey); + assert(bcoin.ec.publicKeyVerify(key)); + return this.fromPublic(key, json.network); } assert(false, 'Could not parse KeyPair JSON.');