react / wstein / node_modules / browserify / node_modules / crypto-browserify / node_modules / browserify-sign / node_modules / elliptic / lib / elliptic / ec / index.js
80621 views'use strict';12var bn = require('bn.js');3var elliptic = require('../../elliptic');4var utils = elliptic.utils;5var assert = utils.assert;67var KeyPair = require('./key');8var Signature = require('./signature');910function EC(options) {11if (!(this instanceof EC))12return new EC(options);1314// Shortcut `elliptic.ec(curve-name)`15if (typeof options === 'string') {16assert(elliptic.curves.hasOwnProperty(options), 'Unknown curve ' + options);1718options = elliptic.curves[options];19}2021// Shortcut for `elliptic.ec(elliptic.curves.curveName)`22if (options instanceof elliptic.curves.PresetCurve)23options = { curve: options };2425this.curve = options.curve.curve;26this.n = this.curve.n;27this.nh = this.n.shrn(1);28this.g = this.curve.g;2930// Point on curve31this.g = options.curve.g;32this.g.precompute(options.curve.n.bitLength() + 1);3334// Hash for function for DRBG35this.hash = options.hash || options.curve.hash;36}37module.exports = EC;3839EC.prototype.keyPair = function keyPair(options) {40return new KeyPair(this, options);41};4243EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) {44return KeyPair.fromPrivate(this, priv, enc);45};4647EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) {48return KeyPair.fromPublic(this, pub, enc);49};5051EC.prototype.genKeyPair = function genKeyPair(options) {52if (!options)53options = {};5455// Instantiate Hmac_DRBG56var drbg = new elliptic.hmacDRBG({57hash: this.hash,58pers: options.pers,59entropy: options.entropy || elliptic.rand(this.hash.hmacStrength),60nonce: this.n.toArray()61});6263var bytes = this.n.byteLength();64var ns2 = this.n.sub(new bn(2));65do {66var priv = new bn(drbg.generate(bytes));67if (priv.cmp(ns2) > 0)68continue;6970priv.iaddn(1);71return this.keyFromPrivate(priv);72} while (true);73};7475EC.prototype._truncateToN = function truncateToN(msg, truncOnly) {76var delta = msg.byteLength() * 8 - this.n.bitLength();77if (delta > 0)78msg = msg.shrn(delta);79if (!truncOnly && msg.cmp(this.n) >= 0)80return msg.sub(this.n);81else82return msg;83};8485EC.prototype.sign = function sign(msg, key, enc, options) {86if (typeof enc === 'object') {87options = enc;88enc = null;89}90if (!options)91options = {};9293key = this.keyFromPrivate(key, enc);94msg = this._truncateToN(new bn(msg, 16));9596// Zero-extend key to provide enough entropy97var bytes = this.n.byteLength();98var bkey = key.getPrivate().toArray();99for (var i = bkey.length; i < 21; i++)100bkey.unshift(0);101102// Zero-extend nonce to have the same byte size as N103var nonce = msg.toArray();104for (var i = nonce.length; i < bytes; i++)105nonce.unshift(0);106107// Instantiate Hmac_DRBG108var drbg = new elliptic.hmacDRBG({109hash: this.hash,110entropy: bkey,111nonce: nonce112});113114// Number of bytes to generate115var ns1 = this.n.sub(new bn(1));116do {117var k = new bn(drbg.generate(this.n.byteLength()));118k = this._truncateToN(k, true);119if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0)120continue;121122var kp = this.g.mul(k);123if (kp.isInfinity())124continue;125126var r = kp.getX().mod(this.n);127if (r.cmpn(0) === 0)128continue;129130var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)).mod(this.n);131if (s.cmpn(0) === 0)132continue;133134// Use complement of `s`, if it is > `n / 2`135if (options.canonical && s.cmp(this.nh) > 0)136s = this.n.sub(s);137138return new Signature({ r: r, s: s });139} while (true);140};141142EC.prototype.verify = function verify(msg, signature, key, enc) {143msg = this._truncateToN(new bn(msg, 16));144key = this.keyFromPublic(key, enc);145signature = new Signature(signature, 'hex');146147// Perform primitive values validation148var r = signature.r;149var s = signature.s;150if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0)151return false;152if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0)153return false;154155// Validate signature156var sinv = s.invm(this.n);157var u1 = sinv.mul(msg).mod(this.n);158var u2 = sinv.mul(r).mod(this.n);159160var p = this.g.mulAdd(u1, key.getPublic(), u2);161if (p.isInfinity())162return false;163164return p.getX().mod(this.n).cmp(r) === 0;165};166167168