UNPKG

know-js

Version:

JavaScript library for sending Know transactions from the client or server

206 lines (170 loc) 4.99 kB
var base58check = require('bs58check') var bcrypto = require('./crypto') var ecdsa = require('./ecdsa') var ECSignature = require('./ecsignature') var randomBytes = require('randombytes') var typeforce = require('typeforce') var types = require('./types') var wif = require('wif') var NETWORKS = require('./networks') var BigInteger = require('bigi') var ecurve = require('ecurve') var secp256k1 = ecurve.getCurveByName('secp256k1') var secp256k1native = require('secp256k1') /** * Provide either `d` or `Q` but not both. * * @constructor * @param {BigInteger} [d] Private key. * @param {Point} [Q] Public key. * @param {object} [options] * @param {boolean} [options.compressed=true] * @param {Network} [options.network=networks.know] */ 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 } /** @type {boolean} */ this.compressed = options.compressed === undefined ? true : options.compressed /** @type {Network} */ this.network = options.network || NETWORKS.know } Object.defineProperty(ECPair.prototype, 'Q', { get: function () { if (!this.__Q && this.d) { this.__Q = secp256k1.G.multiply(this.d) } return this.__Q } }) /** * @param {Buffer} buffer * @param {Network} [network=networks.know] * @returns {ECPair} */ ECPair.fromPublicKeyBuffer = function (buffer, network) { var Q = ecurve.Point.decodeFrom(secp256k1, buffer) return new ECPair(null, Q, { compressed: Q.compressed, network: network }) } /** * @param {string} string * @param {Network[]|Network} network * @returns {ECPair} */ ECPair.fromWIF = function (string, network) { var decoded = wif.decode(string) var version = decoded.version // [network, ...] if (types.Array(network)) { network = network.filter(function (network) { return version === network.wif }).pop() if (!network) throw new Error('Unknown network version') // network } else { network = network || NETWORKS.know 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 }) } /** * @param {object} [options] * @param {function} [options.rng] * @param {boolean} [options.compressed=true] * @param {Network} [options.network=networks.know] */ 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) } /** * @param {string} seed * @param {object} [options] * @param {boolean} [options.compressed=true] * @param {Network} [options.network=networks.know] * @returns {ECPair} */ ECPair.fromSeed = function(seed, options) { var hash = bcrypto.sha256(new Buffer(seed,"utf-8")) var d = BigInteger.fromBuffer(hash) if(d.signum() <= 0 || d.compareTo(secp256k1.n) >= 0){ throw new Error("seed cannot resolve to a compatible private key") } else{ return new ECPair(d, null, options) } } /** * @returns {string} */ ECPair.prototype.getAddress = function () { var payload = new Buffer(21) var hash = bcrypto.ripemd160(this.getPublicKeyBuffer()) var version = this.getNetwork().pubKeyHash payload.writeUInt8(version, 0) hash.copy(payload, 1) return base58check.encode(payload) } /** * @returns {Network} */ ECPair.prototype.getNetwork = function () { return this.network } ECPair.prototype.getPublicKeyBuffer = function () { return this.Q.getEncoded(this.compressed) } /** * Requires a private key (`d`) to be set. * * @param {Buffer} hash * @returns {ECSignature} */ ECPair.prototype.sign = function (hash) { if (!this.d) throw new Error('Missing private key') var native=secp256k1native.sign(hash, this.d.toBuffer(32)) return ECSignature.parseNativeSecp256k1(native).signature } /** * Requires a private key (`d`) to be set. * * @returns {string} */ 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) } /** * @param {Buffer} hash * @returns {boolean} */ ECPair.prototype.verify = function (hash, signature) { return secp256k1native.verify(hash, signature.toNativeSecp256k1(), this.Q.getEncoded(this.compressed)) } module.exports = ECPair