finitefields 0.0.7 → 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.
package/ellipticcurves.ts CHANGED
@@ -7,11 +7,12 @@
7
7
  *
8
8
  */
9
9
 
10
- import type { PrimeField } from "./galois.js";
10
+ import type { GF,PrimeField } from './galois.js';
11
+ import { Util } from './galois.js';
11
12
 
12
13
  let log:(...x:any[])=>void;
13
14
  let fail:(...x:any[])=>never;
14
- let p256:ECCurve;
15
+ let p256:()=>ECCurve;
15
16
 
16
17
  log = console.log;
17
18
  fail = (...args:any[]): never => {
@@ -21,7 +22,7 @@ fail = (...args:any[]): never => {
21
22
  return void 0 as never;
22
23
  }
23
24
 
24
- p256 = {
25
+ p256 = ():ECCurve => ({
25
26
  '#E': 0xffffffff00000000_ffffffffffffffff_bce6faada7179e84_f3b9cac2fc632551n,
26
27
  'θ': 0xffffffff00000001_0000000000000000_00000000ffffffff_ffffffffffffffffn,
27
28
  'b': 0x5ac635d8aa3a93e7_b3ebbd55769886bc_651d06b0cc53b0f6_3bce3c3e27d2604bn,
@@ -34,11 +35,18 @@ p256 = {
34
35
  [
35
36
  0xc97445f45cdef9f0_d3e05e1e585fc297_235b82b5be8ff3ef_ca67c59852018192n,
36
37
  0xb28ef557ba31dfcb_dd21ac46e2a91e3c_304f44cb87058ada_2cb815151e610046n
37
- ]
38
- }
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
+ });
39
46
 
40
47
  type Tuple<a> = readonly [a,a];
41
48
  type infinity = false | true;
49
+ type ECformula = (a:bigint,b:bigint,f:GF)=>Function;
42
50
 
43
51
  interface Tuples {
44
52
  'p': Tuple<bigint>;
@@ -46,8 +54,10 @@ interface Tuples {
46
54
  }
47
55
 
48
56
  interface IECCurve {
49
- 'θ': bigint;
50
- 'b': bigint;
57
+ 'θ': bigint;
58
+ 'b': bigint;
59
+ bitlen: bigint;
60
+ formula: ECformula;
51
61
  }
52
62
 
53
63
  type hashE = {'#E':bigint};
@@ -79,7 +89,7 @@ class Point implements Ipoint {
79
89
  constructor(point:Tuple<bigint>) {
80
90
  [ this['x'], this['y'], this['∞'] ] = [0n,0n,false];
81
91
 
82
- switch (point.every((xy:bigint):xy is bigint=>!xy)) {
92
+ switch (point.every((xy:bigint):xy is bigint=>!!xy)) {
83
93
  case true:
84
94
  [ this['x'], this['y'] ] = point;
85
95
  break;
@@ -100,9 +110,10 @@ class Curve<a> implements Icurve {
100
110
  public b: bigint;
101
111
  public p: Point;
102
112
  public q: Point;
103
- private object: EllipticCurves<a>;
113
+ public bitlen: bigint;
114
+ public formula:ECformula;
104
115
 
105
- constructor(object:EllipticCurves<a>,curve:ECCurve) {
116
+ constructor(curve:ECCurve) {
106
117
  let m:string;
107
118
 
108
119
  m = 'argument error (incomplete curve params)' as const;
@@ -112,9 +123,12 @@ class Curve<a> implements Icurve {
112
123
  || fail(m);
113
124
  this.b = curve.b
114
125
  || fail(m);
126
+ this.bitlen = curve.bitlen
127
+ || fail(m);
128
+ this.formula = curve.formula
129
+ || fail(m);
115
130
  this.p = new Point(curve.p);
116
131
  this.q = new Point(curve.q);
117
- this.object = object;
118
132
 
119
133
  return this;
120
134
  }
@@ -125,13 +139,13 @@ abstract class EllipticCurves<a> implements Iellipticcurves<a> {
125
139
  private curve: Curve<a>;
126
140
 
127
141
  constructor(curve:ECCurve) {
128
- this.curve = new Curve<a>(this,curve);
142
+ this.curve = new Curve<a>(curve);
129
143
 
130
144
  return this;
131
145
  }
132
146
  }
133
147
 
134
- class ECoverℤp extends EllipticCurves<PrimeField>
148
+ class ecℤp extends EllipticCurves<PrimeField>
135
149
  implements Iellipticcurves<PrimeField>
136
150
  {
137
151
  public backend:PrimeField;
@@ -144,4 +158,4 @@ class ECoverℤp extends EllipticCurves<PrimeField>
144
158
  }
145
159
  }
146
160
 
147
- export { ECoverℤp };
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,31 +1,17 @@
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
5
 
6
6
  let log:(...x:any[])=>void;
7
7
  log = console.log;
8
8
 
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;
9
+ let field:PrimeField;
10
+ let curve:ecℤp;
16
11
 
17
- x0 = BigInt(1);
18
- x1 = BigInt(0);
19
- x2 = BigInt(1);
20
- x3 = BigInt(0);
12
+ field = new PrimeField(p256().θ, p256().bitlen);
13
+ log(field);
14
+ curve = new ecℤp(field, p256());
15
+ log(curve);
21
16
 
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);
27
-
28
- log(p3, p3.eval());
29
- // log(p3.eval());
30
-
31
- export { Polynomial,Util,PrimeField,ECoverℤp };
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.7",
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,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