| 'use strict'; | 
|   | 
| var utils = require('../utils'); | 
| var BN = require('bn.js'); | 
| var inherits = require('inherits'); | 
| var Base = require('./base'); | 
|   | 
| var assert = utils.assert; | 
|   | 
| function ShortCurve(conf) { | 
|   Base.call(this, 'short', conf); | 
|   | 
|   this.a = new BN(conf.a, 16).toRed(this.red); | 
|   this.b = new BN(conf.b, 16).toRed(this.red); | 
|   this.tinv = this.two.redInvm(); | 
|   | 
|   this.zeroA = this.a.fromRed().cmpn(0) === 0; | 
|   this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0; | 
|   | 
|   // If the curve is endomorphic, precalculate beta and lambda | 
|   this.endo = this._getEndomorphism(conf); | 
|   this._endoWnafT1 = new Array(4); | 
|   this._endoWnafT2 = new Array(4); | 
| } | 
| inherits(ShortCurve, Base); | 
| module.exports = ShortCurve; | 
|   | 
| ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) { | 
|   // No efficient endomorphism | 
|   if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1) | 
|     return; | 
|   | 
|   // Compute beta and lambda, that lambda * P = (beta * Px; Py) | 
|   var beta; | 
|   var lambda; | 
|   if (conf.beta) { | 
|     beta = new BN(conf.beta, 16).toRed(this.red); | 
|   } else { | 
|     var betas = this._getEndoRoots(this.p); | 
|     // Choose the smallest beta | 
|     beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1]; | 
|     beta = beta.toRed(this.red); | 
|   } | 
|   if (conf.lambda) { | 
|     lambda = new BN(conf.lambda, 16); | 
|   } else { | 
|     // Choose the lambda that is matching selected beta | 
|     var lambdas = this._getEndoRoots(this.n); | 
|     if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) { | 
|       lambda = lambdas[0]; | 
|     } else { | 
|       lambda = lambdas[1]; | 
|       assert(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0); | 
|     } | 
|   } | 
|   | 
|   // Get basis vectors, used for balanced length-two representation | 
|   var basis; | 
|   if (conf.basis) { | 
|     basis = conf.basis.map(function(vec) { | 
|       return { | 
|         a: new BN(vec.a, 16), | 
|         b: new BN(vec.b, 16), | 
|       }; | 
|     }); | 
|   } else { | 
|     basis = this._getEndoBasis(lambda); | 
|   } | 
|   | 
|   return { | 
|     beta: beta, | 
|     lambda: lambda, | 
|     basis: basis, | 
|   }; | 
| }; | 
|   | 
| ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) { | 
|   // Find roots of for x^2 + x + 1 in F | 
|   // Root = (-1 +- Sqrt(-3)) / 2 | 
|   // | 
|   var red = num === this.p ? this.red : BN.mont(num); | 
|   var tinv = new BN(2).toRed(red).redInvm(); | 
|   var ntinv = tinv.redNeg(); | 
|   | 
|   var s = new BN(3).toRed(red).redNeg().redSqrt().redMul(tinv); | 
|   | 
|   var l1 = ntinv.redAdd(s).fromRed(); | 
|   var l2 = ntinv.redSub(s).fromRed(); | 
|   return [ l1, l2 ]; | 
| }; | 
|   | 
| ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) { | 
|   // aprxSqrt >= sqrt(this.n) | 
|   var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2)); | 
|   | 
|   // 3.74 | 
|   // Run EGCD, until r(L + 1) < aprxSqrt | 
|   var u = lambda; | 
|   var v = this.n.clone(); | 
|   var x1 = new BN(1); | 
|   var y1 = new BN(0); | 
|   var x2 = new BN(0); | 
|   var y2 = new BN(1); | 
|   | 
|   // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n) | 
|   var a0; | 
|   var b0; | 
|   // First vector | 
|   var a1; | 
|   var b1; | 
|   // Second vector | 
|   var a2; | 
|   var b2; | 
|   | 
|   var prevR; | 
|   var i = 0; | 
|   var r; | 
|   var x; | 
|   while (u.cmpn(0) !== 0) { | 
|     var q = v.div(u); | 
|     r = v.sub(q.mul(u)); | 
|     x = x2.sub(q.mul(x1)); | 
|     var y = y2.sub(q.mul(y1)); | 
|   | 
|     if (!a1 && r.cmp(aprxSqrt) < 0) { | 
|       a0 = prevR.neg(); | 
|       b0 = x1; | 
|       a1 = r.neg(); | 
|       b1 = x; | 
|     } else if (a1 && ++i === 2) { | 
|       break; | 
|     } | 
|     prevR = r; | 
|   | 
|     v = u; | 
|     u = r; | 
|     x2 = x1; | 
|     x1 = x; | 
|     y2 = y1; | 
|     y1 = y; | 
|   } | 
|   a2 = r.neg(); | 
|   b2 = x; | 
|   | 
|   var len1 = a1.sqr().add(b1.sqr()); | 
|   var len2 = a2.sqr().add(b2.sqr()); | 
|   if (len2.cmp(len1) >= 0) { | 
|     a2 = a0; | 
|     b2 = b0; | 
|   } | 
|   | 
|   // Normalize signs | 
|   if (a1.negative) { | 
|     a1 = a1.neg(); | 
|     b1 = b1.neg(); | 
|   } | 
|   if (a2.negative) { | 
|     a2 = a2.neg(); | 
|     b2 = b2.neg(); | 
|   } | 
|   | 
|   return [ | 
|     { a: a1, b: b1 }, | 
|     { a: a2, b: b2 }, | 
|   ]; | 
| }; | 
|   | 
| ShortCurve.prototype._endoSplit = function _endoSplit(k) { | 
|   var basis = this.endo.basis; | 
|   var v1 = basis[0]; | 
|   var v2 = basis[1]; | 
|   | 
|   var c1 = v2.b.mul(k).divRound(this.n); | 
|   var c2 = v1.b.neg().mul(k).divRound(this.n); | 
|   | 
|   var p1 = c1.mul(v1.a); | 
|   var p2 = c2.mul(v2.a); | 
|   var q1 = c1.mul(v1.b); | 
|   var q2 = c2.mul(v2.b); | 
|   | 
|   // Calculate answer | 
|   var k1 = k.sub(p1).sub(p2); | 
|   var k2 = q1.add(q2).neg(); | 
|   return { k1: k1, k2: k2 }; | 
| }; | 
|   | 
| ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { | 
|   x = new BN(x, 16); | 
|   if (!x.red) | 
|     x = x.toRed(this.red); | 
|   | 
|   var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); | 
|   var y = y2.redSqrt(); | 
|   if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) | 
|     throw new Error('invalid point'); | 
|   | 
|   // XXX Is there any way to tell if the number is odd without converting it | 
|   // to non-red form? | 
|   var isOdd = y.fromRed().isOdd(); | 
|   if (odd && !isOdd || !odd && isOdd) | 
|     y = y.redNeg(); | 
|   | 
|   return this.point(x, y); | 
| }; | 
|   | 
| ShortCurve.prototype.validate = function validate(point) { | 
|   if (point.inf) | 
|     return true; | 
|   | 
|   var x = point.x; | 
|   var y = point.y; | 
|   | 
|   var ax = this.a.redMul(x); | 
|   var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b); | 
|   return y.redSqr().redISub(rhs).cmpn(0) === 0; | 
| }; | 
|   | 
| ShortCurve.prototype._endoWnafMulAdd = | 
|     function _endoWnafMulAdd(points, coeffs, jacobianResult) { | 
|       var npoints = this._endoWnafT1; | 
|       var ncoeffs = this._endoWnafT2; | 
|       for (var i = 0; i < points.length; i++) { | 
|         var split = this._endoSplit(coeffs[i]); | 
|         var p = points[i]; | 
|         var beta = p._getBeta(); | 
|   | 
|         if (split.k1.negative) { | 
|           split.k1.ineg(); | 
|           p = p.neg(true); | 
|         } | 
|         if (split.k2.negative) { | 
|           split.k2.ineg(); | 
|           beta = beta.neg(true); | 
|         } | 
|   | 
|         npoints[i * 2] = p; | 
|         npoints[i * 2 + 1] = beta; | 
|         ncoeffs[i * 2] = split.k1; | 
|         ncoeffs[i * 2 + 1] = split.k2; | 
|       } | 
|       var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult); | 
|   | 
|       // Clean-up references to points and coefficients | 
|       for (var j = 0; j < i * 2; j++) { | 
|         npoints[j] = null; | 
|         ncoeffs[j] = null; | 
|       } | 
|       return res; | 
|     }; | 
|   | 
| function Point(curve, x, y, isRed) { | 
|   Base.BasePoint.call(this, curve, 'affine'); | 
|   if (x === null && y === null) { | 
|     this.x = null; | 
|     this.y = null; | 
|     this.inf = true; | 
|   } else { | 
|     this.x = new BN(x, 16); | 
|     this.y = new BN(y, 16); | 
|     // Force redgomery representation when loading from JSON | 
|     if (isRed) { | 
|       this.x.forceRed(this.curve.red); | 
|       this.y.forceRed(this.curve.red); | 
|     } | 
|     if (!this.x.red) | 
|       this.x = this.x.toRed(this.curve.red); | 
|     if (!this.y.red) | 
|       this.y = this.y.toRed(this.curve.red); | 
|     this.inf = false; | 
|   } | 
| } | 
| inherits(Point, Base.BasePoint); | 
|   | 
| ShortCurve.prototype.point = function point(x, y, isRed) { | 
|   return new Point(this, x, y, isRed); | 
| }; | 
|   | 
| ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) { | 
|   return Point.fromJSON(this, obj, red); | 
| }; | 
|   | 
| Point.prototype._getBeta = function _getBeta() { | 
|   if (!this.curve.endo) | 
|     return; | 
|   | 
|   var pre = this.precomputed; | 
|   if (pre && pre.beta) | 
|     return pre.beta; | 
|   | 
|   var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y); | 
|   if (pre) { | 
|     var curve = this.curve; | 
|     var endoMul = function(p) { | 
|       return curve.point(p.x.redMul(curve.endo.beta), p.y); | 
|     }; | 
|     pre.beta = beta; | 
|     beta.precomputed = { | 
|       beta: null, | 
|       naf: pre.naf && { | 
|         wnd: pre.naf.wnd, | 
|         points: pre.naf.points.map(endoMul), | 
|       }, | 
|       doubles: pre.doubles && { | 
|         step: pre.doubles.step, | 
|         points: pre.doubles.points.map(endoMul), | 
|       }, | 
|     }; | 
|   } | 
|   return beta; | 
| }; | 
|   | 
| Point.prototype.toJSON = function toJSON() { | 
|   if (!this.precomputed) | 
|     return [ this.x, this.y ]; | 
|   | 
|   return [ this.x, this.y, this.precomputed && { | 
|     doubles: this.precomputed.doubles && { | 
|       step: this.precomputed.doubles.step, | 
|       points: this.precomputed.doubles.points.slice(1), | 
|     }, | 
|     naf: this.precomputed.naf && { | 
|       wnd: this.precomputed.naf.wnd, | 
|       points: this.precomputed.naf.points.slice(1), | 
|     }, | 
|   } ]; | 
| }; | 
|   | 
| Point.fromJSON = function fromJSON(curve, obj, red) { | 
|   if (typeof obj === 'string') | 
|     obj = JSON.parse(obj); | 
|   var res = curve.point(obj[0], obj[1], red); | 
|   if (!obj[2]) | 
|     return res; | 
|   | 
|   function obj2point(obj) { | 
|     return curve.point(obj[0], obj[1], red); | 
|   } | 
|   | 
|   var pre = obj[2]; | 
|   res.precomputed = { | 
|     beta: null, | 
|     doubles: pre.doubles && { | 
|       step: pre.doubles.step, | 
|       points: [ res ].concat(pre.doubles.points.map(obj2point)), | 
|     }, | 
|     naf: pre.naf && { | 
|       wnd: pre.naf.wnd, | 
|       points: [ res ].concat(pre.naf.points.map(obj2point)), | 
|     }, | 
|   }; | 
|   return res; | 
| }; | 
|   | 
| Point.prototype.inspect = function inspect() { | 
|   if (this.isInfinity()) | 
|     return '<EC Point Infinity>'; | 
|   return '<EC Point x: ' + this.x.fromRed().toString(16, 2) + | 
|       ' y: ' + this.y.fromRed().toString(16, 2) + '>'; | 
| }; | 
|   | 
| Point.prototype.isInfinity = function isInfinity() { | 
|   return this.inf; | 
| }; | 
|   | 
| Point.prototype.add = function add(p) { | 
|   // O + P = P | 
|   if (this.inf) | 
|     return p; | 
|   | 
|   // P + O = P | 
|   if (p.inf) | 
|     return this; | 
|   | 
|   // P + P = 2P | 
|   if (this.eq(p)) | 
|     return this.dbl(); | 
|   | 
|   // P + (-P) = O | 
|   if (this.neg().eq(p)) | 
|     return this.curve.point(null, null); | 
|   | 
|   // P + Q = O | 
|   if (this.x.cmp(p.x) === 0) | 
|     return this.curve.point(null, null); | 
|   | 
|   var c = this.y.redSub(p.y); | 
|   if (c.cmpn(0) !== 0) | 
|     c = c.redMul(this.x.redSub(p.x).redInvm()); | 
|   var nx = c.redSqr().redISub(this.x).redISub(p.x); | 
|   var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); | 
|   return this.curve.point(nx, ny); | 
| }; | 
|   | 
| Point.prototype.dbl = function dbl() { | 
|   if (this.inf) | 
|     return this; | 
|   | 
|   // 2P = O | 
|   var ys1 = this.y.redAdd(this.y); | 
|   if (ys1.cmpn(0) === 0) | 
|     return this.curve.point(null, null); | 
|   | 
|   var a = this.curve.a; | 
|   | 
|   var x2 = this.x.redSqr(); | 
|   var dyinv = ys1.redInvm(); | 
|   var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv); | 
|   | 
|   var nx = c.redSqr().redISub(this.x.redAdd(this.x)); | 
|   var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); | 
|   return this.curve.point(nx, ny); | 
| }; | 
|   | 
| Point.prototype.getX = function getX() { | 
|   return this.x.fromRed(); | 
| }; | 
|   | 
| Point.prototype.getY = function getY() { | 
|   return this.y.fromRed(); | 
| }; | 
|   | 
| Point.prototype.mul = function mul(k) { | 
|   k = new BN(k, 16); | 
|   if (this.isInfinity()) | 
|     return this; | 
|   else if (this._hasDoubles(k)) | 
|     return this.curve._fixedNafMul(this, k); | 
|   else if (this.curve.endo) | 
|     return this.curve._endoWnafMulAdd([ this ], [ k ]); | 
|   else | 
|     return this.curve._wnafMul(this, k); | 
| }; | 
|   | 
| Point.prototype.mulAdd = function mulAdd(k1, p2, k2) { | 
|   var points = [ this, p2 ]; | 
|   var coeffs = [ k1, k2 ]; | 
|   if (this.curve.endo) | 
|     return this.curve._endoWnafMulAdd(points, coeffs); | 
|   else | 
|     return this.curve._wnafMulAdd(1, points, coeffs, 2); | 
| }; | 
|   | 
| Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) { | 
|   var points = [ this, p2 ]; | 
|   var coeffs = [ k1, k2 ]; | 
|   if (this.curve.endo) | 
|     return this.curve._endoWnafMulAdd(points, coeffs, true); | 
|   else | 
|     return this.curve._wnafMulAdd(1, points, coeffs, 2, true); | 
| }; | 
|   | 
| Point.prototype.eq = function eq(p) { | 
|   return this === p || | 
|          this.inf === p.inf && | 
|              (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0); | 
| }; | 
|   | 
| Point.prototype.neg = function neg(_precompute) { | 
|   if (this.inf) | 
|     return this; | 
|   | 
|   var res = this.curve.point(this.x, this.y.redNeg()); | 
|   if (_precompute && this.precomputed) { | 
|     var pre = this.precomputed; | 
|     var negate = function(p) { | 
|       return p.neg(); | 
|     }; | 
|     res.precomputed = { | 
|       naf: pre.naf && { | 
|         wnd: pre.naf.wnd, | 
|         points: pre.naf.points.map(negate), | 
|       }, | 
|       doubles: pre.doubles && { | 
|         step: pre.doubles.step, | 
|         points: pre.doubles.points.map(negate), | 
|       }, | 
|     }; | 
|   } | 
|   return res; | 
| }; | 
|   | 
| Point.prototype.toJ = function toJ() { | 
|   if (this.inf) | 
|     return this.curve.jpoint(null, null, null); | 
|   | 
|   var res = this.curve.jpoint(this.x, this.y, this.curve.one); | 
|   return res; | 
| }; | 
|   | 
| function JPoint(curve, x, y, z) { | 
|   Base.BasePoint.call(this, curve, 'jacobian'); | 
|   if (x === null && y === null && z === null) { | 
|     this.x = this.curve.one; | 
|     this.y = this.curve.one; | 
|     this.z = new BN(0); | 
|   } else { | 
|     this.x = new BN(x, 16); | 
|     this.y = new BN(y, 16); | 
|     this.z = new BN(z, 16); | 
|   } | 
|   if (!this.x.red) | 
|     this.x = this.x.toRed(this.curve.red); | 
|   if (!this.y.red) | 
|     this.y = this.y.toRed(this.curve.red); | 
|   if (!this.z.red) | 
|     this.z = this.z.toRed(this.curve.red); | 
|   | 
|   this.zOne = this.z === this.curve.one; | 
| } | 
| inherits(JPoint, Base.BasePoint); | 
|   | 
| ShortCurve.prototype.jpoint = function jpoint(x, y, z) { | 
|   return new JPoint(this, x, y, z); | 
| }; | 
|   | 
| JPoint.prototype.toP = function toP() { | 
|   if (this.isInfinity()) | 
|     return this.curve.point(null, null); | 
|   | 
|   var zinv = this.z.redInvm(); | 
|   var zinv2 = zinv.redSqr(); | 
|   var ax = this.x.redMul(zinv2); | 
|   var ay = this.y.redMul(zinv2).redMul(zinv); | 
|   | 
|   return this.curve.point(ax, ay); | 
| }; | 
|   | 
| JPoint.prototype.neg = function neg() { | 
|   return this.curve.jpoint(this.x, this.y.redNeg(), this.z); | 
| }; | 
|   | 
| JPoint.prototype.add = function add(p) { | 
|   // O + P = P | 
|   if (this.isInfinity()) | 
|     return p; | 
|   | 
|   // P + O = P | 
|   if (p.isInfinity()) | 
|     return this; | 
|   | 
|   // 12M + 4S + 7A | 
|   var pz2 = p.z.redSqr(); | 
|   var z2 = this.z.redSqr(); | 
|   var u1 = this.x.redMul(pz2); | 
|   var u2 = p.x.redMul(z2); | 
|   var s1 = this.y.redMul(pz2.redMul(p.z)); | 
|   var s2 = p.y.redMul(z2.redMul(this.z)); | 
|   | 
|   var h = u1.redSub(u2); | 
|   var r = s1.redSub(s2); | 
|   if (h.cmpn(0) === 0) { | 
|     if (r.cmpn(0) !== 0) | 
|       return this.curve.jpoint(null, null, null); | 
|     else | 
|       return this.dbl(); | 
|   } | 
|   | 
|   var h2 = h.redSqr(); | 
|   var h3 = h2.redMul(h); | 
|   var v = u1.redMul(h2); | 
|   | 
|   var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); | 
|   var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); | 
|   var nz = this.z.redMul(p.z).redMul(h); | 
|   | 
|   return this.curve.jpoint(nx, ny, nz); | 
| }; | 
|   | 
| JPoint.prototype.mixedAdd = function mixedAdd(p) { | 
|   // O + P = P | 
|   if (this.isInfinity()) | 
|     return p.toJ(); | 
|   | 
|   // P + O = P | 
|   if (p.isInfinity()) | 
|     return this; | 
|   | 
|   // 8M + 3S + 7A | 
|   var z2 = this.z.redSqr(); | 
|   var u1 = this.x; | 
|   var u2 = p.x.redMul(z2); | 
|   var s1 = this.y; | 
|   var s2 = p.y.redMul(z2).redMul(this.z); | 
|   | 
|   var h = u1.redSub(u2); | 
|   var r = s1.redSub(s2); | 
|   if (h.cmpn(0) === 0) { | 
|     if (r.cmpn(0) !== 0) | 
|       return this.curve.jpoint(null, null, null); | 
|     else | 
|       return this.dbl(); | 
|   } | 
|   | 
|   var h2 = h.redSqr(); | 
|   var h3 = h2.redMul(h); | 
|   var v = u1.redMul(h2); | 
|   | 
|   var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); | 
|   var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); | 
|   var nz = this.z.redMul(h); | 
|   | 
|   return this.curve.jpoint(nx, ny, nz); | 
| }; | 
|   | 
| JPoint.prototype.dblp = function dblp(pow) { | 
|   if (pow === 0) | 
|     return this; | 
|   if (this.isInfinity()) | 
|     return this; | 
|   if (!pow) | 
|     return this.dbl(); | 
|   | 
|   var i; | 
|   if (this.curve.zeroA || this.curve.threeA) { | 
|     var r = this; | 
|     for (i = 0; i < pow; i++) | 
|       r = r.dbl(); | 
|     return r; | 
|   } | 
|   | 
|   // 1M + 2S + 1A + N * (4S + 5M + 8A) | 
|   // N = 1 => 6M + 6S + 9A | 
|   var a = this.curve.a; | 
|   var tinv = this.curve.tinv; | 
|   | 
|   var jx = this.x; | 
|   var jy = this.y; | 
|   var jz = this.z; | 
|   var jz4 = jz.redSqr().redSqr(); | 
|   | 
|   // Reuse results | 
|   var jyd = jy.redAdd(jy); | 
|   for (i = 0; i < pow; i++) { | 
|     var jx2 = jx.redSqr(); | 
|     var jyd2 = jyd.redSqr(); | 
|     var jyd4 = jyd2.redSqr(); | 
|     var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); | 
|   | 
|     var t1 = jx.redMul(jyd2); | 
|     var nx = c.redSqr().redISub(t1.redAdd(t1)); | 
|     var t2 = t1.redISub(nx); | 
|     var dny = c.redMul(t2); | 
|     dny = dny.redIAdd(dny).redISub(jyd4); | 
|     var nz = jyd.redMul(jz); | 
|     if (i + 1 < pow) | 
|       jz4 = jz4.redMul(jyd4); | 
|   | 
|     jx = nx; | 
|     jz = nz; | 
|     jyd = dny; | 
|   } | 
|   | 
|   return this.curve.jpoint(jx, jyd.redMul(tinv), jz); | 
| }; | 
|   | 
| JPoint.prototype.dbl = function dbl() { | 
|   if (this.isInfinity()) | 
|     return this; | 
|   | 
|   if (this.curve.zeroA) | 
|     return this._zeroDbl(); | 
|   else if (this.curve.threeA) | 
|     return this._threeDbl(); | 
|   else | 
|     return this._dbl(); | 
| }; | 
|   | 
| JPoint.prototype._zeroDbl = function _zeroDbl() { | 
|   var nx; | 
|   var ny; | 
|   var nz; | 
|   // Z = 1 | 
|   if (this.zOne) { | 
|     // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html | 
|     //     #doubling-mdbl-2007-bl | 
|     // 1M + 5S + 14A | 
|   | 
|     // XX = X1^2 | 
|     var xx = this.x.redSqr(); | 
|     // YY = Y1^2 | 
|     var yy = this.y.redSqr(); | 
|     // YYYY = YY^2 | 
|     var yyyy = yy.redSqr(); | 
|     // S = 2 * ((X1 + YY)^2 - XX - YYYY) | 
|     var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); | 
|     s = s.redIAdd(s); | 
|     // M = 3 * XX + a; a = 0 | 
|     var m = xx.redAdd(xx).redIAdd(xx); | 
|     // T = M ^ 2 - 2*S | 
|     var t = m.redSqr().redISub(s).redISub(s); | 
|   | 
|     // 8 * YYYY | 
|     var yyyy8 = yyyy.redIAdd(yyyy); | 
|     yyyy8 = yyyy8.redIAdd(yyyy8); | 
|     yyyy8 = yyyy8.redIAdd(yyyy8); | 
|   | 
|     // X3 = T | 
|     nx = t; | 
|     // Y3 = M * (S - T) - 8 * YYYY | 
|     ny = m.redMul(s.redISub(t)).redISub(yyyy8); | 
|     // Z3 = 2*Y1 | 
|     nz = this.y.redAdd(this.y); | 
|   } else { | 
|     // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html | 
|     //     #doubling-dbl-2009-l | 
|     // 2M + 5S + 13A | 
|   | 
|     // A = X1^2 | 
|     var a = this.x.redSqr(); | 
|     // B = Y1^2 | 
|     var b = this.y.redSqr(); | 
|     // C = B^2 | 
|     var c = b.redSqr(); | 
|     // D = 2 * ((X1 + B)^2 - A - C) | 
|     var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c); | 
|     d = d.redIAdd(d); | 
|     // E = 3 * A | 
|     var e = a.redAdd(a).redIAdd(a); | 
|     // F = E^2 | 
|     var f = e.redSqr(); | 
|   | 
|     // 8 * C | 
|     var c8 = c.redIAdd(c); | 
|     c8 = c8.redIAdd(c8); | 
|     c8 = c8.redIAdd(c8); | 
|   | 
|     // X3 = F - 2 * D | 
|     nx = f.redISub(d).redISub(d); | 
|     // Y3 = E * (D - X3) - 8 * C | 
|     ny = e.redMul(d.redISub(nx)).redISub(c8); | 
|     // Z3 = 2 * Y1 * Z1 | 
|     nz = this.y.redMul(this.z); | 
|     nz = nz.redIAdd(nz); | 
|   } | 
|   | 
|   return this.curve.jpoint(nx, ny, nz); | 
| }; | 
|   | 
| JPoint.prototype._threeDbl = function _threeDbl() { | 
|   var nx; | 
|   var ny; | 
|   var nz; | 
|   // Z = 1 | 
|   if (this.zOne) { | 
|     // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html | 
|     //     #doubling-mdbl-2007-bl | 
|     // 1M + 5S + 15A | 
|   | 
|     // XX = X1^2 | 
|     var xx = this.x.redSqr(); | 
|     // YY = Y1^2 | 
|     var yy = this.y.redSqr(); | 
|     // YYYY = YY^2 | 
|     var yyyy = yy.redSqr(); | 
|     // S = 2 * ((X1 + YY)^2 - XX - YYYY) | 
|     var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); | 
|     s = s.redIAdd(s); | 
|     // M = 3 * XX + a | 
|     var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a); | 
|     // T = M^2 - 2 * S | 
|     var t = m.redSqr().redISub(s).redISub(s); | 
|     // X3 = T | 
|     nx = t; | 
|     // Y3 = M * (S - T) - 8 * YYYY | 
|     var yyyy8 = yyyy.redIAdd(yyyy); | 
|     yyyy8 = yyyy8.redIAdd(yyyy8); | 
|     yyyy8 = yyyy8.redIAdd(yyyy8); | 
|     ny = m.redMul(s.redISub(t)).redISub(yyyy8); | 
|     // Z3 = 2 * Y1 | 
|     nz = this.y.redAdd(this.y); | 
|   } else { | 
|     // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b | 
|     // 3M + 5S | 
|   | 
|     // delta = Z1^2 | 
|     var delta = this.z.redSqr(); | 
|     // gamma = Y1^2 | 
|     var gamma = this.y.redSqr(); | 
|     // beta = X1 * gamma | 
|     var beta = this.x.redMul(gamma); | 
|     // alpha = 3 * (X1 - delta) * (X1 + delta) | 
|     var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta)); | 
|     alpha = alpha.redAdd(alpha).redIAdd(alpha); | 
|     // X3 = alpha^2 - 8 * beta | 
|     var beta4 = beta.redIAdd(beta); | 
|     beta4 = beta4.redIAdd(beta4); | 
|     var beta8 = beta4.redAdd(beta4); | 
|     nx = alpha.redSqr().redISub(beta8); | 
|     // Z3 = (Y1 + Z1)^2 - gamma - delta | 
|     nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); | 
|     // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 | 
|     var ggamma8 = gamma.redSqr(); | 
|     ggamma8 = ggamma8.redIAdd(ggamma8); | 
|     ggamma8 = ggamma8.redIAdd(ggamma8); | 
|     ggamma8 = ggamma8.redIAdd(ggamma8); | 
|     ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8); | 
|   } | 
|   | 
|   return this.curve.jpoint(nx, ny, nz); | 
| }; | 
|   | 
| JPoint.prototype._dbl = function _dbl() { | 
|   var a = this.curve.a; | 
|   | 
|   // 4M + 6S + 10A | 
|   var jx = this.x; | 
|   var jy = this.y; | 
|   var jz = this.z; | 
|   var jz4 = jz.redSqr().redSqr(); | 
|   | 
|   var jx2 = jx.redSqr(); | 
|   var jy2 = jy.redSqr(); | 
|   | 
|   var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); | 
|   | 
|   var jxd4 = jx.redAdd(jx); | 
|   jxd4 = jxd4.redIAdd(jxd4); | 
|   var t1 = jxd4.redMul(jy2); | 
|   var nx = c.redSqr().redISub(t1.redAdd(t1)); | 
|   var t2 = t1.redISub(nx); | 
|   | 
|   var jyd8 = jy2.redSqr(); | 
|   jyd8 = jyd8.redIAdd(jyd8); | 
|   jyd8 = jyd8.redIAdd(jyd8); | 
|   jyd8 = jyd8.redIAdd(jyd8); | 
|   var ny = c.redMul(t2).redISub(jyd8); | 
|   var nz = jy.redAdd(jy).redMul(jz); | 
|   | 
|   return this.curve.jpoint(nx, ny, nz); | 
| }; | 
|   | 
| JPoint.prototype.trpl = function trpl() { | 
|   if (!this.curve.zeroA) | 
|     return this.dbl().add(this); | 
|   | 
|   // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl | 
|   // 5M + 10S + ... | 
|   | 
|   // XX = X1^2 | 
|   var xx = this.x.redSqr(); | 
|   // YY = Y1^2 | 
|   var yy = this.y.redSqr(); | 
|   // ZZ = Z1^2 | 
|   var zz = this.z.redSqr(); | 
|   // YYYY = YY^2 | 
|   var yyyy = yy.redSqr(); | 
|   // M = 3 * XX + a * ZZ2; a = 0 | 
|   var m = xx.redAdd(xx).redIAdd(xx); | 
|   // MM = M^2 | 
|   var mm = m.redSqr(); | 
|   // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM | 
|   var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); | 
|   e = e.redIAdd(e); | 
|   e = e.redAdd(e).redIAdd(e); | 
|   e = e.redISub(mm); | 
|   // EE = E^2 | 
|   var ee = e.redSqr(); | 
|   // T = 16*YYYY | 
|   var t = yyyy.redIAdd(yyyy); | 
|   t = t.redIAdd(t); | 
|   t = t.redIAdd(t); | 
|   t = t.redIAdd(t); | 
|   // U = (M + E)^2 - MM - EE - T | 
|   var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t); | 
|   // X3 = 4 * (X1 * EE - 4 * YY * U) | 
|   var yyu4 = yy.redMul(u); | 
|   yyu4 = yyu4.redIAdd(yyu4); | 
|   yyu4 = yyu4.redIAdd(yyu4); | 
|   var nx = this.x.redMul(ee).redISub(yyu4); | 
|   nx = nx.redIAdd(nx); | 
|   nx = nx.redIAdd(nx); | 
|   // Y3 = 8 * Y1 * (U * (T - U) - E * EE) | 
|   var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee))); | 
|   ny = ny.redIAdd(ny); | 
|   ny = ny.redIAdd(ny); | 
|   ny = ny.redIAdd(ny); | 
|   // Z3 = (Z1 + E)^2 - ZZ - EE | 
|   var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee); | 
|   | 
|   return this.curve.jpoint(nx, ny, nz); | 
| }; | 
|   | 
| JPoint.prototype.mul = function mul(k, kbase) { | 
|   k = new BN(k, kbase); | 
|   | 
|   return this.curve._wnafMul(this, k); | 
| }; | 
|   | 
| JPoint.prototype.eq = function eq(p) { | 
|   if (p.type === 'affine') | 
|     return this.eq(p.toJ()); | 
|   | 
|   if (this === p) | 
|     return true; | 
|   | 
|   // x1 * z2^2 == x2 * z1^2 | 
|   var z2 = this.z.redSqr(); | 
|   var pz2 = p.z.redSqr(); | 
|   if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0) | 
|     return false; | 
|   | 
|   // y1 * z2^3 == y2 * z1^3 | 
|   var z3 = z2.redMul(this.z); | 
|   var pz3 = pz2.redMul(p.z); | 
|   return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0; | 
| }; | 
|   | 
| JPoint.prototype.eqXToP = function eqXToP(x) { | 
|   var zs = this.z.redSqr(); | 
|   var rx = x.toRed(this.curve.red).redMul(zs); | 
|   if (this.x.cmp(rx) === 0) | 
|     return true; | 
|   | 
|   var xc = x.clone(); | 
|   var t = this.curve.redN.redMul(zs); | 
|   for (;;) { | 
|     xc.iadd(this.curve.n); | 
|     if (xc.cmp(this.curve.p) >= 0) | 
|       return false; | 
|   | 
|     rx.redIAdd(t); | 
|     if (this.x.cmp(rx) === 0) | 
|       return true; | 
|   } | 
| }; | 
|   | 
| JPoint.prototype.inspect = function inspect() { | 
|   if (this.isInfinity()) | 
|     return '<EC JPoint Infinity>'; | 
|   return '<EC JPoint x: ' + this.x.toString(16, 2) + | 
|       ' y: ' + this.y.toString(16, 2) + | 
|       ' z: ' + this.z.toString(16, 2) + '>'; | 
| }; | 
|   | 
| JPoint.prototype.isInfinity = function isInfinity() { | 
|   // XXX This code assumes that zero is always zero in red | 
|   return this.z.cmpn(0) === 0; | 
| }; |