finitefields 0.0.8 → 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 CHANGED
@@ -7,13 +7,16 @@
7
7
  *
8
8
  */
9
9
 
10
- import type { GF,PrimeField } from './galois.js';
10
+ import { PrimeField, type GF } from './galois.js';
11
+ import { empty, fold, just, nothing, type Maybe, type Nothing } from './maybe.js';
11
12
  import { Util } from './galois.js';
12
13
 
14
+ let 𝒪:Nothing;
13
15
  let log:(...x:any[])=>void;
14
16
  let fail:(...x:any[])=>never;
15
17
  let p256:()=>ECCurve;
16
18
 
19
+ 𝒪 = nothing();
17
20
  log = console.log;
18
21
  fail = (...args:any[]): never => {
19
22
  console.error(...args);
@@ -25,6 +28,7 @@ fail = (...args:any[]): never => {
25
28
  p256 = ():ECCurve => ({
26
29
  '#E': 0xffffffff00000000_ffffffffffffffff_bce6faada7179e84_f3b9cac2fc632551n,
27
30
  'θ': 0xffffffff00000001_0000000000000000_00000000ffffffff_ffffffffffffffffn,
31
+ 'a': -3n,
28
32
  'b': 0x5ac635d8aa3a93e7_b3ebbd55769886bc_651d06b0cc53b0f6_3bce3c3e27d2604bn,
29
33
  'p':
30
34
  [
@@ -45,8 +49,10 @@ p256 = ():ECCurve => ({
45
49
  });
46
50
 
47
51
  type Tuple<a> = readonly [a,a];
52
+ type Coordinate = Maybe<Point>;
48
53
  type infinity = false | true;
49
54
  type ECformula = (a:bigint,b:bigint,f:GF)=>Function;
55
+ type Slope = bigint;
50
56
 
51
57
  interface Tuples {
52
58
  'p': Tuple<bigint>;
@@ -55,6 +61,7 @@ interface Tuples {
55
61
 
56
62
  interface IECCurve {
57
63
  'θ': bigint;
64
+ 'a': bigint;
58
65
  'b': bigint;
59
66
  bitlen: bigint;
60
67
  formula: ECformula;
@@ -66,6 +73,10 @@ interface ECCurve extends IECCurve,Tuples,hashE {};
66
73
  interface Iellipticcurves<a> {
67
74
  backend: a;
68
75
  constructor:Function;
76
+ add:(a:Coordinate,b:Coordinate)=>Coordinate;
77
+ double:(a:Coordinate)=>Coordinate;
78
+ get p(): Coordinate;
79
+ get q(): Coordinate;
69
80
  }
70
81
 
71
82
  interface Icurve extends IECCurve {
@@ -107,6 +118,7 @@ class Point implements Ipoint {
107
118
  class Curve<a> implements Icurve {
108
119
  #E: bigint;
109
120
  public θ: bigint;
121
+ public a: bigint;
110
122
  public b: bigint;
111
123
  public p: Point;
112
124
  public q: Point;
@@ -121,6 +133,8 @@ class Curve<a> implements Icurve {
121
133
  || fail(m);
122
134
  this.θ = curve.θ
123
135
  || fail(m);
136
+ this.a = curve.a
137
+ || fail(m);
124
138
  this.b = curve.b
125
139
  || fail(m);
126
140
  this.bitlen = curve.bitlen
@@ -134,10 +148,148 @@ class Curve<a> implements Icurve {
134
148
  }
135
149
  }
136
150
 
137
- abstract class EllipticCurves<a> implements Iellipticcurves<a> {
151
+ abstract class EllipticCurves<a extends GF> implements Iellipticcurves<a> {
138
152
  public abstract backend: a;
139
153
  private curve: Curve<a>;
140
154
 
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;
246
+ }
247
+
248
+ protected doublepoint(a:Coordinate): Coordinate {
249
+ return this.add(a, a);
250
+ }
251
+
252
+ public add(a:Coordinate,b:Coordinate): Coordinate {
253
+ if (empty(a) && empty(b))
254
+ return <Maybe<Point>>nothing();
255
+ else if (empty(a))
256
+ return <Maybe<Point>>just(b as unknown as Point);
257
+ else if (empty(b))
258
+ return <Maybe<Point>>just(a as unknown as Point);
259
+ else
260
+ return <Maybe<Point>>this.addpoints(a,b);
261
+ }
262
+
263
+ public double(a:Coordinate): Coordinate {
264
+ if (a === 𝒪)
265
+ return nothing();
266
+ else
267
+ return this.doublepoint(a);
268
+ }
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
+
141
293
  constructor(curve:ECCurve) {
142
294
  this.curve = new Curve<a>(curve);
143
295
 
@@ -159,3 +311,4 @@ class ecℤp extends EllipticCurves<PrimeField>
159
311
  }
160
312
 
161
313
  export { ecℤp, p256 };
314
+ export type { Point, Coordinate };
package/galois.ts CHANGED
@@ -146,8 +146,8 @@ Util = {
146
146
  let a:bigint;
147
147
  let e:bigint;
148
148
 
149
- sign = (method==methods.SquareAndMultiply) ? '^' : 'x';
150
- log(`${a_}${sign}${e_} (mod ${p}) = `);
149
+ // sign = (method==methods.SquareAndMultiply) ? '^' : 'x';
150
+ // log(`${a_}${sign}${e_} (mod ${p}) = `);
151
151
 
152
152
  switch (method) {
153
153
  case methods.SquareAndMultiply:
@@ -161,10 +161,8 @@ Util = {
161
161
 
162
162
  case methods.DoubleAndAdd:
163
163
  sq = (y:bigint,p_:bigint):bigint =>
164
- // Util.binmethod(y,2n,p_,DoubleAndAdd)
165
164
  ((y+y)%p_)
166
165
  mul = (y:bigint,z:bigint,p_:bigint):bigint =>
167
- // Util.binmethod(y,z,p_,DoubleAndAdd)
168
166
  ((y+z)%p_);
169
167
  a=e_;
170
168
  e=a_;
@@ -184,18 +182,13 @@ Util = {
184
182
  .fill(false,0,Number(bitlen))
185
183
  .map((x:boolean,idx:number):boolean =>
186
184
  (((e>>n--)&1n)===1n) && (!!idx));
187
- // if (method === methods.DoubleAndAdd)
188
- bitstring.shift();
185
+ bitstring.shift();
189
186
  // log(bitstring.map((x:boolean):number => (x)?1:0));
190
187
  bitstring
191
188
  .forEach((x:boolean):void => {
192
- // val = (x) ?
193
- // mul(a,sq(val,p),p) :
194
- // sq(a,p);
195
189
  val = (x) ?
196
190
  mul(a,sq(val,p),p) :
197
191
  sq(val,p);
198
- // log(val);
199
192
 
200
193
  return void 0;
201
194
  });
package/main.ts CHANGED
@@ -1,17 +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
+ import { empty, fold, just, nothing } from './maybe.js';
6
+ import type { Maybe, Just, Nothing } from './maybe.js';
5
7
 
6
8
  let log:(...x:any[])=>void;
7
9
  log = console.log;
8
10
 
9
11
  let field:PrimeField;
10
12
  let curve:ecℤp;
13
+ let mp:Coordinate;
14
+ let p:Point;
15
+ let q:Point;
11
16
 
12
17
  field = new PrimeField(p256().θ, p256().bitlen);
13
- log(field);
18
+ // log(field);
14
19
  curve = new ecℤp(field, p256());
15
- log(curve);
20
+ // log(curve);
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);
16
38
 
17
39
  export { Polynomial,Util,PrimeField,ecℤp,p256 };
package/maybe.ts ADDED
@@ -0,0 +1,40 @@
1
+ /*
2
+ * maybe datatype
3
+ *
4
+ * finitefields package by @dr-Jonas-Birch
5
+ *
6
+ * 2026
7
+ *
8
+ */
9
+
10
+ let log:(...args:any[])=>void;
11
+ let fail:(...args:any[])=>never;
12
+
13
+ log = console.log;
14
+ fail = (...args:any[]): never => {
15
+ console.error(...args);
16
+ throw new Error(args.toString());
17
+
18
+ return void 0 as never;
19
+ }
20
+
21
+ type Nothing = readonly [];
22
+ type Just<a> = readonly [a];
23
+ type Maybe<a> =
24
+ | Nothing
25
+ | Just<a>;
26
+
27
+ let empty:<a>(x:Maybe<a>)=>boolean;
28
+ let nothing:()=>Nothing;
29
+ let just:<a>(x:a)=>Just<a>;
30
+ let fold:<a>(x:Maybe<a>)=>a|never;
31
+ let x:Function;
32
+
33
+ nothing = (): Nothing => [] as Nothing;
34
+ just = <a>(x:a): Just<a> => [x] as Just<a>;
35
+ empty = <a>(x:Maybe<a>): x is Nothing => !(x&&x.length);
36
+ fold = <a>(x:Maybe<a>): a|never =>
37
+ (!empty(x))?x[0] as a:fail("folding nothing") as never;
38
+
39
+ export type { Maybe, Just, Nothing };
40
+ export { nothing, just, empty, fold };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "finitefields",
3
3
  "type": "module",
4
- "version": "0.0.8",
4
+ "version": "0.0.10",
5
5
  "description": "Galois/Finite field crypto and raw elliptic curves",
6
6
  "main": "main.js",
7
7
  "scripts": {