react / wstein / node_modules / browserify / node_modules / crypto-browserify / node_modules / create-ecdh / node_modules / elliptic / lib / elliptic / curve / base.js
80621 views'use strict';12var bn = require('bn.js');3var elliptic = require('../../elliptic');45var getNAF = elliptic.utils.getNAF;6var getJSF = elliptic.utils.getJSF;7var assert = elliptic.utils.assert;89function BaseCurve(type, conf) {10this.type = type;11this.p = new bn(conf.p, 16);1213// Use Montgomery, when there is no fast reduction for the prime14this.red = conf.prime ? bn.red(conf.prime) : bn.mont(this.p);1516// Useful for many curves17this.zero = new bn(0).toRed(this.red);18this.one = new bn(1).toRed(this.red);19this.two = new bn(2).toRed(this.red);2021// Curve configuration, optional22this.n = conf.n && new bn(conf.n, 16);23this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed);2425// Temporary arrays26this._wnafT1 = new Array(4);27this._wnafT2 = new Array(4);28this._wnafT3 = new Array(4);29this._wnafT4 = new Array(4);30}31module.exports = BaseCurve;3233BaseCurve.prototype.point = function point() {34throw new Error('Not implemented');35};3637BaseCurve.prototype.validate = function validate() {38throw new Error('Not implemented');39};4041BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) {42var doubles = p._getDoubles();4344var naf = getNAF(k, 1);45var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1);46I /= 3;4748// Translate into more windowed form49var repr = [];50for (var j = 0; j < naf.length; j += doubles.step) {51var nafW = 0;52for (var k = j + doubles.step - 1; k >= j; k--)53nafW = (nafW << 1) + naf[k];54repr.push(nafW);55}5657var a = this.jpoint(null, null, null);58var b = this.jpoint(null, null, null);59for (var i = I; i > 0; i--) {60for (var j = 0; j < repr.length; j++) {61var nafW = repr[j];62if (nafW === i)63b = b.mixedAdd(doubles.points[j]);64else if (nafW === -i)65b = b.mixedAdd(doubles.points[j].neg());66}67a = a.add(b);68}69return a.toP();70};7172BaseCurve.prototype._wnafMul = function _wnafMul(p, k) {73var w = 4;7475// Precompute window76var nafPoints = p._getNAFPoints(w);77w = nafPoints.wnd;78var wnd = nafPoints.points;7980// Get NAF form81var naf = getNAF(k, w);8283// Add `this`*(N+1) for every w-NAF index84var acc = this.jpoint(null, null, null);85for (var i = naf.length - 1; i >= 0; i--) {86// Count zeroes87for (var k = 0; i >= 0 && naf[i] === 0; i--)88k++;89if (i >= 0)90k++;91acc = acc.dblp(k);9293if (i < 0)94break;95var z = naf[i];96assert(z !== 0);97if (p.type === 'affine') {98// J +- P99if (z > 0)100acc = acc.mixedAdd(wnd[(z - 1) >> 1]);101else102acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg());103} else {104// J +- J105if (z > 0)106acc = acc.add(wnd[(z - 1) >> 1]);107else108acc = acc.add(wnd[(-z - 1) >> 1].neg());109}110}111return p.type === 'affine' ? acc.toP() : acc;112};113114BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW,115points,116coeffs,117len) {118var wndWidth = this._wnafT1;119var wnd = this._wnafT2;120var naf = this._wnafT3;121122// Fill all arrays123var max = 0;124for (var i = 0; i < len; i++) {125var p = points[i];126var nafPoints = p._getNAFPoints(defW);127wndWidth[i] = nafPoints.wnd;128wnd[i] = nafPoints.points;129}130131// Comb small window NAFs132for (var i = len - 1; i >= 1; i -= 2) {133var a = i - 1;134var b = i;135if (wndWidth[a] !== 1 || wndWidth[b] !== 1) {136naf[a] = getNAF(coeffs[a], wndWidth[a]);137naf[b] = getNAF(coeffs[b], wndWidth[b]);138max = Math.max(naf[a].length, max);139max = Math.max(naf[b].length, max);140continue;141}142143var comb = [144points[a], /* 1 */145null, /* 3 */146null, /* 5 */147points[b] /* 7 */148];149150// Try to avoid Projective points, if possible151if (points[a].y.cmp(points[b].y) === 0) {152comb[1] = points[a].add(points[b]);153comb[2] = points[a].toJ().mixedAdd(points[b].neg());154} else if (points[a].y.cmp(points[b].y.redNeg()) === 0) {155comb[1] = points[a].toJ().mixedAdd(points[b]);156comb[2] = points[a].add(points[b].neg());157} else {158comb[1] = points[a].toJ().mixedAdd(points[b]);159comb[2] = points[a].toJ().mixedAdd(points[b].neg());160}161162var index = [163-3, /* -1 -1 */164-1, /* -1 0 */165-5, /* -1 1 */166-7, /* 0 -1 */1670, /* 0 0 */1687, /* 0 1 */1695, /* 1 -1 */1701, /* 1 0 */1713 /* 1 1 */172];173174var jsf = getJSF(coeffs[a], coeffs[b]);175max = Math.max(jsf[0].length, max);176naf[a] = new Array(max);177naf[b] = new Array(max);178for (var j = 0; j < max; j++) {179var ja = jsf[0][j] | 0;180var jb = jsf[1][j] | 0;181182naf[a][j] = index[(ja + 1) * 3 + (jb + 1)];183naf[b][j] = 0;184wnd[a] = comb;185}186}187188var acc = this.jpoint(null, null, null);189var tmp = this._wnafT4;190for (var i = max; i >= 0; i--) {191var k = 0;192193while (i >= 0) {194var zero = true;195for (var j = 0; j < len; j++) {196tmp[j] = naf[j][i] | 0;197if (tmp[j] !== 0)198zero = false;199}200if (!zero)201break;202k++;203i--;204}205if (i >= 0)206k++;207acc = acc.dblp(k);208if (i < 0)209break;210211for (var j = 0; j < len; j++) {212var z = tmp[j];213var p;214if (z === 0)215continue;216else if (z > 0)217p = wnd[j][(z - 1) >> 1];218else if (z < 0)219p = wnd[j][(-z - 1) >> 1].neg();220221if (p.type === 'affine')222acc = acc.mixedAdd(p);223else224acc = acc.add(p);225}226}227// Zeroify references228for (var i = 0; i < len; i++)229wnd[i] = null;230return acc.toP();231};232233function BasePoint(curve, type) {234this.curve = curve;235this.type = type;236this.precomputed = null;237}238BaseCurve.BasePoint = BasePoint;239240BasePoint.prototype.validate = function validate() {241return this.curve.validate(this);242};243244BasePoint.prototype.precompute = function precompute(power) {245if (this.precomputed)246return this;247248var precomputed = {249doubles: null,250naf: null,251beta: null252};253precomputed.naf = this._getNAFPoints(8);254precomputed.doubles = this._getDoubles(4, power);255precomputed.beta = this._getBeta();256this.precomputed = precomputed;257258return this;259};260261BasePoint.prototype._getDoubles = function _getDoubles(step, power) {262if (this.precomputed && this.precomputed.doubles)263return this.precomputed.doubles;264265var doubles = [ this ];266var acc = this;267for (var i = 0; i < power; i += step) {268for (var j = 0; j < step; j++)269acc = acc.dbl();270doubles.push(acc);271}272return {273step: step,274points: doubles275};276};277278BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) {279if (this.precomputed && this.precomputed.naf)280return this.precomputed.naf;281282var res = [ this ];283var max = (1 << wnd) - 1;284var dbl = max === 1 ? null : this.dbl();285for (var i = 1; i < max; i++)286res[i] = res[i - 1].add(dbl);287return {288wnd: wnd,289points: res290};291};292293BasePoint.prototype._getBeta = function _getBeta() {294return null;295};296297BasePoint.prototype.dblp = function dblp(k) {298var r = this;299for (var i = 0; i < k; i++)300r = r.dbl();301return r;302};303304305