functionalscript 0.0.549 → 0.0.550
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/package.json +1 -1
- package/prime_field/module.f.cjs +54 -42
- package/prime_field/test.f.cjs +4 -3
- package/secp/module.f.cjs +119 -0
- package/secp/test.f.cjs +48 -0
package/package.json
CHANGED
package/prime_field/module.f.cjs
CHANGED
|
@@ -1,39 +1,54 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* readonly g: readonly[bigint, bigint]
|
|
7
|
-
* readonly n: bigint
|
|
8
|
-
* }} Curve
|
|
9
|
-
*/
|
|
1
|
+
const op = require('../types/function/operator/module.f.cjs')
|
|
2
|
+
|
|
3
|
+
/** @typedef {op.Reduce<bigint>} Reduce */
|
|
4
|
+
|
|
5
|
+
/** @typedef {op.Unary<bigint, bigint>} Unary*/
|
|
10
6
|
|
|
11
7
|
/**
|
|
12
8
|
* @typedef {{
|
|
9
|
+
* readonly p: bigint
|
|
13
10
|
* readonly middle: bigint
|
|
14
11
|
* readonly max: bigint
|
|
15
|
-
* readonly neg:
|
|
16
|
-
* readonly sub:
|
|
17
|
-
* readonly add:
|
|
18
|
-
* readonly abs:
|
|
19
|
-
* readonly mul:
|
|
20
|
-
* readonly reciprocal:
|
|
21
|
-
* readonly div:
|
|
22
|
-
* readonly pow:
|
|
23
|
-
* readonly
|
|
12
|
+
* readonly neg: Unary
|
|
13
|
+
* readonly sub: Reduce
|
|
14
|
+
* readonly add: Reduce
|
|
15
|
+
* readonly abs: Unary
|
|
16
|
+
* readonly mul: Reduce
|
|
17
|
+
* readonly reciprocal: Unary
|
|
18
|
+
* readonly div: Reduce
|
|
19
|
+
* readonly pow: Reduce
|
|
20
|
+
* readonly pow2: Unary
|
|
21
|
+
* readonly pow3: Unary
|
|
24
22
|
* }} PrimeField
|
|
25
23
|
*/
|
|
26
24
|
|
|
25
|
+
/** @type {<T>(zero: T, add: op.Reduce<T>) => (a: T) => (n: bigint) => T} */
|
|
26
|
+
const scalar_mul = (zero, add) => a => n => {
|
|
27
|
+
let ai = a
|
|
28
|
+
let ni = n
|
|
29
|
+
let result = zero
|
|
30
|
+
while (true) {
|
|
31
|
+
if ((ni & 1n) === 1n) {
|
|
32
|
+
result = add(result)(ai)
|
|
33
|
+
}
|
|
34
|
+
ni >>= 1n
|
|
35
|
+
if (ni === 0n) {
|
|
36
|
+
return result
|
|
37
|
+
}
|
|
38
|
+
ai = add(ai)(ai)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
27
42
|
/** @type {(p: bigint) => PrimeField} */
|
|
28
43
|
const prime_field = p => {
|
|
29
|
-
/** @type {
|
|
44
|
+
/** @type {Reduce} */
|
|
30
45
|
const sub = a => b => {
|
|
31
46
|
const r = a - b
|
|
32
47
|
return r < 0 ? r + p : r
|
|
33
48
|
}
|
|
34
|
-
/** @type {
|
|
49
|
+
/** @type {Reduce} */
|
|
35
50
|
const mul = a => b => a * b % p
|
|
36
|
-
/** @type {
|
|
51
|
+
/** @type {Unary} */
|
|
37
52
|
const reciprocal = a => {
|
|
38
53
|
if (a === 0n) { throw '1/0' }
|
|
39
54
|
let a1 = a
|
|
@@ -52,23 +67,12 @@ const prime_field = p => {
|
|
|
52
67
|
return f1
|
|
53
68
|
}
|
|
54
69
|
const middle = p >> 1n
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
/** @type {
|
|
58
|
-
const pow =
|
|
59
|
-
let result = 1n
|
|
60
|
-
while (true) {
|
|
61
|
-
if ((n & 1n) === 1n) {
|
|
62
|
-
result = mul(result)(a)
|
|
63
|
-
}
|
|
64
|
-
n >>= 1n
|
|
65
|
-
if (n === 0n) {
|
|
66
|
-
return result
|
|
67
|
-
}
|
|
68
|
-
a = mul(a)(a)
|
|
69
|
-
}
|
|
70
|
-
}
|
|
70
|
+
/** @type {Unary} */
|
|
71
|
+
const pow2 = a => mul(a)(a)
|
|
72
|
+
/** @type {Reduce} */
|
|
73
|
+
const pow = scalar_mul(1n, mul)
|
|
71
74
|
return {
|
|
75
|
+
p,
|
|
72
76
|
middle,
|
|
73
77
|
max: p - 1n,
|
|
74
78
|
neg: a => a === 0n ? 0n : p - a,
|
|
@@ -82,13 +86,21 @@ const prime_field = p => {
|
|
|
82
86
|
reciprocal,
|
|
83
87
|
div: a => b => mul(a)(reciprocal(b)),
|
|
84
88
|
pow,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return mul(result)(result) === a ? result : null
|
|
88
|
-
}
|
|
89
|
+
pow2,
|
|
90
|
+
pow3: a => mul(a)(pow2(a))
|
|
89
91
|
}
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
module.exports = {
|
|
93
|
-
|
|
95
|
+
scalar_mul,
|
|
96
|
+
prime_field,
|
|
97
|
+
/** @type {(f: PrimeField) => (a: bigint) => bigint|null} */
|
|
98
|
+
sqrt: ({p, mul, pow }) => {
|
|
99
|
+
if ((p & 3n) !== 3n) { throw 'sqrt' }
|
|
100
|
+
const sqrt_k = (p + 1n) >> 2n
|
|
101
|
+
return a => {
|
|
102
|
+
const result = pow(a)(sqrt_k)
|
|
103
|
+
return mul(result)(result) === a ? result : null
|
|
104
|
+
}
|
|
105
|
+
}
|
|
94
106
|
}
|
package/prime_field/test.f.cjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
const { prime_field } = require('./module.f.cjs')
|
|
1
|
+
const { prime_field, sqrt } = require('./module.f.cjs')
|
|
2
2
|
|
|
3
3
|
module.exports = {
|
|
4
4
|
prime_field_test: () => {
|
|
5
5
|
const p = 0xffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_fffffffe_fffffc2fn;
|
|
6
6
|
const f = prime_field(p)
|
|
7
|
+
const sqrt_f = sqrt(f)
|
|
7
8
|
return {
|
|
8
9
|
neg: () => {
|
|
9
10
|
if (f.neg(0n) !== 0n) { throw '-0' }
|
|
@@ -41,7 +42,7 @@ module.exports = {
|
|
|
41
42
|
// a^(p-1) % p = 1
|
|
42
43
|
if (f.abs(f.pow(a)(f.middle)) !== 1n) { throw '**middle' }
|
|
43
44
|
if (f.pow(a)(f.sub(f.max)(1n)) !== f.reciprocal(a)) { throw '**(max-1)' }
|
|
44
|
-
if (f.pow(a)(f.max) !== 1n) { throw '**max
|
|
45
|
+
if (f.pow(a)(f.max) !== 1n) { throw '**max' }
|
|
45
46
|
}
|
|
46
47
|
// 0
|
|
47
48
|
if (f.pow(0n)(0n) !== 1n) { throw '0**0'}
|
|
@@ -70,7 +71,7 @@ module.exports = {
|
|
|
70
71
|
/** @type {(a: bigint) => void} */
|
|
71
72
|
const test = a => {
|
|
72
73
|
const a2 = f.mul(a)(a)
|
|
73
|
-
const s =
|
|
74
|
+
const s = sqrt_f(a2)
|
|
74
75
|
if (s !== null && f.abs(s) !== f.abs(a)) { throw 'sqrt' }
|
|
75
76
|
}
|
|
76
77
|
let i = 1n
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
const op = require('../types/function/operator/module.f.cjs')
|
|
2
|
+
const pf = require('../prime_field/module.f.cjs')
|
|
3
|
+
const { scalar_mul, prime_field, sqrt } = pf
|
|
4
|
+
|
|
5
|
+
/** @typedef {readonly[bigint, bigint]} Point2D */
|
|
6
|
+
|
|
7
|
+
/** @typedef {Point2D|null} Point */
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {{
|
|
11
|
+
* readonly p: bigint
|
|
12
|
+
* readonly a: readonly[bigint, bigint]
|
|
13
|
+
* readonly g: readonly[bigint, bigint]
|
|
14
|
+
* readonly n: bigint
|
|
15
|
+
* }} Init
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @typedef {{
|
|
20
|
+
* readonly pf: pf.PrimeField
|
|
21
|
+
* readonly nf: pf.PrimeField
|
|
22
|
+
* readonly y2: (x: bigint) => bigint
|
|
23
|
+
* readonly y: (x: bigint) => bigint|null
|
|
24
|
+
* readonly neg: (a: Point) => Point
|
|
25
|
+
* readonly add: op.Reduce<Point>
|
|
26
|
+
* readonly mul: (a: Point) => (n: bigint) => Point
|
|
27
|
+
* }} Curve
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/** @type {(i: Init) => Curve} */
|
|
31
|
+
const curve = ({ p, a: [a0, a1], n }) => {
|
|
32
|
+
const pf = prime_field(p)
|
|
33
|
+
const { pow2, pow3, sub, add, mul, neg, div } = pf
|
|
34
|
+
const mul3 = mul(3n)
|
|
35
|
+
const mul2 = mul(2n)
|
|
36
|
+
const addA1 = add(a1)
|
|
37
|
+
const mulA1 = mul(a1)
|
|
38
|
+
const addA0 = add(a0)
|
|
39
|
+
// y**2 = a1*x**3 + a0
|
|
40
|
+
/** @type {(x: bigint) => bigint} */
|
|
41
|
+
const y2 = x => addA0(add(pow3(x))(mulA1(x)))
|
|
42
|
+
/** @type {op.Reduce<Point>} */
|
|
43
|
+
const addPoint = p => q => {
|
|
44
|
+
if (p === null) {
|
|
45
|
+
return q
|
|
46
|
+
}
|
|
47
|
+
if (q === null) {
|
|
48
|
+
return p
|
|
49
|
+
}
|
|
50
|
+
const [px, py] = p
|
|
51
|
+
const [qx, qy] = q
|
|
52
|
+
const md = px === qx
|
|
53
|
+
// (3 * px ** 2 + a1) / (2 * py)
|
|
54
|
+
? py !== qy || py === 0n ? null : [addA1(mul3(pow2(px))), mul2(py)]
|
|
55
|
+
// (py - qy) / (px - qx)
|
|
56
|
+
: [sub(py)(qy), sub(px)(qx)]
|
|
57
|
+
if (md === null) {
|
|
58
|
+
return null
|
|
59
|
+
}
|
|
60
|
+
const [ma, mb] = md
|
|
61
|
+
const m = div(ma)(mb)
|
|
62
|
+
// m ** 2 - px - qx
|
|
63
|
+
const rx = sub(pow2(m))(add(px)(qx))
|
|
64
|
+
// [rx, m * (px - rx) - py]
|
|
65
|
+
return [rx, sub(mul(m)(sub(px)(rx)))(py)]
|
|
66
|
+
}
|
|
67
|
+
const sqrt_p = sqrt(pf)
|
|
68
|
+
return {
|
|
69
|
+
pf,
|
|
70
|
+
nf: prime_field(n),
|
|
71
|
+
y2,
|
|
72
|
+
y: x => sqrt_p(y2(x)),
|
|
73
|
+
neg: p => {
|
|
74
|
+
if (p === null) {
|
|
75
|
+
return null
|
|
76
|
+
}
|
|
77
|
+
const [x, y] = p
|
|
78
|
+
return [x, neg(y)]
|
|
79
|
+
},
|
|
80
|
+
add: addPoint,
|
|
81
|
+
mul: scalar_mul(null, addPoint)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = {
|
|
86
|
+
curve,
|
|
87
|
+
/** @type {(a: Point) => (b: Point) => boolean} */
|
|
88
|
+
eq: a => b => {
|
|
89
|
+
if (a === null || b === null) {
|
|
90
|
+
return a === b
|
|
91
|
+
}
|
|
92
|
+
const [ax, ay] = a
|
|
93
|
+
const [bx, by] = b
|
|
94
|
+
return ax === bx && ay === by
|
|
95
|
+
},
|
|
96
|
+
/** @type {Init} */
|
|
97
|
+
secp256k1: {
|
|
98
|
+
p: 0xffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_fffffffe_fffffc2fn,
|
|
99
|
+
a: [7n, 0n],
|
|
100
|
+
g: [
|
|
101
|
+
0x79be667e_f9dcbbac_55a06295_ce870b07_029bfcdb_2dce28d9_59f2815b_16f81798n,
|
|
102
|
+
0x483ada77_26a3c465_5da4fbfc_0e1108a8_fd17b448_a6855419_9c47d08f_fb10d4b8n
|
|
103
|
+
],
|
|
104
|
+
n: 0xffffffff_ffffffff_ffffffff_fffffffe_baaedce6_af48a03b_bfd25e8c_d0364141n,
|
|
105
|
+
},
|
|
106
|
+
/** @type {Init} */
|
|
107
|
+
secp192r1: {
|
|
108
|
+
p: 0xffffffff_ffffffff_ffffffff_fffffffe_ffffffff_ffffffffn,
|
|
109
|
+
a: [
|
|
110
|
+
0x64210519_e59c80e7_0fa7e9ab_72243049_feb8deec_c146b9b1n,
|
|
111
|
+
0xffffffff_ffffffff_ffffffff_fffffffe_ffffffff_fffffffcn
|
|
112
|
+
],
|
|
113
|
+
g: [
|
|
114
|
+
0x188da80e_b03090f6_7cbf20eb_43a18800_f4ff0afd_82ff1012n,
|
|
115
|
+
0x07192b95_ffc8da78_631011ed_6b24cdd5_73f977a1_1e794811n
|
|
116
|
+
],
|
|
117
|
+
n: 0xffffffff_ffffffff_ffffffff_99def836_146bc9b1_b4d22831n,
|
|
118
|
+
},
|
|
119
|
+
}
|
package/secp/test.f.cjs
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const m = require('./module.f.cjs')
|
|
2
|
+
const { curve, secp256k1, secp192r1, eq } = m
|
|
3
|
+
|
|
4
|
+
module.exports = {
|
|
5
|
+
test: () => {
|
|
6
|
+
/** @type {(c: m.Init) => void} */
|
|
7
|
+
const test_curve = c => {
|
|
8
|
+
const { g } = c
|
|
9
|
+
const { mul, neg, pf: { abs }, y: yf, nf: { p: n } } = curve(c)
|
|
10
|
+
/** @type {(p: m.Point) => void} */
|
|
11
|
+
const point_check = p => {
|
|
12
|
+
if (p === null) { throw 'null' }
|
|
13
|
+
const [x, y] = p
|
|
14
|
+
const ye = yf(x)
|
|
15
|
+
if (ye === null) { throw 'null' }
|
|
16
|
+
if (abs(ye) !== abs(y)) { throw 'ye' }
|
|
17
|
+
}
|
|
18
|
+
point_check(g)
|
|
19
|
+
point_check(neg(g))
|
|
20
|
+
/** @type {(p: m.Point) => void} */
|
|
21
|
+
const test_mul = p => {
|
|
22
|
+
if (mul(p)(0n) !== null) { throw 'O' }
|
|
23
|
+
if (mul(p)(1n) !== p) { throw 'p' }
|
|
24
|
+
if (mul(p)(n) !== null) { throw 'n' }
|
|
25
|
+
const pn = neg(p)
|
|
26
|
+
if (!eq(mul(p)(n - 1n))(pn)) { throw 'n - 1' }
|
|
27
|
+
/** @type {(s: bigint) => void} */
|
|
28
|
+
const f = s => {
|
|
29
|
+
const r = mul(p)(s)
|
|
30
|
+
point_check(r)
|
|
31
|
+
const rn = mul(pn)(s)
|
|
32
|
+
point_check(rn)
|
|
33
|
+
if (!eq(r)(neg(rn))) { throw 'r != -rn' }
|
|
34
|
+
}
|
|
35
|
+
f(2n)
|
|
36
|
+
f(3n)
|
|
37
|
+
f(4n << 128n)
|
|
38
|
+
f((5n << 128n) + 6n)
|
|
39
|
+
f(7n << 128n)
|
|
40
|
+
f((8n << 128n) + 9n)
|
|
41
|
+
}
|
|
42
|
+
test_mul(g)
|
|
43
|
+
test_mul(neg(g))
|
|
44
|
+
}
|
|
45
|
+
test_curve(secp256k1)
|
|
46
|
+
test_curve(secp192r1)
|
|
47
|
+
}
|
|
48
|
+
}
|