finitefields 0.0.9 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ellipticcurves.ts +130 -9
- package/main.ts +25 -9
- package/package.json +1 -1
package/ellipticcurves.ts
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import
|
|
11
|
-
import { just, nothing, type Maybe, type Nothing } from './maybe.js';
|
|
10
|
+
import { PrimeField, type GF } from './galois.js';
|
|
11
|
+
import { empty, fold, just, nothing, type Maybe, type Nothing } from './maybe.js';
|
|
12
12
|
import { Util } from './galois.js';
|
|
13
13
|
|
|
14
14
|
let 𝒪:Nothing;
|
|
@@ -28,6 +28,7 @@ fail = (...args:any[]): never => {
|
|
|
28
28
|
p256 = ():ECCurve => ({
|
|
29
29
|
'#E': 0xffffffff00000000_ffffffffffffffff_bce6faada7179e84_f3b9cac2fc632551n,
|
|
30
30
|
'θ': 0xffffffff00000001_0000000000000000_00000000ffffffff_ffffffffffffffffn,
|
|
31
|
+
'a': -3n,
|
|
31
32
|
'b': 0x5ac635d8aa3a93e7_b3ebbd55769886bc_651d06b0cc53b0f6_3bce3c3e27d2604bn,
|
|
32
33
|
'p':
|
|
33
34
|
[
|
|
@@ -51,6 +52,7 @@ type Tuple<a> = readonly [a,a];
|
|
|
51
52
|
type Coordinate = Maybe<Point>;
|
|
52
53
|
type infinity = false | true;
|
|
53
54
|
type ECformula = (a:bigint,b:bigint,f:GF)=>Function;
|
|
55
|
+
type Slope = bigint;
|
|
54
56
|
|
|
55
57
|
interface Tuples {
|
|
56
58
|
'p': Tuple<bigint>;
|
|
@@ -59,6 +61,7 @@ interface Tuples {
|
|
|
59
61
|
|
|
60
62
|
interface IECCurve {
|
|
61
63
|
'θ': bigint;
|
|
64
|
+
'a': bigint;
|
|
62
65
|
'b': bigint;
|
|
63
66
|
bitlen: bigint;
|
|
64
67
|
formula: ECformula;
|
|
@@ -72,6 +75,8 @@ interface Iellipticcurves<a> {
|
|
|
72
75
|
constructor:Function;
|
|
73
76
|
add:(a:Coordinate,b:Coordinate)=>Coordinate;
|
|
74
77
|
double:(a:Coordinate)=>Coordinate;
|
|
78
|
+
get p(): Coordinate;
|
|
79
|
+
get q(): Coordinate;
|
|
75
80
|
}
|
|
76
81
|
|
|
77
82
|
interface Icurve extends IECCurve {
|
|
@@ -113,6 +118,7 @@ class Point implements Ipoint {
|
|
|
113
118
|
class Curve<a> implements Icurve {
|
|
114
119
|
#E: bigint;
|
|
115
120
|
public θ: bigint;
|
|
121
|
+
public a: bigint;
|
|
116
122
|
public b: bigint;
|
|
117
123
|
public p: Point;
|
|
118
124
|
public q: Point;
|
|
@@ -127,6 +133,8 @@ class Curve<a> implements Icurve {
|
|
|
127
133
|
|| fail(m);
|
|
128
134
|
this.θ = curve.θ
|
|
129
135
|
|| fail(m);
|
|
136
|
+
this.a = curve.a
|
|
137
|
+
|| fail(m);
|
|
130
138
|
this.b = curve.b
|
|
131
139
|
|| fail(m);
|
|
132
140
|
this.bitlen = curve.bitlen
|
|
@@ -140,24 +148,113 @@ class Curve<a> implements Icurve {
|
|
|
140
148
|
}
|
|
141
149
|
}
|
|
142
150
|
|
|
143
|
-
abstract class EllipticCurves<a> implements Iellipticcurves<a> {
|
|
151
|
+
abstract class EllipticCurves<a extends GF> implements Iellipticcurves<a> {
|
|
144
152
|
public abstract backend: a;
|
|
145
153
|
private curve: Curve<a>;
|
|
146
154
|
|
|
147
|
-
|
|
148
|
-
return
|
|
155
|
+
private eq(p:Point,q:Point): boolean {
|
|
156
|
+
return (
|
|
157
|
+
(!p || !q) ?
|
|
158
|
+
fail() :
|
|
159
|
+
(p['∞'] && q['∞']) ?
|
|
160
|
+
true :
|
|
161
|
+
(p['∞'] && !q['∞']) ?
|
|
162
|
+
false :
|
|
163
|
+
(!p['∞'] && q['∞']) ?
|
|
164
|
+
false :
|
|
165
|
+
((p.x === q.x) && (p.y === q.y))
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private isprimefield(f:GF): f is PrimeField {
|
|
170
|
+
return (f instanceof PrimeField);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private slope(p_:Point,q_:Point): (a:bigint,p:bigint)=>bigint {
|
|
174
|
+
let f:a;
|
|
175
|
+
const { x:x1,y:y1 } = p_;
|
|
176
|
+
const { x:x2,y:y2 } = q_;
|
|
177
|
+
|
|
178
|
+
if (!this.isprimefield(this.backend))
|
|
179
|
+
return fail();
|
|
180
|
+
else
|
|
181
|
+
f = this.backend;
|
|
182
|
+
|
|
183
|
+
return (this.eq(p_,q_)) ?
|
|
184
|
+
(a:bigint,p:bigint): bigint =>
|
|
185
|
+
(f.mul(
|
|
186
|
+
f.add(a,
|
|
187
|
+
f.mul(3n, f.exp(x1, 2n))
|
|
188
|
+
),
|
|
189
|
+
f.inv(f.mul(y1, 2n))
|
|
190
|
+
) % p) :
|
|
191
|
+
(a:bigint,p:bigint): bigint =>
|
|
192
|
+
(f.mul(
|
|
193
|
+
f.sub(y2, y1),
|
|
194
|
+
f.inv(f.sub(x2, x1))
|
|
195
|
+
) % p);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private isinfinity(p:Point): infinity {
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
protected addpoints(p:Coordinate,q:Coordinate): Coordinate {
|
|
203
|
+
let s:Slope;
|
|
204
|
+
let p_:Point;
|
|
205
|
+
let q_:Point;
|
|
206
|
+
let x:bigint;
|
|
207
|
+
let y:bigint;
|
|
208
|
+
let t:Point;
|
|
209
|
+
let mt:Coordinate;
|
|
210
|
+
let Δx:bigint, Δy:bigint;
|
|
211
|
+
let f:a;
|
|
212
|
+
|
|
213
|
+
if (!this.isprimefield(this.backend))
|
|
214
|
+
return fail();
|
|
215
|
+
else
|
|
216
|
+
f = this.backend;
|
|
217
|
+
|
|
218
|
+
if (empty(p) && empty(q))
|
|
219
|
+
return <Maybe<Point>>nothing();
|
|
220
|
+
else if (empty(p))
|
|
221
|
+
return <Maybe<Point>>just(q as unknown as Point);
|
|
222
|
+
else if (empty(q))
|
|
223
|
+
return <Maybe<Point>>just(p as unknown as Point);
|
|
224
|
+
else
|
|
225
|
+
[p_, q_] = [fold(p), fold(q)];
|
|
226
|
+
|
|
227
|
+
const { x:x1,y:y1 } = p_;
|
|
228
|
+
const { x:x2,y:y2 } = q_;
|
|
229
|
+
|
|
230
|
+
s = this.slope(p_, q_)(this.curve.a, this.backend.p);
|
|
231
|
+
Δx = f.sub(x1, x2);
|
|
232
|
+
x = (f.sub(s, f.mul(s, s)) % this.backend.p);
|
|
233
|
+
Δy = f.sub(x1, x);
|
|
234
|
+
y = (f.sub(
|
|
235
|
+
f.mul(s, Δy),
|
|
236
|
+
y1
|
|
237
|
+
) % this.backend.p);
|
|
238
|
+
|
|
239
|
+
t = new Point([x,y]);
|
|
240
|
+
if (this.isinfinity(t))
|
|
241
|
+
mt = nothing();
|
|
242
|
+
else
|
|
243
|
+
mt = just(t);
|
|
244
|
+
|
|
245
|
+
return mt;
|
|
149
246
|
}
|
|
150
247
|
|
|
151
248
|
protected doublepoint(a:Coordinate): Coordinate {
|
|
152
|
-
return a;
|
|
249
|
+
return this.add(a, a);
|
|
153
250
|
}
|
|
154
251
|
|
|
155
252
|
public add(a:Coordinate,b:Coordinate): Coordinate {
|
|
156
|
-
if ((a
|
|
253
|
+
if (empty(a) && empty(b))
|
|
157
254
|
return <Maybe<Point>>nothing();
|
|
158
|
-
else if (a
|
|
255
|
+
else if (empty(a))
|
|
159
256
|
return <Maybe<Point>>just(b as unknown as Point);
|
|
160
|
-
else if (b
|
|
257
|
+
else if (empty(b))
|
|
161
258
|
return <Maybe<Point>>just(a as unknown as Point);
|
|
162
259
|
else
|
|
163
260
|
return <Maybe<Point>>this.addpoints(a,b);
|
|
@@ -170,6 +267,29 @@ abstract class EllipticCurves<a> implements Iellipticcurves<a> {
|
|
|
170
267
|
return this.doublepoint(a);
|
|
171
268
|
}
|
|
172
269
|
|
|
270
|
+
public get p(): Coordinate {
|
|
271
|
+
let p:Point;
|
|
272
|
+
let mp:Coordinate;
|
|
273
|
+
|
|
274
|
+
p = this.curve.p;
|
|
275
|
+
mp = (p['∞']) ?
|
|
276
|
+
nothing() :
|
|
277
|
+
just(p);
|
|
278
|
+
|
|
279
|
+
return mp;
|
|
280
|
+
}
|
|
281
|
+
public get q(): Coordinate {
|
|
282
|
+
let q:Point;
|
|
283
|
+
let mq:Coordinate;
|
|
284
|
+
|
|
285
|
+
q = this.curve.q;
|
|
286
|
+
mq = (q['∞']) ?
|
|
287
|
+
nothing() :
|
|
288
|
+
just(q);
|
|
289
|
+
|
|
290
|
+
return mq;
|
|
291
|
+
}
|
|
292
|
+
|
|
173
293
|
constructor(curve:ECCurve) {
|
|
174
294
|
this.curve = new Curve<a>(curve);
|
|
175
295
|
|
|
@@ -191,3 +311,4 @@ class ecℤp extends EllipticCurves<PrimeField>
|
|
|
191
311
|
}
|
|
192
312
|
|
|
193
313
|
export { ecℤp, p256 };
|
|
314
|
+
export type { Point, Coordinate };
|
package/main.ts
CHANGED
|
@@ -1,23 +1,39 @@
|
|
|
1
1
|
/* main.ts */
|
|
2
2
|
import { Polynomial } from './polynomial.js';
|
|
3
3
|
import { Util,PrimeField } from './galois.js';
|
|
4
|
-
import { ecℤp, p256 } from './ellipticcurves.js';
|
|
4
|
+
import { ecℤp, p256, type Coordinate, type Point } from './ellipticcurves.js';
|
|
5
5
|
import { empty, fold, just, nothing } from './maybe.js';
|
|
6
6
|
import type { Maybe, Just, Nothing } from './maybe.js';
|
|
7
7
|
|
|
8
8
|
let log:(...x:any[])=>void;
|
|
9
9
|
log = console.log;
|
|
10
10
|
|
|
11
|
-
let
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
let field:PrimeField;
|
|
12
|
+
let curve:ecℤp;
|
|
13
|
+
let mp:Coordinate;
|
|
14
|
+
let p:Point;
|
|
15
|
+
let q:Point;
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
// let curve:ecℤp;
|
|
17
|
-
|
|
18
|
-
// field = new PrimeField(p256().θ, p256().bitlen);
|
|
17
|
+
field = new PrimeField(p256().θ, p256().bitlen);
|
|
19
18
|
// log(field);
|
|
20
|
-
|
|
19
|
+
curve = new ecℤp(field, p256());
|
|
21
20
|
// log(curve);
|
|
22
21
|
|
|
22
|
+
// mp = curve.add(curve.p, curve.q);
|
|
23
|
+
mp = curve.q;
|
|
24
|
+
q = fold(mp);
|
|
25
|
+
p = fold(curve.p);
|
|
26
|
+
do {
|
|
27
|
+
mp = curve.double(mp);
|
|
28
|
+
if (empty(mp)) {
|
|
29
|
+
log(mp);
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
p = fold(mp);
|
|
34
|
+
log(p);
|
|
35
|
+
}
|
|
36
|
+
} while (p.x !== q.x);
|
|
37
|
+
log(q);
|
|
38
|
+
|
|
23
39
|
export { Polynomial,Util,PrimeField,ecℤp,p256 };
|