react / wstein / node_modules / browserify / node_modules / crypto-browserify / node_modules / browserify-sign / node_modules / elliptic / lib / elliptic / curve / edwards.js
80621 views'use strict';12var curve = require('../curve');3var elliptic = require('../../elliptic');4var bn = require('bn.js');5var inherits = require('inherits');6var Base = curve.base;78var assert = elliptic.utils.assert;910function EdwardsCurve(conf) {11// NOTE: Important as we are creating point in Base.call()12this.twisted = (conf.a | 0) !== 1;13this.mOneA = this.twisted && (conf.a | 0) === -1;14this.extended = this.mOneA;1516Base.call(this, 'edwards', conf);1718this.a = new bn(conf.a, 16).mod(this.red.m).toRed(this.red);19this.c = new bn(conf.c, 16).toRed(this.red);20this.c2 = this.c.redSqr();21this.d = new bn(conf.d, 16).toRed(this.red);22this.dd = this.d.redAdd(this.d);2324assert(!this.twisted || this.c.fromRed().cmpn(1) === 0);25this.oneC = (conf.c | 0) === 1;26}27inherits(EdwardsCurve, Base);28module.exports = EdwardsCurve;2930EdwardsCurve.prototype._mulA = function _mulA(num) {31if (this.mOneA)32return num.redNeg();33else34return this.a.redMul(num);35};3637EdwardsCurve.prototype._mulC = function _mulC(num) {38if (this.oneC)39return num;40else41return this.c.redMul(num);42};4344// Just for compatibility with Short curve45EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) {46return this.point(x, y, z, t);47};4849EdwardsCurve.prototype.pointFromX = function pointFromX(odd, x) {50x = new bn(x, 16);51if (!x.red)52x = x.toRed(this.red);5354var x2 = x.redSqr();55var rhs = this.c2.redSub(this.a.redMul(x2));56var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2));5758var y = rhs.redMul(lhs.redInvm()).redSqrt();59var isOdd = y.fromRed().isOdd();60if (odd && !isOdd || !odd && isOdd)61y = y.redNeg();6263return this.point(x, y, curve.one);64};6566EdwardsCurve.prototype.validate = function validate(point) {67if (point.isInfinity())68return true;6970// Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2)71point.normalize();7273var x2 = point.x.redSqr();74var y2 = point.y.redSqr();75var lhs = x2.redMul(this.a).redAdd(y2);76var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2)));7778return lhs.cmp(rhs) === 0;79};8081function Point(curve, x, y, z, t) {82Base.BasePoint.call(this, curve, 'projective');83if (x === null && y === null && z === null) {84this.x = this.curve.zero;85this.y = this.curve.one;86this.z = this.curve.one;87this.t = this.curve.zero;88this.zOne = true;89} else {90this.x = new bn(x, 16);91this.y = new bn(y, 16);92this.z = z ? new bn(z, 16) : this.curve.one;93this.t = t && new bn(t, 16);94if (!this.x.red)95this.x = this.x.toRed(this.curve.red);96if (!this.y.red)97this.y = this.y.toRed(this.curve.red);98if (!this.z.red)99this.z = this.z.toRed(this.curve.red);100if (this.t && !this.t.red)101this.t = this.t.toRed(this.curve.red);102this.zOne = this.z === this.curve.one;103104// Use extended coordinates105if (this.curve.extended && !this.t) {106this.t = this.x.redMul(this.y);107if (!this.zOne)108this.t = this.t.redMul(this.z.redInvm());109}110}111}112inherits(Point, Base.BasePoint);113114EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) {115return Point.fromJSON(this, obj);116};117118EdwardsCurve.prototype.point = function point(x, y, z, t) {119return new Point(this, x, y, z, t);120};121122Point.fromJSON = function fromJSON(curve, obj) {123return new Point(curve, obj[0], obj[1], obj[2]);124};125126Point.prototype.inspect = function inspect() {127if (this.isInfinity())128return '<EC Point Infinity>';129return '<EC Point x: ' + this.x.fromRed().toString(16, 2) +130' y: ' + this.y.fromRed().toString(16, 2) +131' z: ' + this.z.fromRed().toString(16, 2) + '>';132};133134Point.prototype.isInfinity = function isInfinity() {135// XXX This code assumes that zero is always zero in red136return this.x.cmpn(0) === 0 &&137this.y.cmp(this.z) === 0;138};139140Point.prototype._extDbl = function _extDbl() {141// hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html142// #doubling-dbl-2008-hwcd143// 4M + 4S144145// A = X1^2146var a = this.x.redSqr();147// B = Y1^2148var b = this.y.redSqr();149// C = 2 * Z1^2150var c = this.z.redSqr();151c = c.redIAdd(c);152// D = a * A153var d = this.curve._mulA(a);154// E = (X1 + Y1)^2 - A - B155var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b);156// G = D + B157var g = d.redAdd(b);158// F = G - C159var f = g.redSub(c);160// H = D - B161var h = d.redSub(b);162// X3 = E * F163var nx = e.redMul(f);164// Y3 = G * H165var ny = g.redMul(h);166// T3 = E * H167var nt = e.redMul(h);168// Z3 = F * G169var nz = f.redMul(g);170return this.curve.point(nx, ny, nz, nt);171};172173Point.prototype._projDbl = function _projDbl() {174// hyperelliptic.org/EFD/g1p/auto-twisted-projective.html175// #doubling-dbl-2008-bbjlp176// #doubling-dbl-2007-bl177// and others178// Generally 3M + 4S or 2M + 4S179180// B = (X1 + Y1)^2181var b = this.x.redAdd(this.y).redSqr();182// C = X1^2183var c = this.x.redSqr();184// D = Y1^2185var d = this.y.redSqr();186187var nx;188var ny;189var nz;190if (this.curve.twisted) {191// E = a * C192var e = this.curve._mulA(c);193// F = E + D194var f = e.redAdd(d);195if (this.zOne) {196// X3 = (B - C - D) * (F - 2)197nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two));198// Y3 = F * (E - D)199ny = f.redMul(e.redSub(d));200// Z3 = F^2 - 2 * F201nz = f.redSqr().redSub(f).redSub(f);202} else {203// H = Z1^2204var h = this.z.redSqr();205// J = F - 2 * H206var j = f.redSub(h).redISub(h);207// X3 = (B-C-D)*J208nx = b.redSub(c).redISub(d).redMul(j);209// Y3 = F * (E - D)210ny = f.redMul(e.redSub(d));211// Z3 = F * J212nz = f.redMul(j);213}214} else {215// E = C + D216var e = c.redAdd(d);217// H = (c * Z1)^2218var h = this.curve._mulC(this.c.redMul(this.z)).redSqr();219// J = E - 2 * H220var j = e.redSub(h).redSub(h);221// X3 = c * (B - E) * J222nx = this.curve._mulC(b.redISub(e)).redMul(j);223// Y3 = c * E * (C - D)224ny = this.curve._mulC(e).redMul(c.redISub(d));225// Z3 = E * J226nz = e.redMul(j);227}228return this.curve.point(nx, ny, nz);229};230231Point.prototype.dbl = function dbl() {232if (this.isInfinity())233return this;234235// Double in extended coordinates236if (this.curve.extended)237return this._extDbl();238else239return this._projDbl();240};241242Point.prototype._extAdd = function _extAdd(p) {243// hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html244// #addition-add-2008-hwcd-3245// 8M246247// A = (Y1 - X1) * (Y2 - X2)248var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x));249// B = (Y1 + X1) * (Y2 + X2)250var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x));251// C = T1 * k * T2252var c = this.t.redMul(this.curve.dd).redMul(p.t);253// D = Z1 * 2 * Z2254var d = this.z.redMul(p.z.redAdd(p.z));255// E = B - A256var e = b.redSub(a);257// F = D - C258var f = d.redSub(c);259// G = D + C260var g = d.redAdd(c);261// H = B + A262var h = b.redAdd(a);263// X3 = E * F264var nx = e.redMul(f);265// Y3 = G * H266var ny = g.redMul(h);267// T3 = E * H268var nt = e.redMul(h);269// Z3 = F * G270var nz = f.redMul(g);271return this.curve.point(nx, ny, nz, nt);272};273274Point.prototype._projAdd = function _projAdd(p) {275// hyperelliptic.org/EFD/g1p/auto-twisted-projective.html276// #addition-add-2008-bbjlp277// #addition-add-2007-bl278// 10M + 1S279280// A = Z1 * Z2281var a = this.z.redMul(p.z);282// B = A^2283var b = a.redSqr();284// C = X1 * X2285var c = this.x.redMul(p.x);286// D = Y1 * Y2287var d = this.y.redMul(p.y);288// E = d * C * D289var e = this.curve.d.redMul(c).redMul(d);290// F = B - E291var f = b.redSub(e);292// G = B + E293var g = b.redAdd(e);294// X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D)295var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d);296var nx = a.redMul(f).redMul(tmp);297var ny;298var nz;299if (this.curve.twisted) {300// Y3 = A * G * (D - a * C)301ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c)));302// Z3 = F * G303nz = f.redMul(g);304} else {305// Y3 = A * G * (D - C)306ny = a.redMul(g).redMul(d.redSub(c));307// Z3 = c * F * G308nz = this.curve._mulC(f).redMul(g);309}310return this.curve.point(nx, ny, nz);311};312313Point.prototype.add = function add(p) {314if (this.isInfinity())315return p;316if (p.isInfinity())317return this;318319if (this.curve.extended)320return this._extAdd(p);321else322return this._projAdd(p);323};324325Point.prototype.mul = function mul(k) {326if (this.precomputed && this.precomputed.doubles)327return this.curve._fixedNafMul(this, k);328else329return this.curve._wnafMul(this, k);330};331332Point.prototype.mulAdd = function mulAdd(k1, p, k2) {333return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2);334};335336Point.prototype.normalize = function normalize() {337if (this.zOne)338return this;339340// Normalize coordinates341var zi = this.z.redInvm();342this.x = this.x.redMul(zi);343this.y = this.y.redMul(zi);344if (this.t)345this.t = this.t.redMul(zi);346this.z = this.curve.one;347this.zOne = true;348return this;349};350351Point.prototype.neg = function neg() {352return this.curve.point(this.x.redNeg(),353this.y,354this.z,355this.t && this.t.redNeg());356};357358Point.prototype.getX = function getX() {359this.normalize();360return this.x.fromRed();361};362363Point.prototype.getY = function getY() {364this.normalize();365return this.y.fromRed();366};367368// Compatibility with BaseCurve369Point.prototype.toP = Point.prototype.normalize;370Point.prototype.mixedAdd = Point.prototype.add;371372373