finitefields 0.0.5 → 0.0.7
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 +147 -0
- package/galois.ts +86 -27
- package/main.js +3 -0
- package/main.ts +3 -0
- package/package.json +1 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* elliptic curves
|
|
3
|
+
*
|
|
4
|
+
* finitefields package by @dr-Jonas-Birch
|
|
5
|
+
*
|
|
6
|
+
* 2026
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { PrimeField } from "./galois.js";
|
|
11
|
+
|
|
12
|
+
let log:(...x:any[])=>void;
|
|
13
|
+
let fail:(...x:any[])=>never;
|
|
14
|
+
let p256:ECCurve;
|
|
15
|
+
|
|
16
|
+
log = console.log;
|
|
17
|
+
fail = (...args:any[]): never => {
|
|
18
|
+
console.error(...args);
|
|
19
|
+
throw new Error(args.toString());
|
|
20
|
+
|
|
21
|
+
return void 0 as never;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
p256 = {
|
|
25
|
+
'#E': 0xffffffff00000000_ffffffffffffffff_bce6faada7179e84_f3b9cac2fc632551n,
|
|
26
|
+
'θ': 0xffffffff00000001_0000000000000000_00000000ffffffff_ffffffffffffffffn,
|
|
27
|
+
'b': 0x5ac635d8aa3a93e7_b3ebbd55769886bc_651d06b0cc53b0f6_3bce3c3e27d2604bn,
|
|
28
|
+
'p':
|
|
29
|
+
[
|
|
30
|
+
0x6b17d1f2e12c4247_f8bce6e563a440f2_77037d812deb33a0_f4a13945d898c296n,
|
|
31
|
+
0x4fe342e2fe1a7f9b_8ee7eb4a7c0f9e16_2bce33576b315ece_cbb6406837bf51f5n
|
|
32
|
+
],
|
|
33
|
+
'q':
|
|
34
|
+
[
|
|
35
|
+
0xc97445f45cdef9f0_d3e05e1e585fc297_235b82b5be8ff3ef_ca67c59852018192n,
|
|
36
|
+
0xb28ef557ba31dfcb_dd21ac46e2a91e3c_304f44cb87058ada_2cb815151e610046n
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
type Tuple<a> = readonly [a,a];
|
|
41
|
+
type infinity = false | true;
|
|
42
|
+
|
|
43
|
+
interface Tuples {
|
|
44
|
+
'p': Tuple<bigint>;
|
|
45
|
+
'q': Tuple<bigint>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface IECCurve {
|
|
49
|
+
'θ': bigint;
|
|
50
|
+
'b': bigint;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
type hashE = {'#E':bigint};
|
|
54
|
+
interface ECCurve extends IECCurve,Tuples,hashE {};
|
|
55
|
+
|
|
56
|
+
interface Iellipticcurves<a> {
|
|
57
|
+
backend: a;
|
|
58
|
+
constructor:Function;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface Icurve extends IECCurve {
|
|
62
|
+
p: Point;
|
|
63
|
+
q: Point;
|
|
64
|
+
constructor:Function;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
interface Ipoint {
|
|
68
|
+
'x': bigint;
|
|
69
|
+
'y': bigint;
|
|
70
|
+
'∞': infinity;
|
|
71
|
+
constructor: Function;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
class Point implements Ipoint {
|
|
75
|
+
public 'x':bigint;
|
|
76
|
+
public 'y':bigint;
|
|
77
|
+
public '∞':infinity;
|
|
78
|
+
|
|
79
|
+
constructor(point:Tuple<bigint>) {
|
|
80
|
+
[ this['x'], this['y'], this['∞'] ] = [0n,0n,false];
|
|
81
|
+
|
|
82
|
+
switch (point.every((xy:bigint):xy is bigint=>!xy)) {
|
|
83
|
+
case true:
|
|
84
|
+
[ this['x'], this['y'] ] = point;
|
|
85
|
+
break;
|
|
86
|
+
case false:
|
|
87
|
+
(this['∞'] as unknown as number)++;
|
|
88
|
+
break;
|
|
89
|
+
default:
|
|
90
|
+
return fail();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
class Curve<a> implements Icurve {
|
|
98
|
+
#E: bigint;
|
|
99
|
+
public θ: bigint;
|
|
100
|
+
public b: bigint;
|
|
101
|
+
public p: Point;
|
|
102
|
+
public q: Point;
|
|
103
|
+
private object: EllipticCurves<a>;
|
|
104
|
+
|
|
105
|
+
constructor(object:EllipticCurves<a>,curve:ECCurve) {
|
|
106
|
+
let m:string;
|
|
107
|
+
|
|
108
|
+
m = 'argument error (incomplete curve params)' as const;
|
|
109
|
+
this.#E = curve['#E']
|
|
110
|
+
|| fail(m);
|
|
111
|
+
this.θ = curve.θ
|
|
112
|
+
|| fail(m);
|
|
113
|
+
this.b = curve.b
|
|
114
|
+
|| fail(m);
|
|
115
|
+
this.p = new Point(curve.p);
|
|
116
|
+
this.q = new Point(curve.q);
|
|
117
|
+
this.object = object;
|
|
118
|
+
|
|
119
|
+
return this;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
abstract class EllipticCurves<a> implements Iellipticcurves<a> {
|
|
124
|
+
public abstract backend: a;
|
|
125
|
+
private curve: Curve<a>;
|
|
126
|
+
|
|
127
|
+
constructor(curve:ECCurve) {
|
|
128
|
+
this.curve = new Curve<a>(this,curve);
|
|
129
|
+
|
|
130
|
+
return this;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
class ECoverℤp extends EllipticCurves<PrimeField>
|
|
135
|
+
implements Iellipticcurves<PrimeField>
|
|
136
|
+
{
|
|
137
|
+
public backend:PrimeField;
|
|
138
|
+
|
|
139
|
+
constructor(field:PrimeField, curve:ECCurve) {
|
|
140
|
+
super(curve);
|
|
141
|
+
this.backend = field;
|
|
142
|
+
|
|
143
|
+
return this;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export { ECoverℤp };
|
package/galois.ts
CHANGED
|
@@ -19,17 +19,16 @@ fail = (...args:any[]): never => {
|
|
|
19
19
|
return void 0 as never;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
const arithmetics = (p:bigint,op:fieldops) =>
|
|
22
|
+
const arithmeticsℤp = (p:bigint,op:fieldops) =>
|
|
23
23
|
(op==fieldops.$add) ?
|
|
24
|
-
(a:bigint,b:bigint) => (a+b)%p :
|
|
24
|
+
(a:bigint,b:bigint=0n) => (a+b)%p :
|
|
25
25
|
(op==fieldops.$sub) ?
|
|
26
|
-
(a:bigint,b:bigint) => (a-b)%p :
|
|
26
|
+
(a:bigint,b:bigint=0n) => ((a-b)<1)?(a-b+p):(a-b)%p :
|
|
27
27
|
(op==fieldops.$mul) ?
|
|
28
|
-
(a:bigint,b:bigint) => (a*b)%p :
|
|
29
|
-
(op==fieldops.$
|
|
30
|
-
(a:bigint
|
|
31
|
-
fail();
|
|
32
|
-
|
|
28
|
+
(a:bigint,b:bigint=0n) => (a*b)%p :
|
|
29
|
+
(op==fieldops.$inv) ?
|
|
30
|
+
(a:bigint) => (!a)?fail('0 has no inverse'):Util.sqmul(a,(p-2n),p) :
|
|
31
|
+
fail('unknown field operation');
|
|
33
32
|
|
|
34
33
|
Util = {
|
|
35
34
|
countbits(x:bigint): bigint {
|
|
@@ -87,6 +86,45 @@ Util = {
|
|
|
87
86
|
return (val%max);
|
|
88
87
|
else
|
|
89
88
|
return val;
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
eea(x:bigint,p:bigint): bigint {
|
|
92
|
+
return fail('eea() not implemented') as never;
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
sqmul(a:bigint,e:bigint,p:bigint): bigint {
|
|
96
|
+
let bitstring:boolean[];
|
|
97
|
+
let bitlen:bigint;
|
|
98
|
+
let n:bigint;
|
|
99
|
+
let val:bigint;
|
|
100
|
+
let mul:(y:bigint,z:bigint,p_:bigint)=>bigint;
|
|
101
|
+
let sq:(y:bigint,p_:bigint)=>bigint;
|
|
102
|
+
|
|
103
|
+
log(`${a}^${e} (mod ${p}) = `);
|
|
104
|
+
|
|
105
|
+
mul = (y:bigint,z:bigint,p_:bigint):bigint => ((y*z)%p_);
|
|
106
|
+
sq = (y:bigint,p_:bigint):bigint => ((y*y)%p_);
|
|
107
|
+
|
|
108
|
+
val = a;
|
|
109
|
+
bitlen = this.countbits(e);
|
|
110
|
+
if (!bitlen)
|
|
111
|
+
return fail('error: n ≯ 0');
|
|
112
|
+
n = (bitlen-1n);
|
|
113
|
+
bitstring = new Array<boolean>(Number(bitlen))
|
|
114
|
+
.fill(false,0,Number(bitlen))
|
|
115
|
+
.map((x:boolean,idx:number):boolean =>
|
|
116
|
+
(((e>>n--)&1n)===1n) && (!!idx));
|
|
117
|
+
// log(bitstring.map((x:boolean):number => (x)?1:0));
|
|
118
|
+
bitstring
|
|
119
|
+
.forEach((x:boolean):void => {
|
|
120
|
+
val = (x) ?
|
|
121
|
+
mul(a,sq(val,p),p) :
|
|
122
|
+
sq(a,p);
|
|
123
|
+
|
|
124
|
+
return void 0;
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
return (val%p);
|
|
90
128
|
}
|
|
91
129
|
}
|
|
92
130
|
|
|
@@ -94,10 +132,14 @@ enum fieldops {
|
|
|
94
132
|
$add,
|
|
95
133
|
$sub,
|
|
96
134
|
$mul,
|
|
97
|
-
$
|
|
135
|
+
$inv
|
|
98
136
|
}
|
|
99
137
|
|
|
100
138
|
interface Igalois {
|
|
139
|
+
add: (a:bigint,b:bigint)=>bigint;
|
|
140
|
+
sub: (a:bigint,b:bigint)=>bigint;
|
|
141
|
+
mul: (a:bigint,b:bigint)=>bigint;
|
|
142
|
+
inv: (a:bigint)=>bigint;
|
|
101
143
|
verify:()=>void;
|
|
102
144
|
constructor:Function;
|
|
103
145
|
}
|
|
@@ -106,38 +148,55 @@ interface Iutil {
|
|
|
106
148
|
isprime: (p:bigint,bitlen?:bigint,s?:number)=>boolean;
|
|
107
149
|
countbits: (x:bigint)=>bigint;
|
|
108
150
|
rnd: (bitlen:bigint,max:bigint)=>bigint;
|
|
151
|
+
eea: (x:bigint,p:bigint)=>bigint;
|
|
152
|
+
sqmul: (a:bigint,e:bigint,p:bigint)=>bigint;
|
|
109
153
|
}
|
|
110
154
|
|
|
111
|
-
class GF implements Igalois {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
155
|
+
abstract class GF implements Igalois {
|
|
156
|
+
protected modulus: bigint;
|
|
157
|
+
protected bitlen: bigint;
|
|
158
|
+
public abstract add: (a:bigint,b:bigint)=>bigint;
|
|
159
|
+
public abstract sub: typeof this.add;
|
|
160
|
+
public abstract mul: typeof this.add;
|
|
161
|
+
public abstract inv: (a:bigint)=>bigint;
|
|
162
|
+
|
|
163
|
+
public abstract verify(): void;
|
|
164
|
+
|
|
165
|
+
constructor(field:bigint,bitlen:bigint) {
|
|
166
|
+
this.modulus = field;
|
|
167
|
+
this.bitlen = bitlen;
|
|
168
|
+
this.verify();
|
|
169
|
+
|
|
170
|
+
return this;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
class PrimeField extends GF implements Igalois {
|
|
176
|
+
public add: (a:bigint,b:bigint)=>bigint;
|
|
177
|
+
public sub: typeof this.add;
|
|
178
|
+
public mul: typeof this.add;
|
|
179
|
+
public inv: (a:bigint)=>bigint;
|
|
118
180
|
|
|
119
181
|
public verify(): void {
|
|
120
182
|
if (!Util.isprime(this.modulus))
|
|
121
|
-
return fail(
|
|
183
|
+
return fail('error: p ∉ ℙ');
|
|
122
184
|
else if (Util.countbits(this.modulus) > this.bitlen)
|
|
123
|
-
return fail(
|
|
185
|
+
return fail('error: p ≮ 2ⁿ', this.bitlen);
|
|
124
186
|
|
|
125
187
|
return void 0;
|
|
126
188
|
}
|
|
127
189
|
|
|
128
190
|
constructor(field:bigint,bitlen:bigint) {
|
|
129
|
-
|
|
130
|
-
this.
|
|
131
|
-
this.
|
|
132
|
-
|
|
133
|
-
this.
|
|
134
|
-
this.sub = arithmetics(this.modulus, fieldops.$sub);
|
|
135
|
-
this.mul = arithmetics(this.modulus, fieldops.$mul);
|
|
136
|
-
this.div = arithmetics(this.modulus, fieldops.$div);
|
|
191
|
+
super(field,bitlen);
|
|
192
|
+
this.add = arithmeticsℤp(this.modulus, fieldops.$add);
|
|
193
|
+
this.sub = arithmeticsℤp(this.modulus, fieldops.$sub);
|
|
194
|
+
this.mul = arithmeticsℤp(this.modulus, fieldops.$mul);
|
|
195
|
+
this.inv = arithmeticsℤp(this.modulus, fieldops.$inv);
|
|
137
196
|
|
|
138
197
|
return this;
|
|
139
198
|
}
|
|
140
199
|
|
|
141
200
|
}
|
|
142
201
|
|
|
143
|
-
export { Util,
|
|
202
|
+
export { Util, PrimeField };
|
package/main.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/* main.ts */
|
|
2
2
|
import { Polynomial } from './polynomial.js';
|
|
3
|
+
import { Util, PrimeField } from './galois.js';
|
|
4
|
+
import { ECoverℤp } from './ellipticcurves.js';
|
|
3
5
|
let log;
|
|
4
6
|
log = console.log;
|
|
5
7
|
let p1;
|
|
@@ -20,4 +22,5 @@ p2 = new Polynomial({ tobject: 0n, x3: 1n, x2: 0n, x: 1n, 1: 1n }, 2n);
|
|
|
20
22
|
p3 = new Polynomial(1n << 254n, 2n);
|
|
21
23
|
log(p3, p3.eval());
|
|
22
24
|
// log(p3.eval());
|
|
25
|
+
export { Polynomial, Util, PrimeField, ECoverℤp };
|
|
23
26
|
//# sourceMappingURL=main.js.map
|
package/main.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/* main.ts */
|
|
2
2
|
import { Polynomial } from './polynomial.js';
|
|
3
|
+
import { Util,PrimeField } from './galois.js';
|
|
4
|
+
import { ECoverℤp } from './ellipticcurves.js';
|
|
3
5
|
|
|
4
6
|
let log:(...x:any[])=>void;
|
|
5
7
|
log = console.log;
|
|
@@ -26,3 +28,4 @@ p3 = new Polynomial(1n<<254n, 2n);
|
|
|
26
28
|
log(p3, p3.eval());
|
|
27
29
|
// log(p3.eval());
|
|
28
30
|
|
|
31
|
+
export { Polynomial,Util,PrimeField,ECoverℤp };
|