finitefields 0.0.6 → 0.0.8

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.
@@ -0,0 +1,161 @@
1
+ /*
2
+ * elliptic curves
3
+ *
4
+ * finitefields package by @dr-Jonas-Birch
5
+ *
6
+ * 2026
7
+ *
8
+ */
9
+
10
+ import type { GF,PrimeField } from './galois.js';
11
+ import { Util } from './galois.js';
12
+
13
+ let log:(...x:any[])=>void;
14
+ let fail:(...x:any[])=>never;
15
+ let p256:()=>ECCurve;
16
+
17
+ log = console.log;
18
+ fail = (...args:any[]): never => {
19
+ console.error(...args);
20
+ throw new Error(args.toString());
21
+
22
+ return void 0 as never;
23
+ }
24
+
25
+ p256 = ():ECCurve => ({
26
+ '#E': 0xffffffff00000000_ffffffffffffffff_bce6faada7179e84_f3b9cac2fc632551n,
27
+ 'θ': 0xffffffff00000001_0000000000000000_00000000ffffffff_ffffffffffffffffn,
28
+ 'b': 0x5ac635d8aa3a93e7_b3ebbd55769886bc_651d06b0cc53b0f6_3bce3c3e27d2604bn,
29
+ 'p':
30
+ [
31
+ 0x6b17d1f2e12c4247_f8bce6e563a440f2_77037d812deb33a0_f4a13945d898c296n,
32
+ 0x4fe342e2fe1a7f9b_8ee7eb4a7c0f9e16_2bce33576b315ece_cbb6406837bf51f5n
33
+ ],
34
+ 'q':
35
+ [
36
+ 0xc97445f45cdef9f0_d3e05e1e585fc297_235b82b5be8ff3ef_ca67c59852018192n,
37
+ 0xb28ef557ba31dfcb_dd21ac46e2a91e3c_304f44cb87058ada_2cb815151e610046n
38
+ ],
39
+ bitlen: 256n,
40
+ formula: (a:bigint,b:bigint,f:PrimeField)=>(x:bigint,y:bigint) =>
41
+ f.add(f.add( // y^2 =
42
+ f.exp(x, 3n), // x^3
43
+ f.mul(a,x)), // + ax
44
+ b) // + b
45
+ });
46
+
47
+ type Tuple<a> = readonly [a,a];
48
+ type infinity = false | true;
49
+ type ECformula = (a:bigint,b:bigint,f:GF)=>Function;
50
+
51
+ interface Tuples {
52
+ 'p': Tuple<bigint>;
53
+ 'q': Tuple<bigint>;
54
+ }
55
+
56
+ interface IECCurve {
57
+ 'θ': bigint;
58
+ 'b': bigint;
59
+ bitlen: bigint;
60
+ formula: ECformula;
61
+ }
62
+
63
+ type hashE = {'#E':bigint};
64
+ interface ECCurve extends IECCurve,Tuples,hashE {};
65
+
66
+ interface Iellipticcurves<a> {
67
+ backend: a;
68
+ constructor:Function;
69
+ }
70
+
71
+ interface Icurve extends IECCurve {
72
+ p: Point;
73
+ q: Point;
74
+ constructor:Function;
75
+ }
76
+
77
+ interface Ipoint {
78
+ 'x': bigint;
79
+ 'y': bigint;
80
+ '∞': infinity;
81
+ constructor: Function;
82
+ }
83
+
84
+ class Point implements Ipoint {
85
+ public 'x':bigint;
86
+ public 'y':bigint;
87
+ public '∞':infinity;
88
+
89
+ constructor(point:Tuple<bigint>) {
90
+ [ this['x'], this['y'], this['∞'] ] = [0n,0n,false];
91
+
92
+ switch (point.every((xy:bigint):xy is bigint=>!!xy)) {
93
+ case true:
94
+ [ this['x'], this['y'] ] = point;
95
+ break;
96
+ case false:
97
+ (this['∞'] as unknown as number)++;
98
+ break;
99
+ default:
100
+ return fail();
101
+ }
102
+
103
+ return this;
104
+ }
105
+ }
106
+
107
+ class Curve<a> implements Icurve {
108
+ #E: bigint;
109
+ public θ: bigint;
110
+ public b: bigint;
111
+ public p: Point;
112
+ public q: Point;
113
+ public bitlen: bigint;
114
+ public formula:ECformula;
115
+
116
+ constructor(curve:ECCurve) {
117
+ let m:string;
118
+
119
+ m = 'argument error (incomplete curve params)' as const;
120
+ this.#E = curve['#E']
121
+ || fail(m);
122
+ this.θ = curve.θ
123
+ || fail(m);
124
+ this.b = curve.b
125
+ || fail(m);
126
+ this.bitlen = curve.bitlen
127
+ || fail(m);
128
+ this.formula = curve.formula
129
+ || fail(m);
130
+ this.p = new Point(curve.p);
131
+ this.q = new Point(curve.q);
132
+
133
+ return this;
134
+ }
135
+ }
136
+
137
+ abstract class EllipticCurves<a> implements Iellipticcurves<a> {
138
+ public abstract backend: a;
139
+ private curve: Curve<a>;
140
+
141
+ constructor(curve:ECCurve) {
142
+ this.curve = new Curve<a>(curve);
143
+
144
+ return this;
145
+ }
146
+ }
147
+
148
+ class ecℤp extends EllipticCurves<PrimeField>
149
+ implements Iellipticcurves<PrimeField>
150
+ {
151
+ public backend:PrimeField;
152
+
153
+ constructor(field:PrimeField, curve:ECCurve) {
154
+ super(curve);
155
+ this.backend = field;
156
+
157
+ return this;
158
+ }
159
+ }
160
+
161
+ export { ecℤp, p256 };
package/galois.ts CHANGED
@@ -19,15 +19,30 @@ fail = (...args:any[]): never => {
19
19
  return void 0 as never;
20
20
  }
21
21
 
22
+ enum fieldops {
23
+ $add,
24
+ $sub,
25
+ $mul,
26
+ $inv,
27
+ $exp
28
+ }
29
+
30
+ enum methods {
31
+ SquareAndMultiply,
32
+ DoubleAndAdd
33
+ }
34
+
22
35
  const arithmeticsℤp = (p:bigint,op:fieldops) =>
23
36
  (op==fieldops.$add) ?
24
37
  (a:bigint,b:bigint=0n) => (a+b)%p :
25
38
  (op==fieldops.$sub) ?
26
39
  (a:bigint,b:bigint=0n) => ((a-b)<1)?(a-b+p):(a-b)%p :
27
40
  (op==fieldops.$mul) ?
28
- (a:bigint,b:bigint=0n) => (a*b)%p :
41
+ (a:bigint,b:bigint=0n) => (!a||!b)?0n:Util.dblad(a,b,p) :
29
42
  (op==fieldops.$inv) ?
30
43
  (a:bigint) => (!a)?fail('0 has no inverse'):Util.sqmul(a,(p-2n),p) :
44
+ (op==fieldops.$exp) ?
45
+ (a:bigint,b:bigint=0n) => (!a)?0n:(!b)?1n:Util.sqmul(a,b,p) :
31
46
  fail('unknown field operation');
32
47
 
33
48
  Util = {
@@ -44,6 +59,28 @@ Util = {
44
59
  let n:number;
45
60
  let r:bigint;
46
61
  let ret:boolean;
62
+ // let pow:(x:bigint,e:bigint,p_:bigint)=>bigint;
63
+
64
+ // pow = (x:bigint,e:bigint,p_:bigint): bigint => {
65
+ // let n_:bigint;
66
+ // let v:bigint;
67
+
68
+ // if (e == 1n)
69
+ // return (x%p_);
70
+ // else if (!e)
71
+ // return (1n%p_);
72
+ // else if (e<0n)
73
+ // return fail("trying to raise to negative power");
74
+
75
+ // n_ = e;
76
+ // v = x;
77
+ // while (--n_)
78
+ // v = (v*v)%p_;
79
+
80
+ // return v;
81
+ // }
82
+
83
+ return true;
47
84
 
48
85
  if (p<2n)
49
86
  return true;
@@ -51,7 +88,8 @@ Util = {
51
88
  for (n=0, ret=true; n<s; n++) {
52
89
  r = this.rnd(bitlen,(p-1n));
53
90
  r += 1n;
54
- if (((r**(p-1n))%p) != 1n) {
91
+ // if (((r**(p-1n))%p) != 1n) {
92
+ if (this.sqmul(r,(p-1n),p) !== 1n) {
55
93
  ret = false;
56
94
  break;
57
95
  }
@@ -92,18 +130,50 @@ Util = {
92
130
  return fail('eea() not implemented') as never;
93
131
  },
94
132
 
95
- sqmul(a:bigint,e:bigint,p:bigint): bigint {
133
+ sqmul: (a:bigint,e:bigint,p:bigint): bigint =>
134
+ Util.binmethod(a,e,p,methods.SquareAndMultiply),
135
+ dblad: (a:bigint,e:bigint,p:bigint): bigint =>
136
+ Util.binmethod(a,e,p,methods.DoubleAndAdd),
137
+
138
+ binmethod(a_:bigint,e_:bigint,p:bigint,method:methods): bigint {
96
139
  let bitstring:boolean[];
97
140
  let bitlen:bigint;
98
141
  let n:bigint;
99
142
  let val:bigint;
100
143
  let mul:(y:bigint,z:bigint,p_:bigint)=>bigint;
101
144
  let sq:(y:bigint,p_:bigint)=>bigint;
145
+ let sign:string;
146
+ let a:bigint;
147
+ let e:bigint;
148
+
149
+ sign = (method==methods.SquareAndMultiply) ? '^' : 'x';
150
+ log(`${a_}${sign}${e_} (mod ${p}) = `);
151
+
152
+ switch (method) {
153
+ case methods.SquareAndMultiply:
154
+ sq = (y:bigint,p_:bigint):bigint =>
155
+ Util.binmethod(y,y,p_,methods.DoubleAndAdd);
156
+ mul = (y:bigint,z:bigint,p_:bigint):bigint =>
157
+ Util.binmethod(y,z,p_,methods.DoubleAndAdd);
158
+ a=a_;
159
+ e=e_;
160
+ break;
102
161
 
103
- log(`${a}^${e} (mod ${p}) = `);
162
+ case methods.DoubleAndAdd:
163
+ sq = (y:bigint,p_:bigint):bigint =>
164
+ // Util.binmethod(y,2n,p_,DoubleAndAdd)
165
+ ((y+y)%p_)
166
+ mul = (y:bigint,z:bigint,p_:bigint):bigint =>
167
+ // Util.binmethod(y,z,p_,DoubleAndAdd)
168
+ ((y+z)%p_);
169
+ a=e_;
170
+ e=a_;
171
+ break;
104
172
 
105
- mul = (y:bigint,z:bigint,p_:bigint):bigint => ((y*z)%p_);
106
- sq = (y:bigint,p_:bigint):bigint => ((y*y)%p_);
173
+ default:
174
+ return fail('argument error');
175
+ break;
176
+ }
107
177
 
108
178
  val = a;
109
179
  bitlen = this.countbits(e);
@@ -114,12 +184,18 @@ Util = {
114
184
  .fill(false,0,Number(bitlen))
115
185
  .map((x:boolean,idx:number):boolean =>
116
186
  (((e>>n--)&1n)===1n) && (!!idx));
187
+ // if (method === methods.DoubleAndAdd)
188
+ bitstring.shift();
117
189
  // log(bitstring.map((x:boolean):number => (x)?1:0));
118
190
  bitstring
119
191
  .forEach((x:boolean):void => {
192
+ // val = (x) ?
193
+ // mul(a,sq(val,p),p) :
194
+ // sq(a,p);
120
195
  val = (x) ?
121
196
  mul(a,sq(val,p),p) :
122
- sq(a,p);
197
+ sq(val,p);
198
+ // log(val);
123
199
 
124
200
  return void 0;
125
201
  });
@@ -128,19 +204,14 @@ Util = {
128
204
  }
129
205
  }
130
206
 
131
- enum fieldops {
132
- $add,
133
- $sub,
134
- $mul,
135
- $inv
136
- }
137
-
138
207
  interface Igalois {
139
208
  add: (a:bigint,b:bigint)=>bigint;
140
209
  sub: (a:bigint,b:bigint)=>bigint;
141
210
  mul: (a:bigint,b:bigint)=>bigint;
142
211
  inv: (a:bigint)=>bigint;
212
+ exp: (a:bigint,b:bigint)=>bigint;
143
213
  verify:()=>void;
214
+ get p(): bigint;
144
215
  constructor:Function;
145
216
  }
146
217
 
@@ -149,7 +220,9 @@ interface Iutil {
149
220
  countbits: (x:bigint)=>bigint;
150
221
  rnd: (bitlen:bigint,max:bigint)=>bigint;
151
222
  eea: (x:bigint,p:bigint)=>bigint;
223
+ binmethod: (a:bigint,e:bigint,p:bigint,method:methods)=>bigint;
152
224
  sqmul: (a:bigint,e:bigint,p:bigint)=>bigint;
225
+ dblad: (a:bigint,e:bigint,p:bigint)=>bigint;
153
226
  }
154
227
 
155
228
  abstract class GF implements Igalois {
@@ -159,9 +232,14 @@ abstract class GF implements Igalois {
159
232
  public abstract sub: typeof this.add;
160
233
  public abstract mul: typeof this.add;
161
234
  public abstract inv: (a:bigint)=>bigint;
235
+ public abstract exp: typeof this.add;
162
236
 
163
237
  public abstract verify(): void;
164
238
 
239
+ public get p(): bigint {
240
+ return this.modulus;
241
+ }
242
+
165
243
  constructor(field:bigint,bitlen:bigint) {
166
244
  this.modulus = field;
167
245
  this.bitlen = bitlen;
@@ -177,6 +255,7 @@ class PrimeField extends GF implements Igalois {
177
255
  public sub: typeof this.add;
178
256
  public mul: typeof this.add;
179
257
  public inv: (a:bigint)=>bigint;
258
+ public exp: typeof this.add;
180
259
 
181
260
  public verify(): void {
182
261
  if (!Util.isprime(this.modulus))
@@ -193,6 +272,7 @@ class PrimeField extends GF implements Igalois {
193
272
  this.sub = arithmeticsℤp(this.modulus, fieldops.$sub);
194
273
  this.mul = arithmeticsℤp(this.modulus, fieldops.$mul);
195
274
  this.inv = arithmeticsℤp(this.modulus, fieldops.$inv);
275
+ this.exp = arithmeticsℤp(this.modulus, fieldops.$exp);
196
276
 
197
277
  return this;
198
278
  }
@@ -200,3 +280,4 @@ class PrimeField extends GF implements Igalois {
200
280
  }
201
281
 
202
282
  export { Util, PrimeField };
283
+ export type { GF }
package/main.ts CHANGED
@@ -1,30 +1,17 @@
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
5
 
5
6
  let log:(...x:any[])=>void;
6
7
  log = console.log;
7
8
 
8
- let p1:Polynomial;
9
- let p2:Polynomial;
10
- let p3:Polynomial;
11
- let x0:bigint;
12
- let x1:bigint;
13
- let x2:bigint;
14
- let x3:bigint;
9
+ let field:PrimeField;
10
+ let curve:ecℤp;
15
11
 
16
- x0 = BigInt(1);
17
- x1 = BigInt(0);
18
- x2 = BigInt(1);
19
- x3 = BigInt(0);
12
+ field = new PrimeField(p256().θ, p256().bitlen);
13
+ log(field);
14
+ curve = new ecℤp(field, p256());
15
+ log(curve);
20
16
 
21
- p1 = new Polynomial([x0, x1, x2, x3], 2n);
22
- p2 = new Polynomial({ tobject:0n, x3:1n, x2:0n, x:1n, 1:1n }, 2n);
23
- // log(p1, " + ", p2, " =");
24
- // p3 = Polynomial.add(p1,p2);
25
- p3 = new Polynomial(1n<<254n, 2n);
26
-
27
- log(p3, p3.eval());
28
- // log(p3.eval());
29
-
30
- export { Polynomial,Util,PrimeField };
17
+ export { Polynomial,Util,PrimeField,ecℤp,p256 };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "finitefields",
3
3
  "type": "module",
4
- "version": "0.0.6",
4
+ "version": "0.0.8",
5
5
  "description": "Galois/Finite field crypto and raw elliptic curves",
6
6
  "main": "main.js",
7
7
  "scripts": {
package/main.js DELETED
@@ -1,25 +0,0 @@
1
- /* main.ts */
2
- import { Polynomial } from './polynomial.js';
3
- import { Util, PrimeField } from './galois.js';
4
- let log;
5
- log = console.log;
6
- let p1;
7
- let p2;
8
- let p3;
9
- let x0;
10
- let x1;
11
- let x2;
12
- let x3;
13
- x0 = BigInt(1);
14
- x1 = BigInt(0);
15
- x2 = BigInt(1);
16
- x3 = BigInt(0);
17
- p1 = new Polynomial([x0, x1, x2, x3], 2n);
18
- p2 = new Polynomial({ tobject: 0n, x3: 1n, x2: 0n, x: 1n, 1: 1n }, 2n);
19
- // log(p1, " + ", p2, " =");
20
- // p3 = Polynomial.add(p1,p2);
21
- p3 = new Polynomial(1n << 254n, 2n);
22
- log(p3, p3.eval());
23
- // log(p3.eval());
24
- export { Polynomial, Util, PrimeField };
25
- //# sourceMappingURL=main.js.map