let ecdsa = require('./ecdsa') let randomBytes = require('randombytes') let typeforce = require('typeforce') let types = require('./types') let wif = require('wif') let NETWORKS = require('./networks') let BigInteger = require('bigi') let ecurve = require('ecurve') let secp256k1 = ecdsa.__curve function ECPair (d, Q, options) { if (options) { typeforce({ compressed: types.maybe(types.Boolean), network: types.maybe(types.Network) }, options) } options = options || {} if (d) { if (d.signum() <= 0) throw new Error('Private key must be greater than 0') if (d.compareTo(secp256k1.n) >= 0) throw new Error('Private key must be less than the curve order') if (Q) throw new TypeError('Unexpected publicKey parameter') this.d = d } else { typeforce(types.ECPoint, Q) this.__Q = Q } this.compressed = options.compressed === undefined ? true : options.compressed this.network = options.network || NETWORKS.bitcoin } Object.defineProperty(ECPair.prototype, 'Q', { get: function () { if (!this.__Q && this.d) { this.__Q = secp256k1.G.multiply(this.d) } return this.__Q } }) ECPair.fromPublicKeyBuffer = function (buffer, network) { var Q = ecurve.Point.decodeFrom(secp256k1, buffer) return new ECPair(null, Q, { compressed: Q.compressed, network: network }) } ECPair.fromWIF = function (string, network) { var decoded = wif.decode(string) var version = decoded.version // list of networks? if (types.Array(network)) { network = network.filter(function (x) { return version === x.wif }).pop() if (!network) throw new Error('Unknown network version') // otherwise, assume a network object (or default to bitcoin) } else { network = network || NETWORKS.bitcoin if (version !== network.wif) throw new Error('Invalid network version') } var d = BigInteger.fromBuffer(decoded.privateKey) return new ECPair(d, null, { compressed: decoded.compressed, network: network }) } ECPair.makeRandom = function (options) { options = options || {} var rng = options.rng || randomBytes var d do { var buffer = rng(32) typeforce(types.Buffer256bit, buffer) d = BigInteger.fromBuffer(buffer) } while (d.signum() <= 0 || d.compareTo(secp256k1.n) >= 0) return new ECPair(d, null, options) } ECPair.prototype.getNetwork = function () { return this.network } ECPair.prototype.getPublicKeyBuffer = function () { return this.Q.getEncoded(this.compressed) } ECPair.prototype.sign = function (hash) { if (!this.d) throw new Error('Missing private key') let signature = ecdsa.sign(hash, this.d) return Buffer.concat([signature.r.toBuffer(32), signature.s.toBuffer(32)], 64) } ECPair.prototype.toWIF = function () { if (!this.d) throw new Error('Missing private key') return wif.encode(this.network.wif, this.d.toBuffer(32), this.compressed) } ECPair.prototype.verify = function (hash, signature) { signature = { r: BigInteger.fromBuffer(signature.slice(0, 32)), s: BigInteger.fromBuffer(signature.slice(32, 64)) } return ecdsa.verify(hash, signature, this.Q) } module.exports = ECPair