functionalscript 0.8.0 → 0.8.2
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/bnf/data/module.f.d.ts +6 -0
- package/bnf/data/module.f.js +57 -4
- package/bnf/data/test.f.d.ts +1 -0
- package/bnf/data/test.f.js +67 -1
- package/ci/module.f.d.ts +3 -0
- package/ci/module.f.js +169 -0
- package/ci/module.js +3 -0
- package/crypto/hmac/module.f.d.ts +5 -4
- package/crypto/hmac/module.f.js +9 -18
- package/crypto/hmac/test.f.d.ts +1 -0
- package/crypto/hmac/test.f.js +16 -8
- package/crypto/secp/module.f.d.ts +14 -11
- package/crypto/secp/module.f.js +33 -13
- package/crypto/secp/test.f.js +12 -13
- package/crypto/sha2/module.f.d.ts +11 -5
- package/crypto/sha2/module.f.js +4 -3
- package/crypto/sha2/test.f.d.ts +4 -1
- package/crypto/sha2/test.f.js +41 -31
- package/crypto/sign/module.f.d.ts +17 -4
- package/crypto/sign/module.f.js +141 -46
- package/crypto/sign/test.f.d.ts +11 -1
- package/crypto/sign/test.f.js +631 -1
- package/dev/tf/all.test.js +9 -1
- package/djs/ast/module.f.d.ts +3 -3
- package/djs/ast/test.f.js +7 -8
- package/djs/parser/module.f.d.ts +3 -3
- package/djs/parser/module.f.js +4 -4
- package/djs/parser/test.f.js +76 -77
- package/djs/serializer/module.f.d.ts +8 -8
- package/djs/serializer/module.f.js +4 -7
- package/djs/serializer/test.f.js +8 -9
- package/djs/tokenizer/module.f.d.ts +2 -2
- package/djs/tokenizer/module.f.js +3 -5
- package/djs/tokenizer/test.f.js +8 -10
- package/djs/transpiler/module.f.d.ts +3 -3
- package/djs/transpiler/module.f.js +2 -0
- package/fsc/bnf.f.d.ts +1 -1
- package/fsc/bnf.f.js +39 -51
- package/fsc/json.f.d.ts +1 -1
- package/fsc/json.f.js +56 -81
- package/fsc/test.f.js +4 -6
- package/fsm/module.f.js +3 -3
- package/fsm/test.f.js +21 -25
- package/html/module.f.js +17 -4
- package/html/test.f.d.ts +7 -0
- package/html/test.f.js +37 -0
- package/issues/031-json.f.d.ts +1 -0
- package/js/tokenizer/module.f.d.ts +4 -4
- package/js/tokenizer/module.f.js +12 -17
- package/js/tokenizer/test.f.js +9 -11
- package/json/module.f.d.ts +6 -6
- package/json/module.f.js +5 -10
- package/json/parser/module.f.d.ts +4 -4
- package/json/parser/module.f.js +7 -4
- package/json/parser/test.f.js +47 -49
- package/json/serializer/module.f.d.ts +6 -6
- package/json/serializer/module.f.js +3 -2
- package/json/serializer/test.f.js +13 -13
- package/json/test.f.js +13 -15
- package/json/tokenizer/module.f.d.ts +4 -4
- package/json/tokenizer/module.f.js +6 -7
- package/json/tokenizer/test.f.js +7 -9
- package/nanvm-lib/tests/vm/test.f.js +1 -1
- package/package.json +5 -5
- package/path/module.f.d.ts +3 -2
- package/text/ascii/test.f.js +2 -2
- package/text/module.f.d.ts +3 -2
- package/text/module.f.js +2 -2
- package/text/test.f.js +3 -3
- package/text/utf16/test.f.js +2 -2
- package/text/utf8/test.f.js +2 -2
- package/types/array/test.f.js +2 -2
- package/types/bigint/module.f.d.ts +6 -3
- package/types/bigint/module.f.js +12 -11
- package/types/bigint/test.f.d.ts +2 -0
- package/types/bigint/test.f.js +21 -2
- package/types/bit_vec/module.f.d.ts +66 -34
- package/types/bit_vec/module.f.js +97 -32
- package/types/bit_vec/test.f.d.ts +7 -0
- package/types/bit_vec/test.f.js +283 -62
- package/types/btree/find/test.f.js +9 -8
- package/types/btree/remove/test.f.js +4 -4
- package/types/btree/set/test.f.js +4 -4
- package/types/btree/test.f.js +7 -7
- package/types/byte_set/test.f.js +2 -2
- package/types/function/compare/module.f.d.ts +15 -1
- package/types/function/compare/module.f.js +1 -1
- package/types/function/compare/test.f.js +37 -4
- package/types/list/test.f.js +93 -93
- package/types/monoid/module.f.d.ts +4 -4
- package/types/monoid/module.f.js +3 -3
- package/types/monoid/test.f.js +3 -3
- package/types/nominal/module.f.d.ts +5 -0
- package/types/nominal/module.f.js +4 -0
- package/types/nominal/test.f.d.ts +5 -0
- package/types/nominal/test.f.js +53 -0
- package/types/number/module.f.js +2 -2
- package/{crypto → types}/prime_field/module.f.d.ts +2 -2
- package/{crypto → types}/prime_field/module.f.js +5 -4
- package/{crypto → types}/prime_field/test.f.js +13 -13
- package/types/range_map/test.f.js +21 -21
- package/types/sorted_list/test.f.js +10 -10
- package/types/sorted_set/test.f.js +14 -14
- package/types/string/module.f.js +2 -2
- package/types/string_set/module.f.js +3 -3
- package/bnf/func/module.f.d.ts +0 -148
- package/bnf/func/module.f.js +0 -132
- package/bnf/func/test.f.d.ts +0 -12
- package/bnf/func/test.f.js +0 -171
- package/bnf/func/testlib.f.d.ts +0 -25
- package/bnf/func/testlib.f.js +0 -150
- /package/{issues/31-json.f.d.ts → ci/module.d.ts} +0 -0
- /package/issues/{31-json.f.js → 031-json.f.js} +0 -0
- /package/{crypto → types}/prime_field/test.f.d.ts +0 -0
package/crypto/secp/module.f.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { prime_field, sqrt } from "
|
|
1
|
+
import { prime_field, sqrt } from "../../types/prime_field/module.f.js";
|
|
2
2
|
import { repeat } from "../../types/monoid/module.f.js";
|
|
3
3
|
/**
|
|
4
4
|
* Constructs an elliptic curve with the given initialization parameters.
|
|
@@ -20,7 +20,7 @@ import { repeat } from "../../types/monoid/module.f.js";
|
|
|
20
20
|
* const mulPoint = curveInstance.mul([1n, 1n])(3n); // Multiply a point by 3
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
|
-
export const curve = ({ p, a: [a0, a1], n }) => {
|
|
23
|
+
export const curve = ({ p, a: [a0, a1], n, g }) => {
|
|
24
24
|
const pf = prime_field(p);
|
|
25
25
|
const { pow2, pow3, sub, add, mul, neg, div } = pf;
|
|
26
26
|
const mul3 = mul(3n);
|
|
@@ -60,6 +60,7 @@ export const curve = ({ p, a: [a0, a1], n }) => {
|
|
|
60
60
|
return {
|
|
61
61
|
pf,
|
|
62
62
|
nf: prime_field(n),
|
|
63
|
+
g,
|
|
63
64
|
y2,
|
|
64
65
|
y: x => sqrt_p(y2(x)),
|
|
65
66
|
neg: p => {
|
|
@@ -73,7 +74,7 @@ export const curve = ({ p, a: [a0, a1], n }) => {
|
|
|
73
74
|
mul: repeat({ identity: null, operation: addPoint })
|
|
74
75
|
};
|
|
75
76
|
};
|
|
76
|
-
export const eq =
|
|
77
|
+
export const eq = a => b => {
|
|
77
78
|
if (a === null || b === null) {
|
|
78
79
|
return a === b;
|
|
79
80
|
}
|
|
@@ -83,8 +84,9 @@ export const eq = (a) => (b) => {
|
|
|
83
84
|
};
|
|
84
85
|
/**
|
|
85
86
|
* https://neuromancer.sk/std/secg/secp192r1
|
|
87
|
+
* NIST P-192
|
|
86
88
|
*/
|
|
87
|
-
export const secp192r1 = {
|
|
89
|
+
export const secp192r1 = curve({
|
|
88
90
|
p: 0xfffffffffffffffffffffffffffffffeffffffffffffffffn,
|
|
89
91
|
a: [
|
|
90
92
|
0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1n,
|
|
@@ -95,12 +97,29 @@ export const secp192r1 = {
|
|
|
95
97
|
0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811n
|
|
96
98
|
],
|
|
97
99
|
n: 0xffffffffffffffffffffffff99def836146bc9b1b4d22831n,
|
|
98
|
-
};
|
|
100
|
+
});
|
|
101
|
+
// The curve doesn't have a simple square root function.
|
|
102
|
+
// /**
|
|
103
|
+
// * https://std.neuromancer.sk/nist/P-224
|
|
104
|
+
// * NIST P-224
|
|
105
|
+
// */
|
|
106
|
+
// export const secp224r1: Curve = curve({
|
|
107
|
+
// p: 0xffffffff_ffffffff_ffffffff_ffffffff_00000000_00000000_00000001n,
|
|
108
|
+
// a: [
|
|
109
|
+
// 0xb4050a85_0c04b3ab_f5413256_5044b0b7_d7bfd8ba_270b3943_2355ffb4n,
|
|
110
|
+
// 0xffffffff_ffffffff_ffffffff_fffffffe_ffffffff_ffffffff_fffffffen,
|
|
111
|
+
// ],
|
|
112
|
+
// g: [
|
|
113
|
+
// 0xb70e0cbd_6bb4bf7f_321390b9_4a03c1d3_56c21122_343280d6_115c1d21n,
|
|
114
|
+
// 0xbd376388_b5f723fb_4c22dfe6_cd4375a0_5a074764_44d58199_85007e34n,
|
|
115
|
+
// ],
|
|
116
|
+
// n: 0xffffffff_ffffffff_ffffffff_ffff16a2_e0b8f03e_13dd2945_5c5c2a3dn,
|
|
117
|
+
// })
|
|
99
118
|
/**
|
|
100
119
|
* https://en.bitcoin.it/wiki/Secp256k1
|
|
101
120
|
* https://neuromancer.sk/std/secg/secp256k1
|
|
102
121
|
*/
|
|
103
|
-
export const secp256k1 = {
|
|
122
|
+
export const secp256k1 = curve({
|
|
104
123
|
p: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn,
|
|
105
124
|
a: [7n, 0n],
|
|
106
125
|
g: [
|
|
@@ -108,11 +127,12 @@ export const secp256k1 = {
|
|
|
108
127
|
0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n
|
|
109
128
|
],
|
|
110
129
|
n: 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n,
|
|
111
|
-
};
|
|
130
|
+
});
|
|
112
131
|
/**
|
|
113
132
|
* https://neuromancer.sk/std/secg/secp256r1
|
|
133
|
+
* NIST P-256
|
|
114
134
|
*/
|
|
115
|
-
export const secp256r1 = {
|
|
135
|
+
export const secp256r1 = curve({
|
|
116
136
|
p: 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffffn,
|
|
117
137
|
a: [
|
|
118
138
|
0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604bn, //< b
|
|
@@ -123,11 +143,11 @@ export const secp256r1 = {
|
|
|
123
143
|
0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5n, //< y
|
|
124
144
|
],
|
|
125
145
|
n: 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551n,
|
|
126
|
-
};
|
|
146
|
+
});
|
|
127
147
|
/**
|
|
128
148
|
* https://neuromancer.sk/std/secg/secp384r1
|
|
129
149
|
*/
|
|
130
|
-
export const secp384r1 = {
|
|
150
|
+
export const secp384r1 = curve({
|
|
131
151
|
p: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffffn,
|
|
132
152
|
a: [
|
|
133
153
|
0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aefn, //< b
|
|
@@ -138,11 +158,11 @@ export const secp384r1 = {
|
|
|
138
158
|
0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5fn, //< y
|
|
139
159
|
],
|
|
140
160
|
n: 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973n,
|
|
141
|
-
};
|
|
161
|
+
});
|
|
142
162
|
/**
|
|
143
163
|
* https://neuromancer.sk/std/secg/secp521r1
|
|
144
164
|
*/
|
|
145
|
-
export const secp521r1 = {
|
|
165
|
+
export const secp521r1 = curve({
|
|
146
166
|
p: 0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn,
|
|
147
167
|
a: [
|
|
148
168
|
0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00n, //< b
|
|
@@ -153,4 +173,4 @@ export const secp521r1 = {
|
|
|
153
173
|
0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650n,
|
|
154
174
|
],
|
|
155
175
|
n: 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409n
|
|
156
|
-
};
|
|
176
|
+
});
|
package/crypto/secp/test.f.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { prime_field } from "
|
|
1
|
+
import { prime_field } from "../../types/prime_field/module.f.js";
|
|
2
2
|
import { curve, secp256k1, secp192r1, secp256r1, eq, secp384r1, secp521r1 } from "./module.f.js";
|
|
3
3
|
const poker = (param) => () => {
|
|
4
4
|
// (c ^ x) ^ y = c ^ (x * y)
|
|
5
5
|
// c ^ ((x * y) * (1/x * 1/y)) = c
|
|
6
|
-
const { g, n } = param
|
|
7
|
-
const { mul, y } =
|
|
8
|
-
const f = (m) => (pList) => pList.map(
|
|
6
|
+
// const { g, n } = param
|
|
7
|
+
const { mul, y, nf: { p: n } } = param;
|
|
8
|
+
const f = (m) => (pList) => pList.map(mul(m));
|
|
9
9
|
//
|
|
10
10
|
const pf = prime_field(n);
|
|
11
11
|
// 0 1 2 3 4 5 6 7
|
|
@@ -65,12 +65,11 @@ export default {
|
|
|
65
65
|
// Access curve operations
|
|
66
66
|
const point = c.add([1n, 1n])([2n, 5n]); // Add two points
|
|
67
67
|
const negPoint = c.neg([1n, 1n]); // Negate a point
|
|
68
|
-
const mulPoint = c.mul([1n, 1n])
|
|
68
|
+
const mulPoint = c.mul(3n)([1n, 1n]); // Multiply a point by 3
|
|
69
69
|
},
|
|
70
70
|
test: () => {
|
|
71
71
|
const test_curve = c => {
|
|
72
|
-
const { g } = c;
|
|
73
|
-
const { mul, neg, pf: { abs }, y: yf, nf: { p: n } } = curve(c);
|
|
72
|
+
const { mul, neg, pf: { abs }, y: yf, nf: { p: n }, g } = c;
|
|
74
73
|
const point_check = (p) => {
|
|
75
74
|
if (p === null) {
|
|
76
75
|
throw 'p === null';
|
|
@@ -87,23 +86,23 @@ export default {
|
|
|
87
86
|
point_check(g);
|
|
88
87
|
point_check(neg(g));
|
|
89
88
|
const test_mul = (p) => {
|
|
90
|
-
if (mul(
|
|
89
|
+
if (mul(0n)(p) !== null) {
|
|
91
90
|
throw 'O';
|
|
92
91
|
}
|
|
93
|
-
if (mul(
|
|
92
|
+
if (mul(1n)(p) !== p) {
|
|
94
93
|
throw 'p';
|
|
95
94
|
}
|
|
96
|
-
if (mul(
|
|
95
|
+
if (mul(n)(p) !== null) {
|
|
97
96
|
throw 'n';
|
|
98
97
|
}
|
|
99
98
|
const pn = neg(p);
|
|
100
|
-
if (!eq(mul(
|
|
99
|
+
if (!eq(mul(n - 1n)(p))(pn)) {
|
|
101
100
|
throw 'n - 1';
|
|
102
101
|
}
|
|
103
102
|
const f = s => {
|
|
104
|
-
const r = mul(
|
|
103
|
+
const r = mul(s)(p);
|
|
105
104
|
point_check(r);
|
|
106
|
-
const rn = mul(
|
|
105
|
+
const rn = mul(s)(pn);
|
|
107
106
|
point_check(rn);
|
|
108
107
|
if (!eq(r)(neg(rn))) {
|
|
109
108
|
throw 'r != -rn';
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* See https://www.rfc-editor.org/rfc/rfc6234
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
1
6
|
import type { Array16, Array8 } from '../../types/array/module.f.ts';
|
|
2
7
|
import { type Vec } from '../../types/bit_vec/module.f.ts';
|
|
8
|
+
import type { Fold } from '../../types/function/operator/module.f.ts';
|
|
3
9
|
import { type List } from '../../types/list/module.f.ts';
|
|
4
10
|
export type V8 = Array8<bigint>;
|
|
5
11
|
export type V16 = Array16<bigint>;
|
|
@@ -25,8 +31,8 @@ export type Base = {
|
|
|
25
31
|
readonly chunkLength: bigint;
|
|
26
32
|
readonly compress: (i: V8) => (u: bigint) => V8;
|
|
27
33
|
readonly fromV8: (a: V8) => bigint;
|
|
28
|
-
readonly append:
|
|
29
|
-
readonly end: (hashLength: bigint) => (state: State) =>
|
|
34
|
+
readonly append: Fold<Vec, State>;
|
|
35
|
+
readonly end: (hashLength: bigint) => (state: State) => Vec;
|
|
30
36
|
};
|
|
31
37
|
/**
|
|
32
38
|
* SHA2. See https://en.wikipedia.org/wiki/SHA-2
|
|
@@ -56,18 +62,18 @@ export type Sha2 = {
|
|
|
56
62
|
/**
|
|
57
63
|
* Appends data to the state and returns the new state.
|
|
58
64
|
*
|
|
59
|
-
* @param state The current state.
|
|
60
65
|
* @param v The data to append.
|
|
66
|
+
* @param state The current state.
|
|
61
67
|
* @returns The new state after appending data.
|
|
62
68
|
*/
|
|
63
|
-
readonly append:
|
|
69
|
+
readonly append: Fold<Vec, State>;
|
|
64
70
|
/**
|
|
65
71
|
* Finalizes the hash and returns the result as a bigint.
|
|
66
72
|
*
|
|
67
73
|
* @param state The final state.
|
|
68
74
|
* @returns The resulting hash.
|
|
69
75
|
*/
|
|
70
|
-
readonly end: (state: State) =>
|
|
76
|
+
readonly end: (state: State) => Vec;
|
|
71
77
|
};
|
|
72
78
|
export declare const computeSync: ({ append, init, end }: Sha2) => (list: List<Vec>) => Vec;
|
|
73
79
|
export declare const base32: Base;
|
package/crypto/sha2/module.f.js
CHANGED
|
@@ -115,13 +115,14 @@ const base = ({ logBitLen, k, bs0, bs1, ss0, ss1 }) => {
|
|
|
115
115
|
};
|
|
116
116
|
const chunkLength = bitLength << 4n; // * 16
|
|
117
117
|
const fromV8 = (a) => a.reduce((p, v) => (p << bitLength) | v);
|
|
118
|
-
|
|
118
|
+
// See https://www.rfc-editor.org/rfc/rfc6234#section-4
|
|
119
|
+
const lastChunkLength = chunkLength - 1n - (bitLength << 1n);
|
|
119
120
|
return {
|
|
120
121
|
bitLength,
|
|
121
122
|
chunkLength,
|
|
122
123
|
compress,
|
|
123
124
|
fromV8,
|
|
124
|
-
append: (
|
|
125
|
+
append: (v) => (state) => {
|
|
125
126
|
let { remainder, hash, len } = state;
|
|
126
127
|
remainder = concat(remainder)(v);
|
|
127
128
|
let remainderLen = length(remainder);
|
|
@@ -168,7 +169,7 @@ const sha2 = ({ append, end, chunkLength }, hash, hashLength) => ({
|
|
|
168
169
|
end: end(hashLength),
|
|
169
170
|
});
|
|
170
171
|
export const computeSync = ({ append, init, end }) => {
|
|
171
|
-
const f = fold(
|
|
172
|
+
const f = fold(append)(init);
|
|
172
173
|
return (list) => end(f(list));
|
|
173
174
|
};
|
|
174
175
|
export const base32 = base({
|
package/crypto/sha2/test.f.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ declare const _default: {
|
|
|
6
6
|
};
|
|
7
7
|
b64: () => {
|
|
8
8
|
s512: () => void;
|
|
9
|
-
|
|
9
|
+
s384: () => void;
|
|
10
10
|
s512x256: () => void;
|
|
11
11
|
s512x224: () => void;
|
|
12
12
|
};
|
|
@@ -24,5 +24,8 @@ declare const _default: {
|
|
|
24
24
|
8: () => void;
|
|
25
25
|
16: () => void;
|
|
26
26
|
};
|
|
27
|
+
padding: {
|
|
28
|
+
overflow: () => void;
|
|
29
|
+
};
|
|
27
30
|
};
|
|
28
31
|
export default _default;
|
package/crypto/sha2/test.f.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { utf8 } from "../../text/module.f.js";
|
|
2
|
+
import { repeat, uint, vec } from "../../types/bit_vec/module.f.js";
|
|
3
|
+
import { flip } from "../../types/function/module.f.js";
|
|
3
4
|
import { map } from "../../types/list/module.f.js";
|
|
4
|
-
import { repeat } from "../../types/monoid/module.f.js";
|
|
5
5
|
import { base32, base64, computeSync, sha224, sha256, sha384, sha512, sha512x224, sha512x256, } from "./module.f.js";
|
|
6
|
-
const {
|
|
7
|
-
const checkEmpty = ({ init, end }) => (x) => {
|
|
6
|
+
const checkEmpty = ({ init, end, hashLength }) => (x) => {
|
|
8
7
|
const result = end(init);
|
|
9
|
-
if (result !== x) {
|
|
8
|
+
if (result !== vec(hashLength)(x)) {
|
|
10
9
|
throw [result, x];
|
|
11
10
|
}
|
|
12
11
|
};
|
|
@@ -46,7 +45,7 @@ export default {
|
|
|
46
45
|
throw [result, x];
|
|
47
46
|
}
|
|
48
47
|
},
|
|
49
|
-
|
|
48
|
+
s384: () => {
|
|
50
49
|
const result = fromV8(compress(sha384.init.hash)(e)) >> 128n;
|
|
51
50
|
const x = 0x38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95bn;
|
|
52
51
|
if (result !== x) {
|
|
@@ -71,72 +70,83 @@ export default {
|
|
|
71
70
|
}
|
|
72
71
|
},
|
|
73
72
|
sha2: {
|
|
74
|
-
sha256: () => checkEmpty(sha256)(
|
|
75
|
-
sha224: () => checkEmpty(sha224)(
|
|
76
|
-
sha512: () => checkEmpty(sha512)(
|
|
77
|
-
sha384: () => checkEmpty(sha384)(
|
|
78
|
-
sha512x256: () => checkEmpty(sha512x256)(
|
|
79
|
-
sha512x224: () => checkEmpty(sha512x224)(
|
|
73
|
+
sha256: () => checkEmpty(sha256)(0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855n),
|
|
74
|
+
sha224: () => checkEmpty(sha224)(0xd14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42fn),
|
|
75
|
+
sha512: () => checkEmpty(sha512)(0xcf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3en),
|
|
76
|
+
sha384: () => checkEmpty(sha384)(0x38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95bn),
|
|
77
|
+
sha512x256: () => checkEmpty(sha512x256)(0xc672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967an),
|
|
78
|
+
sha512x224: () => checkEmpty(sha512x224)(0x6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4n),
|
|
80
79
|
},
|
|
81
80
|
utf8: [
|
|
82
81
|
() => {
|
|
83
|
-
const e =
|
|
82
|
+
const e = 0x730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525n;
|
|
84
83
|
{
|
|
85
|
-
const s =
|
|
84
|
+
const s = utf8("The quick brown fox jumps over the lazy dog");
|
|
86
85
|
const h = computeSync(sha224)([s]);
|
|
87
|
-
if (h !== e) {
|
|
86
|
+
if (uint(h) !== e) {
|
|
88
87
|
throw h;
|
|
89
88
|
}
|
|
90
89
|
}
|
|
91
90
|
{
|
|
92
91
|
const s = ['The', ' quick', ' brown', ' fox', ' jumps', ' over', ' the', ' lazy', ' dog'];
|
|
93
|
-
const h = computeSync(sha224)(map(
|
|
94
|
-
if (h !== e) {
|
|
92
|
+
const h = computeSync(sha224)(map(utf8)(s));
|
|
93
|
+
if (uint(h) !== e) {
|
|
95
94
|
throw h;
|
|
96
95
|
}
|
|
97
96
|
}
|
|
98
97
|
},
|
|
99
98
|
() => {
|
|
100
|
-
const s =
|
|
99
|
+
const s = utf8("The quick brown fox jumps over the lazy dog.");
|
|
101
100
|
const h = computeSync(sha224)([s]);
|
|
102
|
-
if (h !==
|
|
101
|
+
if (uint(h) !== 0x619cba8e8e05826e9b8c519c0a5c68f4fb653e8a3d8aa04bb2c8cd4cn) {
|
|
103
102
|
throw h;
|
|
104
103
|
}
|
|
105
104
|
},
|
|
106
105
|
() => {
|
|
107
|
-
const s =
|
|
108
|
-
if (s !==
|
|
106
|
+
const s = utf8("hello world");
|
|
107
|
+
if (uint(s) !== 0x68656c6c6f20776f726c64n) {
|
|
109
108
|
throw s;
|
|
110
109
|
}
|
|
111
110
|
let state = sha256.init;
|
|
112
|
-
state = sha256.append(
|
|
111
|
+
state = sha256.append(s)(state);
|
|
113
112
|
const h = sha256.end(state);
|
|
114
|
-
if (h !==
|
|
113
|
+
if (uint(h) !== 0xb94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9n) {
|
|
115
114
|
throw h;
|
|
116
115
|
}
|
|
117
116
|
}
|
|
118
117
|
],
|
|
119
118
|
fill: () => {
|
|
120
|
-
const times = repeat
|
|
119
|
+
const times = flip(repeat)(vec(32n)(0x31313131n));
|
|
121
120
|
return {
|
|
122
121
|
8: () => {
|
|
123
122
|
const r = times(8n);
|
|
124
123
|
let state = sha256.init;
|
|
125
|
-
state = sha256.append(
|
|
126
|
-
const h = sha256.end(state);
|
|
127
|
-
if (h >> 224n !==
|
|
124
|
+
state = sha256.append(r)(state);
|
|
125
|
+
const h = uint(sha256.end(state));
|
|
126
|
+
if (h >> 224n !== 0x8a83665fn) {
|
|
128
127
|
throw h;
|
|
129
128
|
}
|
|
130
129
|
},
|
|
131
130
|
16: () => {
|
|
132
131
|
const r = times(16n);
|
|
133
132
|
let state = sha256.init;
|
|
134
|
-
state = sha256.append(
|
|
133
|
+
state = sha256.append(r)(state);
|
|
135
134
|
const h = sha256.end(state);
|
|
136
|
-
if (h !==
|
|
135
|
+
if (uint(h) !== 0x3138bb9bc78df27c473ecfd1410f7bd45ebac1f59cf3ff9cfe4db77aab7aedd3n) {
|
|
137
136
|
throw h;
|
|
138
137
|
}
|
|
139
138
|
}
|
|
140
139
|
};
|
|
141
|
-
}
|
|
140
|
+
},
|
|
141
|
+
padding: {
|
|
142
|
+
overflow: () => {
|
|
143
|
+
const zero = vec(8n)(0n);
|
|
144
|
+
const msg = flip(repeat)(zero)(113n);
|
|
145
|
+
const h = computeSync(sha384)([msg]);
|
|
146
|
+
const x = 0x6be9af2cf3cd5dd12c8d9399ec2b34e66034fbd699d4e0221d39074172a380656089caafe8f39963f94cc7c0a07e3d21n;
|
|
147
|
+
if (uint(h) !== x) {
|
|
148
|
+
throw h;
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
},
|
|
142
152
|
};
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
+
import type { Array2 } from '../../types/array/module.f.ts';
|
|
1
2
|
import { type Vec } from '../../types/bit_vec/module.f.ts';
|
|
2
|
-
import {
|
|
3
|
-
import type
|
|
4
|
-
export
|
|
5
|
-
|
|
3
|
+
import type { Curve } from '../secp/module.f.ts';
|
|
4
|
+
import { type Sha2 } from '../sha2/module.f.ts';
|
|
5
|
+
export type All = {
|
|
6
|
+
readonly q: bigint;
|
|
7
|
+
readonly qlen: bigint;
|
|
8
|
+
readonly bits2int: (b: Vec) => bigint;
|
|
9
|
+
readonly int2octets: (x: bigint) => Vec;
|
|
10
|
+
readonly bits2octets: (b: Vec) => Vec;
|
|
11
|
+
};
|
|
12
|
+
export declare const all: (q: bigint) => All;
|
|
13
|
+
export declare const fromCurve: (c: Curve) => All;
|
|
14
|
+
export declare const concat: (...x: readonly Vec[]) => Vec;
|
|
15
|
+
export declare const computeK: (_: All) => (_: Sha2) => (x: bigint) => (m: Vec) => bigint;
|
|
16
|
+
type Signature = Array2<bigint>;
|
|
17
|
+
export declare const sign: (c: Curve) => (hf: Sha2) => (x: bigint) => (m: Vec) => Signature;
|
|
18
|
+
export {};
|
package/crypto/sign/module.f.js
CHANGED
|
@@ -1,53 +1,148 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { bitLength, divUp, roundUp } from "../../types/bigint/module.f.js";
|
|
2
|
+
import { empty, length, listToVec, msb, repeat, unpack, vec, vec8 } from "../../types/bit_vec/module.f.js";
|
|
2
3
|
import { hmac } from "../hmac/module.f.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
4
|
+
import { computeSync } from "../sha2/module.f.js";
|
|
5
|
+
// qlen to rlen
|
|
6
|
+
const roundUp8 = roundUp(8n);
|
|
7
|
+
const divUp8 = divUp(8n);
|
|
8
|
+
export const all = (q) => {
|
|
9
|
+
const qlen = bitLength(q);
|
|
10
|
+
const bits2int = (b) => {
|
|
11
|
+
const { length, uint } = unpack(b);
|
|
12
|
+
const diff = length - qlen;
|
|
13
|
+
return diff > 0n ? uint >> diff : uint;
|
|
14
|
+
};
|
|
15
|
+
const int2octets = vec(roundUp8(qlen));
|
|
16
|
+
return {
|
|
17
|
+
q,
|
|
18
|
+
qlen,
|
|
19
|
+
bits2int,
|
|
20
|
+
int2octets,
|
|
21
|
+
// since z2 < 2*q, we can use simple mod with `z1 < q ? z1 : z1 - q`
|
|
22
|
+
bits2octets: b => int2octets(bits2int(b) % q),
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export const fromCurve = (c) => all(c.nf.p);
|
|
26
|
+
const x01 = vec8(0x01n);
|
|
27
|
+
const x00 = vec8(0x00n);
|
|
28
|
+
const ltov = listToVec(msb);
|
|
29
|
+
export const concat = (...x) => ltov(x);
|
|
30
|
+
export const computeK = ({ q, bits2int, qlen, int2octets, bits2octets }) => hf => {
|
|
31
|
+
// TODO: Look at https://www.rfc-editor.org/rfc/rfc6979#section-3.3 to reformulate
|
|
32
|
+
// it using `HMAC_DRBG`.
|
|
33
|
+
const hmacf = hmac(hf);
|
|
34
|
+
// b. Set:
|
|
35
|
+
// V = 0x01 0x01 0x01 ... 0x01
|
|
36
|
+
// such that the length of V, in bits, is equal to 8*ceil(hlen/8).
|
|
37
|
+
// For instance, on an octet-based system, if H is SHA-256, then V
|
|
38
|
+
// is set to a sequence of 32 octets of value 1. Note that in this
|
|
39
|
+
// step and all subsequent steps, we use the same H function as the
|
|
40
|
+
// one used in step 'a' to process the input message; this choice
|
|
41
|
+
// will be discussed in more detail in Section 3.6.
|
|
42
|
+
const rep = repeat(divUp8(hf.hashLength));
|
|
43
|
+
const v0 = rep(x01);
|
|
44
|
+
// c. Set:
|
|
45
|
+
// K = 0x00 0x00 0x00 ... 0x00
|
|
46
|
+
// such that the length of K, in bits, is equal to 8*ceil(hlen/8).
|
|
47
|
+
const k0 = rep(x00);
|
|
48
|
+
//
|
|
49
|
+
return x => m => {
|
|
21
50
|
let v = v0;
|
|
22
|
-
k =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
51
|
+
let k = k0;
|
|
52
|
+
// a. Process m through the hash function H, yielding:
|
|
53
|
+
// h1 = H(m)
|
|
54
|
+
// (h1 is a sequence of hlen bits).
|
|
55
|
+
const h1 = computeSync(hf)([m]);
|
|
56
|
+
// d. Set:
|
|
57
|
+
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1))
|
|
58
|
+
// where '||' denotes concatenation.
|
|
59
|
+
const xh1 = concat(int2octets(x), bits2octets(h1));
|
|
60
|
+
k = hmacf(k)(concat(v, x00, xh1));
|
|
61
|
+
// e. Set:
|
|
62
|
+
// V = HMAC_K(V)
|
|
63
|
+
v = hmacf(k)(v);
|
|
64
|
+
// f. Set:
|
|
65
|
+
// K = HMAC_K(V || 0x01 || int2octets(x) || bits2octets(h1))
|
|
66
|
+
k = hmacf(k)(concat(v, x01, xh1));
|
|
67
|
+
// g. Set:
|
|
68
|
+
// V = HMAC_K(V)
|
|
69
|
+
v = hmacf(k)(v);
|
|
70
|
+
// h. Apply the following algorithm until a proper value is for `k`:
|
|
71
|
+
while (true) {
|
|
72
|
+
// h. Apply the following algorithm until a proper value is for `k`:
|
|
73
|
+
// 1. Set `T` to the empty sequence, so `tlen = 0`.
|
|
74
|
+
let t = empty;
|
|
75
|
+
// 2. while `tlen < qlen` do:
|
|
76
|
+
// - `V = HMAC_K(V)`
|
|
77
|
+
// - `T = T || V`
|
|
78
|
+
// Possible optimizations:
|
|
79
|
+
// - precompute number of iterations
|
|
80
|
+
// - `qlen` can't be 0, so we can avoid the first check and
|
|
81
|
+
// first concatenation.
|
|
82
|
+
while (length(t) < qlen) {
|
|
83
|
+
v = hmacf(k)(v);
|
|
84
|
+
t = concat(t, v);
|
|
85
|
+
}
|
|
86
|
+
// 3. Compute `k = bits2int(T)`. If `k` is not in `[1, q-1]` or `kG = 0` then
|
|
87
|
+
// - `K = HMAC_K(V || 0x00)`
|
|
88
|
+
// - `V = HMAC_K(V)`
|
|
89
|
+
// and loop (try to generate a new `T`, and so on). Return to step `1`.
|
|
90
|
+
const result = bits2int(t);
|
|
91
|
+
if (0n < result && result < q) {
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
k = hmacf(k)(concat(v, x00));
|
|
95
|
+
v = hmacf(k)(v);
|
|
96
|
+
}
|
|
27
97
|
};
|
|
28
98
|
};
|
|
29
|
-
export const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
99
|
+
export const sign = (c) => (hf) => (x) => (m) => {
|
|
100
|
+
// 2.4 Signature Generation
|
|
101
|
+
const { nf: { p: q, div }, g } = c;
|
|
102
|
+
const a = all(q);
|
|
103
|
+
const { bits2int } = a;
|
|
104
|
+
// The following steps are then applied:
|
|
105
|
+
//
|
|
106
|
+
// 1. H(m) is transformed into an integer modulo q using the bits2int
|
|
107
|
+
// transform and an extra modular reduction:
|
|
108
|
+
//
|
|
109
|
+
// h = bits2int(H(m)) mod q
|
|
110
|
+
//
|
|
111
|
+
// As was noted in the description of bits2octets, the extra modular
|
|
112
|
+
// reduction is no more than a conditional subtraction.
|
|
113
|
+
const hm = computeSync(hf)([m]);
|
|
114
|
+
const h = bits2int(hm) % q;
|
|
115
|
+
// 2. A random value modulo q, dubbed k, is generated. That value
|
|
116
|
+
// shall not be 0; hence, it lies in the [1, q-1] range. Most of
|
|
117
|
+
// the remainder of this document will revolve around the process
|
|
118
|
+
// used to generate k. In plain DSA or ECDSA, k should be selected
|
|
119
|
+
// through a random selection that chooses a value among the q-1
|
|
120
|
+
// possible values with uniform probability.
|
|
121
|
+
const k = computeK(a)(hf)(x)(m);
|
|
122
|
+
// 3. A value r (modulo q) is computed from k and the key parameters:
|
|
123
|
+
//
|
|
124
|
+
// * For ECDSA: the point kG is computed; its X coordinate (a
|
|
125
|
+
// member of the field over which E is defined) is converted to
|
|
126
|
+
// an integer, which is reduced modulo q, yielding r.
|
|
127
|
+
//
|
|
128
|
+
// If r turns out to be zero, a new k should be selected and r
|
|
129
|
+
// computed again (this is an utterly improbable occurrence).
|
|
130
|
+
const rxy = c.mul(k)(g);
|
|
131
|
+
// TODO: implement the loop. `computeK` should either
|
|
132
|
+
// - accept a state (current `k`).
|
|
133
|
+
// - accept a `is_valid` function.
|
|
134
|
+
if (rxy === null) {
|
|
135
|
+
throw 'rxy === null';
|
|
33
136
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const r = rp === null ? 0n : rp[0];
|
|
45
|
-
// `s = ((z + r * d) / k)`.
|
|
46
|
-
const d = uint(privateKey);
|
|
47
|
-
const z = uint(messageHash);
|
|
48
|
-
const rd = pf.mul(r)(d);
|
|
49
|
-
const zrd = pf.add(z)(rd);
|
|
50
|
-
const kn1 = pf.reciprocal(k);
|
|
51
|
-
const s = pf.mul(zrd)(kn1);
|
|
137
|
+
const [r] = rxy;
|
|
138
|
+
// 4. The value s (modulo q) is computed:
|
|
139
|
+
//
|
|
140
|
+
// s = (h+x*r)/k mod q
|
|
141
|
+
//
|
|
142
|
+
// The pair (r, s) is the signature. How a signature is to be
|
|
143
|
+
// encoded is not covered by the DSA and ECDSA standards themselves;
|
|
144
|
+
// a common way is to use a DER-encoded ASN.1 structure (a SEQUENCE
|
|
145
|
+
// of two INTEGERs, for r and s, in that order).
|
|
146
|
+
const s = div(h + x * r)(k);
|
|
52
147
|
return [r, s];
|
|
53
148
|
};
|
package/crypto/sign/test.f.d.ts
CHANGED
|
@@ -1,2 +1,12 @@
|
|
|
1
|
-
declare const _default: {
|
|
1
|
+
declare const _default: {
|
|
2
|
+
bits2int: () => void;
|
|
3
|
+
int2octets: () => void;
|
|
4
|
+
bit2octets: () => void;
|
|
5
|
+
k: () => void;
|
|
6
|
+
computeK: () => void;
|
|
7
|
+
investigate: () => void;
|
|
8
|
+
kk: () => void;
|
|
9
|
+
a2: () => void;
|
|
10
|
+
a2s: () => void;
|
|
11
|
+
};
|
|
2
12
|
export default _default;
|