finitefields 0.0.7 → 0.0.9

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,12 +7,16 @@
7
7
  *
8
8
  */
9
9
 
10
- import type { PrimeField } from "./galois.js";
10
+ import type { GF,PrimeField } from './galois.js';
11
+ import { just, nothing, type Maybe, type Nothing } from './maybe.js';
12
+ import { Util } from './galois.js';
11
13
 
14
+ let 𝒪:Nothing;
12
15
  let log:(...x:any[])=>void;
13
16
  let fail:(...x:any[])=>never;
14
- let p256:ECCurve;
17
+ let p256:()=>ECCurve;
15
18
 
19
+ 𝒪 = nothing();
16
20
  log = console.log;
17
21
  fail = (...args:any[]): never => {
18
22
  console.error(...args);
@@ -21,7 +25,7 @@ fail = (...args:any[]): never => {
21
25
  return void 0 as never;
22
26
  }
23
27
 
24
- p256 = {
28
+ p256 = ():ECCurve => ({
25
29
  '#E': 0xffffffff00000000_ffffffffffffffff_bce6faada7179e84_f3b9cac2fc632551n,
26
30
  'θ': 0xffffffff00000001_0000000000000000_00000000ffffffff_ffffffffffffffffn,
27
31
  'b': 0x5ac635d8aa3a93e7_b3ebbd55769886bc_651d06b0cc53b0f6_3bce3c3e27d2604bn,
@@ -34,11 +38,19 @@ p256 = {
34
38
  [
35
39
  0xc97445f45cdef9f0_d3e05e1e585fc297_235b82b5be8ff3ef_ca67c59852018192n,
36
40
  0xb28ef557ba31dfcb_dd21ac46e2a91e3c_304f44cb87058ada_2cb815151e610046n
37
- ]
38
- }
41
+ ],
42
+ bitlen: 256n,
43
+ formula: (a:bigint,b:bigint,f:PrimeField)=>(x:bigint,y:bigint) =>
44
+ f.add(f.add( // y^2 =
45
+ f.exp(x, 3n), // x^3
46
+ f.mul(a,x)), // + ax
47
+ b) // + b
48
+ });
39
49
 
40
50
  type Tuple<a> = readonly [a,a];
51
+ type Coordinate = Maybe<Point>;
41
52
  type infinity = false | true;
53
+ type ECformula = (a:bigint,b:bigint,f:GF)=>Function;
42
54
 
43
55
  interface Tuples {
44
56
  'p': Tuple<bigint>;
@@ -46,8 +58,10 @@ interface Tuples {
46
58
  }
47
59
 
48
60
  interface IECCurve {
49
- 'θ': bigint;
50
- 'b': bigint;
61
+ 'θ': bigint;
62
+ 'b': bigint;
63
+ bitlen: bigint;
64
+ formula: ECformula;
51
65
  }
52
66
 
53
67
  type hashE = {'#E':bigint};
@@ -56,6 +70,8 @@ interface ECCurve extends IECCurve,Tuples,hashE {};
56
70
  interface Iellipticcurves<a> {
57
71
  backend: a;
58
72
  constructor:Function;
73
+ add:(a:Coordinate,b:Coordinate)=>Coordinate;
74
+ double:(a:Coordinate)=>Coordinate;
59
75
  }
60
76
 
61
77
  interface Icurve extends IECCurve {
@@ -79,7 +95,7 @@ class Point implements Ipoint {
79
95
  constructor(point:Tuple<bigint>) {
80
96
  [ this['x'], this['y'], this['∞'] ] = [0n,0n,false];
81
97
 
82
- switch (point.every((xy:bigint):xy is bigint=>!xy)) {
98
+ switch (point.every((xy:bigint):xy is bigint=>!!xy)) {
83
99
  case true:
84
100
  [ this['x'], this['y'] ] = point;
85
101
  break;
@@ -100,9 +116,10 @@ class Curve<a> implements Icurve {
100
116
  public b: bigint;
101
117
  public p: Point;
102
118
  public q: Point;
103
- private object: EllipticCurves<a>;
119
+ public bitlen: bigint;
120
+ public formula:ECformula;
104
121
 
105
- constructor(object:EllipticCurves<a>,curve:ECCurve) {
122
+ constructor(curve:ECCurve) {
106
123
  let m:string;
107
124
 
108
125
  m = 'argument error (incomplete curve params)' as const;
@@ -112,9 +129,12 @@ class Curve<a> implements Icurve {
112
129
  || fail(m);
113
130
  this.b = curve.b
114
131
  || fail(m);
132
+ this.bitlen = curve.bitlen
133
+ || fail(m);
134
+ this.formula = curve.formula
135
+ || fail(m);
115
136
  this.p = new Point(curve.p);
116
137
  this.q = new Point(curve.q);
117
- this.object = object;
118
138
 
119
139
  return this;
120
140
  }
@@ -124,14 +144,40 @@ abstract class EllipticCurves<a> implements Iellipticcurves<a> {
124
144
  public abstract backend: a;
125
145
  private curve: Curve<a>;
126
146
 
147
+ protected addpoints(a:Coordinate,b:Coordinate): Coordinate {
148
+ return a;
149
+ }
150
+
151
+ protected doublepoint(a:Coordinate): Coordinate {
152
+ return a;
153
+ }
154
+
155
+ public add(a:Coordinate,b:Coordinate): Coordinate {
156
+ if ((a === 𝒪) && (b === 𝒪))
157
+ return <Maybe<Point>>nothing();
158
+ else if (a === 𝒪)
159
+ return <Maybe<Point>>just(b as unknown as Point);
160
+ else if (b === 𝒪)
161
+ return <Maybe<Point>>just(a as unknown as Point);
162
+ else
163
+ return <Maybe<Point>>this.addpoints(a,b);
164
+ }
165
+
166
+ public double(a:Coordinate): Coordinate {
167
+ if (a === 𝒪)
168
+ return nothing();
169
+ else
170
+ return this.doublepoint(a);
171
+ }
172
+
127
173
  constructor(curve:ECCurve) {
128
- this.curve = new Curve<a>(this,curve);
174
+ this.curve = new Curve<a>(curve);
129
175
 
130
176
  return this;
131
177
  }
132
178
  }
133
179
 
134
- class ECoverℤp extends EllipticCurves<PrimeField>
180
+ class ecℤp extends EllipticCurves<PrimeField>
135
181
  implements Iellipticcurves<PrimeField>
136
182
  {
137
183
  public backend:PrimeField;
@@ -144,4 +190,4 @@ class ECoverℤp extends EllipticCurves<PrimeField>
144
190
  }
145
191
  }
146
192
 
147
- export { ECoverℤp };
193
+ 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,48 @@ 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
+ ((y+y)%p_)
165
+ mul = (y:bigint,z:bigint,p_:bigint):bigint =>
166
+ ((y+z)%p_);
167
+ a=e_;
168
+ e=a_;
169
+ break;
104
170
 
105
- mul = (y:bigint,z:bigint,p_:bigint):bigint => ((y*z)%p_);
106
- sq = (y:bigint,p_:bigint):bigint => ((y*y)%p_);
171
+ default:
172
+ return fail('argument error');
173
+ break;
174
+ }
107
175
 
108
176
  val = a;
109
177
  bitlen = this.countbits(e);
@@ -114,12 +182,13 @@ Util = {
114
182
  .fill(false,0,Number(bitlen))
115
183
  .map((x:boolean,idx:number):boolean =>
116
184
  (((e>>n--)&1n)===1n) && (!!idx));
185
+ bitstring.shift();
117
186
  // log(bitstring.map((x:boolean):number => (x)?1:0));
118
187
  bitstring
119
188
  .forEach((x:boolean):void => {
120
189
  val = (x) ?
121
190
  mul(a,sq(val,p),p) :
122
- sq(a,p);
191
+ sq(val,p);
123
192
 
124
193
  return void 0;
125
194
  });
@@ -128,19 +197,14 @@ Util = {
128
197
  }
129
198
  }
130
199
 
131
- enum fieldops {
132
- $add,
133
- $sub,
134
- $mul,
135
- $inv
136
- }
137
-
138
200
  interface Igalois {
139
201
  add: (a:bigint,b:bigint)=>bigint;
140
202
  sub: (a:bigint,b:bigint)=>bigint;
141
203
  mul: (a:bigint,b:bigint)=>bigint;
142
204
  inv: (a:bigint)=>bigint;
205
+ exp: (a:bigint,b:bigint)=>bigint;
143
206
  verify:()=>void;
207
+ get p(): bigint;
144
208
  constructor:Function;
145
209
  }
146
210
 
@@ -149,7 +213,9 @@ interface Iutil {
149
213
  countbits: (x:bigint)=>bigint;
150
214
  rnd: (bitlen:bigint,max:bigint)=>bigint;
151
215
  eea: (x:bigint,p:bigint)=>bigint;
216
+ binmethod: (a:bigint,e:bigint,p:bigint,method:methods)=>bigint;
152
217
  sqmul: (a:bigint,e:bigint,p:bigint)=>bigint;
218
+ dblad: (a:bigint,e:bigint,p:bigint)=>bigint;
153
219
  }
154
220
 
155
221
  abstract class GF implements Igalois {
@@ -159,9 +225,14 @@ abstract class GF implements Igalois {
159
225
  public abstract sub: typeof this.add;
160
226
  public abstract mul: typeof this.add;
161
227
  public abstract inv: (a:bigint)=>bigint;
228
+ public abstract exp: typeof this.add;
162
229
 
163
230
  public abstract verify(): void;
164
231
 
232
+ public get p(): bigint {
233
+ return this.modulus;
234
+ }
235
+
165
236
  constructor(field:bigint,bitlen:bigint) {
166
237
  this.modulus = field;
167
238
  this.bitlen = bitlen;
@@ -177,6 +248,7 @@ class PrimeField extends GF implements Igalois {
177
248
  public sub: typeof this.add;
178
249
  public mul: typeof this.add;
179
250
  public inv: (a:bigint)=>bigint;
251
+ public exp: typeof this.add;
180
252
 
181
253
  public verify(): void {
182
254
  if (!Util.isprime(this.modulus))
@@ -193,6 +265,7 @@ class PrimeField extends GF implements Igalois {
193
265
  this.sub = arithmeticsℤp(this.modulus, fieldops.$sub);
194
266
  this.mul = arithmeticsℤp(this.modulus, fieldops.$mul);
195
267
  this.inv = arithmeticsℤp(this.modulus, fieldops.$inv);
268
+ this.exp = arithmeticsℤp(this.modulus, fieldops.$exp);
196
269
 
197
270
  return this;
198
271
  }
@@ -200,3 +273,4 @@ class PrimeField extends GF implements Igalois {
200
273
  }
201
274
 
202
275
  export { Util, PrimeField };
276
+ export type { GF }
package/main.ts CHANGED
@@ -1,31 +1,23 @@
1
1
  /* main.ts */
2
2
  import { Polynomial } from './polynomial.js';
3
3
  import { Util,PrimeField } from './galois.js';
4
- import { ECoverℤp } from './ellipticcurves.js';
4
+ import { ecℤp, p256 } 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
- let p1:Polynomial;
10
- let p2:Polynomial;
11
- let p3:Polynomial;
12
- let x0:bigint;
13
- let x1:bigint;
14
- let x2:bigint;
15
- let x3:bigint;
11
+ let foo:Maybe<string>;
12
+ foo = just(1..toString());
13
+ log(empty(foo));
16
14
 
17
- x0 = BigInt(1);
18
- x1 = BigInt(0);
19
- x2 = BigInt(1);
20
- x3 = BigInt(0);
15
+ // let field:PrimeField;
16
+ // let curve:ecℤp;
21
17
 
22
- p1 = new Polynomial([x0, x1, x2, x3], 2n);
23
- p2 = new Polynomial({ tobject:0n, x3:1n, x2:0n, x:1n, 1:1n }, 2n);
24
- // log(p1, " + ", p2, " =");
25
- // p3 = Polynomial.add(p1,p2);
26
- p3 = new Polynomial(1n<<254n, 2n);
18
+ // field = new PrimeField(p256().θ, p256().bitlen);
19
+ // log(field);
20
+ // curve = new ecℤp(field, p256());
21
+ // log(curve);
27
22
 
28
- log(p3, p3.eval());
29
- // log(p3.eval());
30
-
31
- export { Polynomial,Util,PrimeField,ECoverℤp };
23
+ 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.7",
4
+ "version": "0.0.9",
5
5
  "description": "Galois/Finite field crypto and raw elliptic curves",
6
6
  "main": "main.js",
7
7
  "scripts": {
package/main.js DELETED
@@ -1,26 +0,0 @@
1
- /* main.ts */
2
- import { Polynomial } from './polynomial.js';
3
- import { Util, PrimeField } from './galois.js';
4
- import { ECoverℤp } from './ellipticcurves.js';
5
- let log;
6
- log = console.log;
7
- let p1;
8
- let p2;
9
- let p3;
10
- let x0;
11
- let x1;
12
- let x2;
13
- let x3;
14
- x0 = BigInt(1);
15
- x1 = BigInt(0);
16
- x2 = BigInt(1);
17
- x3 = BigInt(0);
18
- p1 = new Polynomial([x0, x1, x2, x3], 2n);
19
- p2 = new Polynomial({ tobject: 0n, x3: 1n, x2: 0n, x: 1n, 1: 1n }, 2n);
20
- // log(p1, " + ", p2, " =");
21
- // p3 = Polynomial.add(p1,p2);
22
- p3 = new Polynomial(1n << 254n, 2n);
23
- log(p3, p3.eval());
24
- // log(p3.eval());
25
- export { Polynomial, Util, PrimeField, ECoverℤp };
26
- //# sourceMappingURL=main.js.map