Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80621 views
1
'use strict';
2
3
var curve = require('../curve');
4
var bn = require('bn.js');
5
var inherits = require('inherits');
6
var Base = curve.base;
7
8
function MontCurve(conf) {
9
Base.call(this, 'mont', conf);
10
11
this.a = new bn(conf.a, 16).toRed(this.red);
12
this.b = new bn(conf.b, 16).toRed(this.red);
13
this.i4 = new bn(4).toRed(this.red).redInvm();
14
this.two = new bn(2).toRed(this.red);
15
this.a24 = this.i4.redMul(this.a.redAdd(this.two));
16
}
17
inherits(MontCurve, Base);
18
module.exports = MontCurve;
19
20
MontCurve.prototype.validate = function validate(point) {
21
var x = point.normalize().x;
22
var x2 = x.redSqr();
23
var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x);
24
var y = rhs.redSqrt();
25
26
return y.redSqr().cmp(rhs) === 0;
27
};
28
29
function Point(curve, x, z) {
30
Base.BasePoint.call(this, curve, 'projective');
31
if (x === null && z === null) {
32
this.x = this.curve.one;
33
this.z = this.curve.zero;
34
} else {
35
this.x = new bn(x, 16);
36
this.z = new bn(z, 16);
37
if (!this.x.red)
38
this.x = this.x.toRed(this.curve.red);
39
if (!this.z.red)
40
this.z = this.z.toRed(this.curve.red);
41
}
42
}
43
inherits(Point, Base.BasePoint);
44
45
MontCurve.prototype.point = function point(x, z) {
46
return new Point(this, x, z);
47
};
48
49
MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) {
50
return Point.fromJSON(this, obj);
51
};
52
53
Point.prototype.precompute = function precompute() {
54
// No-op
55
};
56
57
Point.fromJSON = function fromJSON(curve, obj) {
58
return new Point(curve, obj[0], obj[1] || curve.one);
59
};
60
61
Point.prototype.inspect = function inspect() {
62
if (this.isInfinity())
63
return '<EC Point Infinity>';
64
return '<EC Point x: ' + this.x.fromRed().toString(16, 2) +
65
' z: ' + this.z.fromRed().toString(16, 2) + '>';
66
};
67
68
Point.prototype.isInfinity = function isInfinity() {
69
// XXX This code assumes that zero is always zero in red
70
return this.z.cmpn(0) === 0;
71
};
72
73
Point.prototype.dbl = function dbl() {
74
// http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3
75
// 2M + 2S + 4A
76
77
// A = X1 + Z1
78
var a = this.x.redAdd(this.z);
79
// AA = A^2
80
var aa = a.redSqr();
81
// B = X1 - Z1
82
var b = this.x.redSub(this.z);
83
// BB = B^2
84
var bb = b.redSqr();
85
// C = AA - BB
86
var c = aa.redSub(bb);
87
// X3 = AA * BB
88
var nx = aa.redMul(bb);
89
// Z3 = C * (BB + A24 * C)
90
var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c)));
91
return this.curve.point(nx, nz);
92
};
93
94
Point.prototype.add = function add() {
95
throw new Error('Not supported on Montgomery curve');
96
};
97
98
Point.prototype.diffAdd = function diffAdd(p, diff) {
99
// http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3
100
// 4M + 2S + 6A
101
102
// A = X2 + Z2
103
var a = this.x.redAdd(this.z);
104
// B = X2 - Z2
105
var b = this.x.redSub(this.z);
106
// C = X3 + Z3
107
var c = p.x.redAdd(p.z);
108
// D = X3 - Z3
109
var d = p.x.redSub(p.z);
110
// DA = D * A
111
var da = d.redMul(a);
112
// CB = C * B
113
var cb = c.redMul(b);
114
// X5 = Z1 * (DA + CB)^2
115
var nx = diff.z.redMul(da.redAdd(cb).redSqr());
116
// Z5 = X1 * (DA - CB)^2
117
var nz = diff.x.redMul(da.redISub(cb).redSqr());
118
return this.curve.point(nx, nz);
119
};
120
121
Point.prototype.mul = function mul(k) {
122
var t = k.clone();
123
var a = this; // (N / 2) * Q + Q
124
var b = this.curve.point(null, null); // (N / 2) * Q
125
var c = this; // Q
126
127
for (var bits = []; t.cmpn(0) !== 0; t.ishrn(1))
128
bits.push(t.andln(1));
129
130
for (var i = bits.length - 1; i >= 0; i--) {
131
if (bits[i] === 0) {
132
// N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q
133
a = a.diffAdd(b, c);
134
// N * Q = 2 * ((N / 2) * Q + Q))
135
b = b.dbl();
136
} else {
137
// N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q)
138
b = a.diffAdd(b, c);
139
// N * Q + Q = 2 * ((N / 2) * Q + Q)
140
a = a.dbl();
141
}
142
}
143
return b;
144
};
145
146
Point.prototype.mulAdd = function mulAdd() {
147
throw new Error('Not supported on Montgomery curve');
148
};
149
150
Point.prototype.normalize = function normalize() {
151
this.x = this.x.redMul(this.z.redInvm());
152
this.z = this.curve.one;
153
return this;
154
};
155
156
Point.prototype.getX = function getX() {
157
// Normalize coordinates
158
this.normalize();
159
160
return this.x.fromRed();
161
};
162
163