functionalscript 0.7.0 → 0.8.1
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/LICENSE +21 -661
- package/README.md +3 -2
- package/bnf/data/module.f.d.ts +16 -6
- package/bnf/data/module.f.js +115 -23
- package/bnf/data/test.f.d.ts +4 -0
- package/bnf/data/test.f.js +389 -14
- package/bnf/module.f.d.ts +5 -4
- package/bnf/module.f.js +1 -1
- package/bnf/testlib.f.js +1 -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/prime_field/module.f.d.ts +1 -1
- package/crypto/prime_field/module.f.js +4 -3
- package/crypto/prime_field/test.f.js +13 -13
- package/crypto/rfc6979/module.f.d.ts +15 -0
- package/crypto/rfc6979/module.f.js +98 -0
- package/crypto/rfc6979/test.f.d.ts +10 -0
- package/crypto/rfc6979/test.f.js +490 -0
- package/crypto/secp/module.f.d.ts +4 -4
- package/crypto/secp/module.f.js +1 -1
- package/crypto/secp/test.f.js +8 -8
- 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 +1 -1
- package/crypto/sign/module.f.js +3 -2
- 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.d.ts +5 -0
- package/fsc/test.f.js +69 -7
- 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.d.ts +25 -0
- package/nanvm-lib/tests/vm/test.f.js +105 -0
- package/package.json +8 -8
- 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/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/djs/module.f.d.ts +0 -77
- package/bnf/djs/module.f.js +0 -207
- package/bnf/djs/test.f.d.ts +0 -8
- package/bnf/djs/test.f.js +0 -277
- 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/ci/module.f.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
const os = ['ubuntu', 'macos', 'windows'];
|
|
2
|
+
const architecture = ['intel', 'arm'];
|
|
3
|
+
// https://docs.github.com/en/actions/reference/runners/github-hosted-runners#standard-github-hosted-runners-for-public-repositories
|
|
4
|
+
const images = {
|
|
5
|
+
ubuntu: {
|
|
6
|
+
intel: 'ubuntu-latest',
|
|
7
|
+
arm: 'ubuntu-24.04-arm'
|
|
8
|
+
},
|
|
9
|
+
macos: {
|
|
10
|
+
intel: 'macos-15-intel',
|
|
11
|
+
arm: 'macos-latest'
|
|
12
|
+
},
|
|
13
|
+
windows: {
|
|
14
|
+
intel: 'windows-latest',
|
|
15
|
+
arm: 'windows-11-arm',
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const install = (step) => ({ type: 'install', step });
|
|
19
|
+
const test = (step) => ({ type: 'test', step });
|
|
20
|
+
const installOnWindowsArm = ({ def, name, path }) => (v) => (a) => install(v === 'windows' && a === 'arm'
|
|
21
|
+
? { run: `irm ${path}/install.ps1 | iex; "$env:USERPROFILE\\.${name}\\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append` }
|
|
22
|
+
: def);
|
|
23
|
+
const installBun = installOnWindowsArm({
|
|
24
|
+
def: { uses: 'oven-sh/setup-bun@v1' },
|
|
25
|
+
name: 'bun',
|
|
26
|
+
path: 'bun.sh'
|
|
27
|
+
});
|
|
28
|
+
const installDeno = installOnWindowsArm({
|
|
29
|
+
def: { uses: 'denoland/setup-deno@v2', with: { 'deno-version': '2' } },
|
|
30
|
+
name: 'deno',
|
|
31
|
+
path: 'deno.land'
|
|
32
|
+
});
|
|
33
|
+
const cargoTest = (target, config) => {
|
|
34
|
+
const to = target ? ` --target ${target}` : '';
|
|
35
|
+
const co = config ? ` --config ${config}` : '';
|
|
36
|
+
const main = `cargo test${to}${co}`;
|
|
37
|
+
return [
|
|
38
|
+
test({ run: main }),
|
|
39
|
+
test({ run: `${main} --release` })
|
|
40
|
+
];
|
|
41
|
+
};
|
|
42
|
+
const customTarget = (target) => [
|
|
43
|
+
{ type: 'rust', target },
|
|
44
|
+
...cargoTest(target)
|
|
45
|
+
];
|
|
46
|
+
const wasmTarget = (target) => [
|
|
47
|
+
...customTarget(target),
|
|
48
|
+
...cargoTest(target, '.cargo/config.wasmer.toml')
|
|
49
|
+
];
|
|
50
|
+
const clean = (steps) => [
|
|
51
|
+
...steps,
|
|
52
|
+
test({ run: 'git reset --hard HEAD && git clean -fdx' })
|
|
53
|
+
];
|
|
54
|
+
const installNode = (version) => ({ uses: 'actions/setup-node@v6', with: { 'node-version': version } });
|
|
55
|
+
const basicNode = (version) => (extra) => clean([
|
|
56
|
+
install(installNode(version)),
|
|
57
|
+
test({ run: 'npm ci' }),
|
|
58
|
+
...extra,
|
|
59
|
+
]);
|
|
60
|
+
const node = (version) => (extra) => basicNode(version)([
|
|
61
|
+
test({ run: 'npm test' }),
|
|
62
|
+
test({ run: 'npm run fst' }),
|
|
63
|
+
...extra,
|
|
64
|
+
]);
|
|
65
|
+
const findTgz = (v) => v === 'windows' ? '(Get-ChildItem *.tgz).FullName' : './*.tgz';
|
|
66
|
+
const toSteps = (m) => {
|
|
67
|
+
const filter = (st) => m.flatMap((mt) => mt.type === st ? [mt.step] : []);
|
|
68
|
+
const aptGet = m.flatMap(v => v.type === 'apt-get' ? [v.package] : []).join(' ');
|
|
69
|
+
const rust = m.find(v => v.type === 'rust') !== undefined;
|
|
70
|
+
const targets = m.flatMap(v => v.type === 'rust' && v.target !== undefined ? [v.target] : []).join(',');
|
|
71
|
+
return [
|
|
72
|
+
...(aptGet !== '' ? [{ run: `sudo apt-get update && sudo apt-get install -y ${aptGet}` }] : []),
|
|
73
|
+
...(rust ? [{
|
|
74
|
+
// wasm32-wasip1-threads doesn't work on Rust 1.91 in the release mode.
|
|
75
|
+
// See https://github.com/sergey-shandar/wasmtime-crash
|
|
76
|
+
uses: 'dtolnay/rust-toolchain@1.90.0',
|
|
77
|
+
with: {
|
|
78
|
+
components: 'rustfmt,clippy',
|
|
79
|
+
targets
|
|
80
|
+
}
|
|
81
|
+
}] : []),
|
|
82
|
+
...filter('install'),
|
|
83
|
+
{ uses: 'actions/checkout@v5' },
|
|
84
|
+
...filter('test'),
|
|
85
|
+
];
|
|
86
|
+
};
|
|
87
|
+
const nodes = ['20', '22', '25'];
|
|
88
|
+
const nodeTest = (v) => v === '20' ? 'run test20' : 'test';
|
|
89
|
+
const nodeSteps = (v) => [
|
|
90
|
+
install(installNode(v)),
|
|
91
|
+
test({ run: 'npm ci' }),
|
|
92
|
+
test({ run: `npm ${nodeTest(v)}` }),
|
|
93
|
+
];
|
|
94
|
+
const ubuntu = (ms) => ({
|
|
95
|
+
'runs-on': 'ubuntu-latest',
|
|
96
|
+
steps: toSteps(ms)
|
|
97
|
+
});
|
|
98
|
+
const nodeVersions = Object.fromEntries(nodes.map(v => [`node${v}`, ubuntu(nodeSteps(v))]));
|
|
99
|
+
const steps = (v) => (a) => {
|
|
100
|
+
const result = [
|
|
101
|
+
// Rust
|
|
102
|
+
test({ run: 'cargo fmt -- --check' }),
|
|
103
|
+
test({ run: 'cargo clippy -- -D warnings' }),
|
|
104
|
+
...cargoTest(),
|
|
105
|
+
install({ uses: 'bytecodealliance/actions/wasmtime/setup@v1' }),
|
|
106
|
+
install({ uses: 'wasmerio/setup-wasmer@v1' }),
|
|
107
|
+
...wasmTarget('wasm32-wasip1'),
|
|
108
|
+
...wasmTarget('wasm32-wasip2'),
|
|
109
|
+
...wasmTarget('wasm32-unknown-unknown'),
|
|
110
|
+
...wasmTarget('wasm32-wasip1-threads'),
|
|
111
|
+
...(a !== 'intel' ? [] :
|
|
112
|
+
v === 'windows' ?
|
|
113
|
+
customTarget('i686-pc-windows-msvc') :
|
|
114
|
+
v === 'ubuntu' ? [
|
|
115
|
+
{ type: 'apt-get', package: 'libc6-dev-i386' },
|
|
116
|
+
...customTarget('i686-unknown-linux-gnu'),
|
|
117
|
+
] :
|
|
118
|
+
[]),
|
|
119
|
+
// Node.js
|
|
120
|
+
...node('24')([
|
|
121
|
+
// TypeScript Preview
|
|
122
|
+
install({ run: 'npm install -g @typescript/native-preview' }),
|
|
123
|
+
test({ run: 'tsgo' }),
|
|
124
|
+
// Playwright
|
|
125
|
+
install({ run: 'npm install -g playwright' }),
|
|
126
|
+
install({ run: 'playwright install --with-deps' }),
|
|
127
|
+
...['chromium', 'firefox', 'webkit'].map(browser => (test({ run: `npx playwright test --browser=${browser}` }))),
|
|
128
|
+
// publishing
|
|
129
|
+
test({ run: 'npm pack' }),
|
|
130
|
+
test({ run: `npm install -g ${findTgz(v)}` }),
|
|
131
|
+
test({ run: 'fsc issues/demo/data/tree.json _tree.f.js' }),
|
|
132
|
+
test({ run: 'fst' }),
|
|
133
|
+
test({ run: 'npm uninstall functionalscript -g' }),
|
|
134
|
+
]),
|
|
135
|
+
// Deno
|
|
136
|
+
...clean([
|
|
137
|
+
installDeno(v)(a),
|
|
138
|
+
test({ run: 'deno install' }),
|
|
139
|
+
test({ run: 'deno task test' }),
|
|
140
|
+
test({ run: 'deno task fst' }),
|
|
141
|
+
test({ run: 'deno publish --dry-run' }),
|
|
142
|
+
]),
|
|
143
|
+
// Bun
|
|
144
|
+
...clean([
|
|
145
|
+
installBun(v)(a),
|
|
146
|
+
test({ run: 'bun test --timeout 20000' }),
|
|
147
|
+
test({ run: 'bun ./dev/tf/module.ts' }),
|
|
148
|
+
]),
|
|
149
|
+
];
|
|
150
|
+
return toSteps(result);
|
|
151
|
+
};
|
|
152
|
+
const jobs = {
|
|
153
|
+
...Object.fromEntries([
|
|
154
|
+
...os.flatMap(v => architecture.map(a => [`${v}-${a}`, {
|
|
155
|
+
'runs-on': images[v][a],
|
|
156
|
+
steps: steps(v)(a),
|
|
157
|
+
}]))
|
|
158
|
+
]),
|
|
159
|
+
...nodeVersions,
|
|
160
|
+
};
|
|
161
|
+
const gha = {
|
|
162
|
+
name: 'CI',
|
|
163
|
+
on: { pull_request: {} },
|
|
164
|
+
jobs,
|
|
165
|
+
};
|
|
166
|
+
export default async (io) => {
|
|
167
|
+
io.fs.writeFileSync('.github/workflows/ci.yml', JSON.stringify(gha, null, ' '));
|
|
168
|
+
return 0;
|
|
169
|
+
};
|
package/ci/module.js
ADDED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Provides an implementation of HMAC (Hash-based Message Authentication Code).
|
|
3
3
|
*
|
|
4
4
|
* https://en.wikipedia.org/wiki/HMAC
|
|
5
|
+
* https://www.rfc-editor.org/rfc/rfc2104
|
|
5
6
|
*
|
|
6
7
|
* @module
|
|
7
8
|
*
|
|
@@ -16,13 +17,13 @@
|
|
|
16
17
|
* if (r !== vec(256n)(0xf7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8n)) { throw r }
|
|
17
18
|
* ```
|
|
18
19
|
*/
|
|
19
|
-
import { type
|
|
20
|
+
import { type Reduce } from '../../types/bit_vec/module.f.ts';
|
|
20
21
|
import { type Sha2 } from '../sha2/module.f.ts';
|
|
21
22
|
/**
|
|
22
|
-
* Generates an HMAC (Hash-based Message Authentication Code) using the specified
|
|
23
|
+
* Generates an HMAC (Hash-based Message Authentication Code) using the specified hash function.
|
|
23
24
|
*
|
|
24
|
-
* @param
|
|
25
|
+
* @param hashFunc - The hash function implementation to use.
|
|
25
26
|
* @returns - A function that takes a key and returns another function
|
|
26
27
|
* that takes a message and computes the HMAC.
|
|
27
28
|
*/
|
|
28
|
-
export declare const hmac: (
|
|
29
|
+
export declare const hmac: (hashFunc: Sha2) => Reduce;
|
package/crypto/hmac/module.f.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Provides an implementation of HMAC (Hash-based Message Authentication Code).
|
|
3
3
|
*
|
|
4
4
|
* https://en.wikipedia.org/wiki/HMAC
|
|
5
|
+
* https://www.rfc-editor.org/rfc/rfc2104
|
|
5
6
|
*
|
|
6
7
|
* @module
|
|
7
8
|
*
|
|
@@ -16,12 +17,9 @@
|
|
|
16
17
|
* if (r !== vec(256n)(0xf7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8n)) { throw r }
|
|
17
18
|
* ```
|
|
18
19
|
*/
|
|
19
|
-
import { length } from "../../types/bit_vec/module.f.js";
|
|
20
|
-
import { empty, msb, vec, vec8 } from "../../types/bit_vec/module.f.js";
|
|
21
|
-
import { flip } from "../../types/function/module.f.js";
|
|
22
|
-
import { repeat } from "../../types/monoid/module.f.js";
|
|
20
|
+
import { length, msb, vec, vec8, repeat } from "../../types/bit_vec/module.f.js";
|
|
23
21
|
import { computeSync } from "../sha2/module.f.js";
|
|
24
|
-
const { concat } = msb;
|
|
22
|
+
const { concat, xor } = msb;
|
|
25
23
|
/**
|
|
26
24
|
* Outer padding.
|
|
27
25
|
*/
|
|
@@ -31,25 +29,18 @@ const oPad = vec8(0x5cn);
|
|
|
31
29
|
*/
|
|
32
30
|
const iPad = vec8(0x36n);
|
|
33
31
|
/**
|
|
34
|
-
*
|
|
35
|
-
*/
|
|
36
|
-
const padRepeat = repeat({ identity: empty, operation: concat });
|
|
37
|
-
/**
|
|
38
|
-
* Generates an HMAC (Hash-based Message Authentication Code) using the specified SHA-2 hash function.
|
|
32
|
+
* Generates an HMAC (Hash-based Message Authentication Code) using the specified hash function.
|
|
39
33
|
*
|
|
40
|
-
* @param
|
|
34
|
+
* @param hashFunc - The hash function implementation to use.
|
|
41
35
|
* @returns - A function that takes a key and returns another function
|
|
42
36
|
* that takes a message and computes the HMAC.
|
|
43
37
|
*/
|
|
44
|
-
export const hmac = (
|
|
45
|
-
const { blockLength } =
|
|
46
|
-
const p =
|
|
38
|
+
export const hmac = (hashFunc) => {
|
|
39
|
+
const { blockLength } = hashFunc;
|
|
40
|
+
const p = repeat(blockLength >> 3n);
|
|
47
41
|
const ip = p(iPad);
|
|
48
42
|
const op = p(oPad);
|
|
49
|
-
const c = computeSync(
|
|
50
|
-
const vbl = vec(blockLength);
|
|
51
|
-
// a and b should have the same size
|
|
52
|
-
const xor = (a) => (b) => vbl(a ^ b);
|
|
43
|
+
const c = computeSync(hashFunc);
|
|
53
44
|
return k => {
|
|
54
45
|
const k1 = length(k) > blockLength ? c([k]) : k;
|
|
55
46
|
const k2 = concat(k1)(vec(blockLength - length(k1))(0n));
|
package/crypto/hmac/test.f.d.ts
CHANGED
package/crypto/hmac/test.f.js
CHANGED
|
@@ -1,23 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { vec } from "../../types/bit_vec/module.f.js";
|
|
3
|
-
import { sha256, sha512 } from "../sha2/module.f.js";
|
|
1
|
+
import { utf8 } from "../../text/module.f.js";
|
|
2
|
+
import { length, uint, vec } from "../../types/bit_vec/module.f.js";
|
|
3
|
+
import { sha256, sha384, sha512 } from "../sha2/module.f.js";
|
|
4
4
|
import { hmac } from "./module.f.js";
|
|
5
5
|
export default {
|
|
6
6
|
example: () => {
|
|
7
|
-
const r = hmac(sha256)(
|
|
7
|
+
const r = hmac(sha256)(utf8('key'))(utf8('The quick brown fox jumps over the lazy dog'));
|
|
8
8
|
if (r !== vec(256n)(0xf7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8n)) {
|
|
9
9
|
throw r;
|
|
10
10
|
}
|
|
11
11
|
},
|
|
12
12
|
sha256: () => {
|
|
13
|
-
const r = hmac(sha256)(
|
|
14
|
-
if (r !==
|
|
13
|
+
const r = hmac(sha256)(utf8('key'))(utf8('The quick brown fox jumps over the lazy dog'));
|
|
14
|
+
if (uint(r) !== 0xf7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8n) {
|
|
15
15
|
throw r;
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
|
+
sha384: () => {
|
|
19
|
+
const k = vec(384n)(0n);
|
|
20
|
+
const m = vec(904n)(0x0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010069c7548c21d0dfea6b9a51c9ead4e27c33d3b3f180316e5bcab92c933f0e4dbc9a9083505bc92276aec4be312696ef7bf3bf603f4bbd381196a029f340585312n);
|
|
21
|
+
const r = hmac(sha384)(k)(m);
|
|
22
|
+
if (r !== vec(384n)(0x8f858157ce005cd52fd8e8f1a46b55e6cfae21c8c183d9c2f7504bedf450609edd7d3c6171dc0bdd2d2444faa28f18ban)) {
|
|
23
|
+
throw uint(r).toString(16);
|
|
24
|
+
}
|
|
25
|
+
},
|
|
18
26
|
sha512: () => {
|
|
19
|
-
const r = hmac(sha512)(
|
|
20
|
-
if (r !==
|
|
27
|
+
const r = hmac(sha512)(utf8('key'))(utf8('The quick brown fox jumps over the lazy dog'));
|
|
28
|
+
if (r !== vec(512n)(0xb42af09057bac1e2d41708e48a902e09b5ff7f12ab428a4fe86653c73dd248fb82f948a549f7b791a5b41915ee4d1ec3935357e4e2317250d0372afa2ebeeb3an)) {
|
|
21
29
|
throw r;
|
|
22
30
|
}
|
|
23
31
|
}
|
|
@@ -37,4 +37,4 @@ export declare const prime_field: (p: bigint) => PrimeField;
|
|
|
37
37
|
* if (root !== 2n) { throw root }
|
|
38
38
|
* ```
|
|
39
39
|
*/
|
|
40
|
-
export declare const sqrt: ({ p,
|
|
40
|
+
export declare const sqrt: ({ p, pow, pow2 }: PrimeField) => (a: bigint) => bigint | null;
|
|
@@ -65,13 +65,14 @@ export const prime_field = (p) => {
|
|
|
65
65
|
* if (root !== 2n) { throw root }
|
|
66
66
|
* ```
|
|
67
67
|
*/
|
|
68
|
-
export const sqrt = ({ p,
|
|
68
|
+
export const sqrt = ({ p, pow, pow2 }) => {
|
|
69
69
|
if ((p & 3n) !== 3n) {
|
|
70
70
|
throw 'sqrt';
|
|
71
71
|
}
|
|
72
72
|
const sqrt_k = (p + 1n) >> 2n;
|
|
73
|
+
const psk = pow(sqrt_k);
|
|
73
74
|
return a => {
|
|
74
|
-
const result =
|
|
75
|
-
return
|
|
75
|
+
const result = psk(a);
|
|
76
|
+
return pow2(result) === a ? result : null;
|
|
76
77
|
};
|
|
77
78
|
};
|
|
@@ -58,21 +58,21 @@ export default {
|
|
|
58
58
|
},
|
|
59
59
|
pow: () => {
|
|
60
60
|
const test = a => {
|
|
61
|
-
if (f.pow(
|
|
61
|
+
if (f.pow(0n)(a) !== 1n) {
|
|
62
62
|
throw '**0';
|
|
63
63
|
}
|
|
64
|
-
if (f.pow(
|
|
64
|
+
if (f.pow(1n)(a) !== a) {
|
|
65
65
|
throw '**1';
|
|
66
66
|
}
|
|
67
67
|
// https://en.wikipedia.org/wiki/Fermat%27s_little_theorem
|
|
68
68
|
// a^(p-1) % p = 1
|
|
69
|
-
if (f.abs(f.pow(
|
|
69
|
+
if (f.abs(f.pow(f.middle)(a)) !== 1n) {
|
|
70
70
|
throw '**middle';
|
|
71
71
|
}
|
|
72
|
-
if (f.pow(
|
|
72
|
+
if (f.pow(f.sub(f.max)(1n))(a) !== f.reciprocal(a)) {
|
|
73
73
|
throw '**(max-1)';
|
|
74
74
|
}
|
|
75
|
-
if (f.pow(
|
|
75
|
+
if (f.pow(f.max)(a) !== 1n) {
|
|
76
76
|
throw '**max';
|
|
77
77
|
}
|
|
78
78
|
};
|
|
@@ -80,7 +80,7 @@ export default {
|
|
|
80
80
|
if (f.pow(0n)(0n) !== 1n) {
|
|
81
81
|
throw '0**0';
|
|
82
82
|
}
|
|
83
|
-
if (f.pow(
|
|
83
|
+
if (f.pow(f.max)(0n) !== 0n) {
|
|
84
84
|
throw '0**max';
|
|
85
85
|
}
|
|
86
86
|
// 1
|
|
@@ -90,30 +90,30 @@ export default {
|
|
|
90
90
|
if (f.pow(2n)(2n) !== 4n) {
|
|
91
91
|
throw '2**2';
|
|
92
92
|
}
|
|
93
|
-
if (f.pow(
|
|
93
|
+
if (f.pow(3n)(2n) !== 8n) {
|
|
94
94
|
throw '2**3';
|
|
95
95
|
}
|
|
96
|
-
if (f.pow(
|
|
96
|
+
if (f.pow(128n)(2n) !== 1n << 128n) {
|
|
97
97
|
throw '2**128';
|
|
98
98
|
}
|
|
99
99
|
// 3
|
|
100
100
|
test(3n);
|
|
101
|
-
if (f.pow(
|
|
101
|
+
if (f.pow(2n)(3n) !== 9n) {
|
|
102
102
|
throw '3**2';
|
|
103
103
|
}
|
|
104
104
|
if (f.pow(3n)(3n) !== 27n) {
|
|
105
105
|
throw '3**3';
|
|
106
106
|
}
|
|
107
|
-
if (f.pow(
|
|
107
|
+
if (f.pow(100n)(3n) !== 3n ** 100n) {
|
|
108
108
|
throw '3**100';
|
|
109
109
|
}
|
|
110
|
-
if (f.pow(
|
|
110
|
+
if (f.pow(110n)(3n) !== 3n ** 110n) {
|
|
111
111
|
throw '3**110';
|
|
112
112
|
}
|
|
113
|
-
if (f.pow(
|
|
113
|
+
if (f.pow(120n)(3n) !== 3n ** 120n) {
|
|
114
114
|
throw '3**120';
|
|
115
115
|
}
|
|
116
|
-
if (f.pow(
|
|
116
|
+
if (f.pow(121n)(3n) !== 3n ** 121n) {
|
|
117
117
|
throw '3**121';
|
|
118
118
|
}
|
|
119
119
|
//
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type Vec } from '../../types/bit_vec/module.f.ts';
|
|
2
|
+
import type { Curve } from '../secp/module.f.ts';
|
|
3
|
+
import { type Sha2 } from '../sha2/module.f.ts';
|
|
4
|
+
export type All = {
|
|
5
|
+
readonly q: bigint;
|
|
6
|
+
readonly qlen: bigint;
|
|
7
|
+
readonly bits2int: (b: Vec) => bigint;
|
|
8
|
+
readonly int2octets: (x: bigint) => Vec;
|
|
9
|
+
readonly bits2octets: (b: Vec) => Vec;
|
|
10
|
+
};
|
|
11
|
+
export declare const all: (q: bigint) => All;
|
|
12
|
+
export declare const fromCurve: (c: Curve) => All;
|
|
13
|
+
export declare const concat: (...x: readonly Vec[]) => Vec;
|
|
14
|
+
export declare const computeK: ({ q, bits2int, qlen, int2octets, bits2octets }: All) => (hf: Sha2) => (x: bigint) => (m: Vec) => bigint;
|
|
15
|
+
export declare const sign: (a: All) => (hf: Sha2) => (x: bigint) => (m: Vec) => bigint;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { todo } from "../../dev/module.f.js";
|
|
2
|
+
import { bitLength, divUp, roundUp } from "../../types/bigint/module.f.js";
|
|
3
|
+
import { empty, length, listToVec, msb, repeat, unpack, vec, vec8 } from "../../types/bit_vec/module.f.js";
|
|
4
|
+
import { hmac } from "../hmac/module.f.js";
|
|
5
|
+
import { computeSync } from "../sha2/module.f.js";
|
|
6
|
+
// qlen to rlen
|
|
7
|
+
const roundUp8 = roundUp(8n);
|
|
8
|
+
const divUp8 = divUp(8n);
|
|
9
|
+
export const all = (q) => {
|
|
10
|
+
const qlen = bitLength(q);
|
|
11
|
+
const bits2int = (b) => {
|
|
12
|
+
const { length, uint } = unpack(b);
|
|
13
|
+
const diff = length - qlen;
|
|
14
|
+
return diff > 0n ? uint >> diff : uint;
|
|
15
|
+
};
|
|
16
|
+
const int2octets = vec(roundUp8(qlen));
|
|
17
|
+
return {
|
|
18
|
+
q,
|
|
19
|
+
qlen,
|
|
20
|
+
bits2int,
|
|
21
|
+
int2octets,
|
|
22
|
+
// since z2 < 2*q, we can use simple mod with `z1 < q ? z1 : z1 - q`
|
|
23
|
+
bits2octets: b => int2octets(bits2int(b) % q),
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
export const fromCurve = (c) => all(c.nf.p);
|
|
27
|
+
const v0 = vec8(0x01n);
|
|
28
|
+
const k0 = vec8(0x00n);
|
|
29
|
+
const ltov = listToVec(msb);
|
|
30
|
+
export const concat = (...x) => ltov(x);
|
|
31
|
+
export const computeK = ({ q, bits2int, qlen, int2octets, bits2octets }) => (hf) => (x) => (m) => {
|
|
32
|
+
const hmacf = hmac(hf);
|
|
33
|
+
// a. Process m through the hash function H, yielding:
|
|
34
|
+
// h1 = H(m)
|
|
35
|
+
// (h1 is a sequence of hlen bits).
|
|
36
|
+
const h1 = computeSync(hf)([m]);
|
|
37
|
+
// b. Set:
|
|
38
|
+
// V = 0x01 0x01 0x01 ... 0x01
|
|
39
|
+
// such that the length of V, in bits, is equal to 8*ceil(hlen/8).
|
|
40
|
+
// For instance, on an octet-based system, if H is SHA-256, then V
|
|
41
|
+
// is set to a sequence of 32 octets of value 1. Note that in this
|
|
42
|
+
// step and all subsequent steps, we use the same H function as the
|
|
43
|
+
// one used in step 'a' to process the input message; this choice
|
|
44
|
+
// will be discussed in more detail in Section 3.6.
|
|
45
|
+
const rep = repeat(divUp8(hf.hashLength));
|
|
46
|
+
let v = rep(v0);
|
|
47
|
+
// c. Set:
|
|
48
|
+
// K = 0x00 0x00 0x00 ... 0x00
|
|
49
|
+
// such that the length of K, in bits, is equal to 8*ceil(hlen/8).
|
|
50
|
+
let k = rep(k0);
|
|
51
|
+
// d. Set:
|
|
52
|
+
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1))
|
|
53
|
+
// where '||' denotes concatenation.
|
|
54
|
+
const xh1 = concat(int2octets(x), bits2octets(h1));
|
|
55
|
+
k = hmacf(k)(concat(v, k0, xh1));
|
|
56
|
+
// e. Set:
|
|
57
|
+
// V = HMAC_K(V)
|
|
58
|
+
v = hmacf(k)(v);
|
|
59
|
+
// f. Set:
|
|
60
|
+
// K = HMAC_K(V || 0x01 || int2octets(x) || bits2octets(h1))
|
|
61
|
+
k = hmacf(k)(concat(v, v0, xh1));
|
|
62
|
+
// g. Set:
|
|
63
|
+
// V = HMAC_K(V)
|
|
64
|
+
v = hmacf(k)(v);
|
|
65
|
+
// h. Apply the following algorithm until a proper value is for `k`:
|
|
66
|
+
while (true) {
|
|
67
|
+
// h. Apply the following algorithm until a proper value is for `k`:
|
|
68
|
+
// 1. Set `T` to the empty sequence, so `tlen = 0`.
|
|
69
|
+
let t = empty;
|
|
70
|
+
// 2. while `tlen < qlen` do:
|
|
71
|
+
// - `V = HMAC_K(V)`
|
|
72
|
+
// - `T = T || V`
|
|
73
|
+
// Possible optimizations:
|
|
74
|
+
// - precompute number of iterations
|
|
75
|
+
// - `qlen` can't be 0, so we can avoid the first check and
|
|
76
|
+
// first concatenation.
|
|
77
|
+
while (length(t) < qlen) {
|
|
78
|
+
v = hmacf(k)(v);
|
|
79
|
+
t = concat(t, v);
|
|
80
|
+
}
|
|
81
|
+
// 3. Compute `k = bits2int(T)`. If `k` is not in `[1, q-1]` or `kG = 0` then
|
|
82
|
+
// - `K = HMAC_K(V || 0x00)`
|
|
83
|
+
// - `V = HMAC_K(V)`
|
|
84
|
+
// and loop (try to generate a new `T`, and so on). Return to step `1`.
|
|
85
|
+
const result = bits2int(t);
|
|
86
|
+
if (0n < result && result < q) {
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
k = hmacf(k)(concat(v, k0));
|
|
90
|
+
v = hmacf(k)(v);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
export const sign = (a) => (hf) => (x) => (m) => {
|
|
94
|
+
const hm = computeSync(hf)([m]);
|
|
95
|
+
const h = a.bits2int(hm) % a.q;
|
|
96
|
+
///
|
|
97
|
+
return todo();
|
|
98
|
+
};
|