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.
Files changed (125) hide show
  1. package/LICENSE +21 -661
  2. package/README.md +3 -2
  3. package/bnf/data/module.f.d.ts +16 -6
  4. package/bnf/data/module.f.js +115 -23
  5. package/bnf/data/test.f.d.ts +4 -0
  6. package/bnf/data/test.f.js +389 -14
  7. package/bnf/module.f.d.ts +5 -4
  8. package/bnf/module.f.js +1 -1
  9. package/bnf/testlib.f.js +1 -1
  10. package/ci/module.f.d.ts +3 -0
  11. package/ci/module.f.js +169 -0
  12. package/ci/module.js +3 -0
  13. package/crypto/hmac/module.f.d.ts +5 -4
  14. package/crypto/hmac/module.f.js +9 -18
  15. package/crypto/hmac/test.f.d.ts +1 -0
  16. package/crypto/hmac/test.f.js +16 -8
  17. package/crypto/prime_field/module.f.d.ts +1 -1
  18. package/crypto/prime_field/module.f.js +4 -3
  19. package/crypto/prime_field/test.f.js +13 -13
  20. package/crypto/rfc6979/module.f.d.ts +15 -0
  21. package/crypto/rfc6979/module.f.js +98 -0
  22. package/crypto/rfc6979/test.f.d.ts +10 -0
  23. package/crypto/rfc6979/test.f.js +490 -0
  24. package/crypto/secp/module.f.d.ts +4 -4
  25. package/crypto/secp/module.f.js +1 -1
  26. package/crypto/secp/test.f.js +8 -8
  27. package/crypto/sha2/module.f.d.ts +11 -5
  28. package/crypto/sha2/module.f.js +4 -3
  29. package/crypto/sha2/test.f.d.ts +4 -1
  30. package/crypto/sha2/test.f.js +41 -31
  31. package/crypto/sign/module.f.d.ts +1 -1
  32. package/crypto/sign/module.f.js +3 -2
  33. package/dev/tf/all.test.js +9 -1
  34. package/djs/ast/module.f.d.ts +3 -3
  35. package/djs/ast/test.f.js +7 -8
  36. package/djs/parser/module.f.d.ts +3 -3
  37. package/djs/parser/module.f.js +4 -4
  38. package/djs/parser/test.f.js +76 -77
  39. package/djs/serializer/module.f.d.ts +8 -8
  40. package/djs/serializer/module.f.js +4 -7
  41. package/djs/serializer/test.f.js +8 -9
  42. package/djs/tokenizer/module.f.d.ts +2 -2
  43. package/djs/tokenizer/module.f.js +3 -5
  44. package/djs/tokenizer/test.f.js +8 -10
  45. package/djs/transpiler/module.f.d.ts +3 -3
  46. package/djs/transpiler/module.f.js +2 -0
  47. package/fsc/bnf.f.d.ts +1 -1
  48. package/fsc/bnf.f.js +39 -51
  49. package/fsc/json.f.d.ts +1 -1
  50. package/fsc/json.f.js +56 -81
  51. package/fsc/test.f.d.ts +5 -0
  52. package/fsc/test.f.js +69 -7
  53. package/fsm/module.f.js +3 -3
  54. package/fsm/test.f.js +21 -25
  55. package/html/module.f.js +17 -4
  56. package/html/test.f.d.ts +7 -0
  57. package/html/test.f.js +37 -0
  58. package/issues/031-json.f.d.ts +1 -0
  59. package/js/tokenizer/module.f.d.ts +4 -4
  60. package/js/tokenizer/module.f.js +12 -17
  61. package/js/tokenizer/test.f.js +9 -11
  62. package/json/module.f.d.ts +6 -6
  63. package/json/module.f.js +5 -10
  64. package/json/parser/module.f.d.ts +4 -4
  65. package/json/parser/module.f.js +7 -4
  66. package/json/parser/test.f.js +47 -49
  67. package/json/serializer/module.f.d.ts +6 -6
  68. package/json/serializer/module.f.js +3 -2
  69. package/json/serializer/test.f.js +13 -13
  70. package/json/test.f.js +13 -15
  71. package/json/tokenizer/module.f.d.ts +4 -4
  72. package/json/tokenizer/module.f.js +6 -7
  73. package/json/tokenizer/test.f.js +7 -9
  74. package/nanvm-lib/tests/vm/test.f.d.ts +25 -0
  75. package/nanvm-lib/tests/vm/test.f.js +105 -0
  76. package/package.json +8 -8
  77. package/text/ascii/test.f.js +2 -2
  78. package/text/module.f.d.ts +3 -2
  79. package/text/module.f.js +2 -2
  80. package/text/test.f.js +3 -3
  81. package/text/utf16/test.f.js +2 -2
  82. package/text/utf8/test.f.js +2 -2
  83. package/types/array/test.f.js +2 -2
  84. package/types/bigint/module.f.d.ts +6 -3
  85. package/types/bigint/module.f.js +12 -11
  86. package/types/bigint/test.f.d.ts +2 -0
  87. package/types/bigint/test.f.js +21 -2
  88. package/types/bit_vec/module.f.d.ts +66 -34
  89. package/types/bit_vec/module.f.js +97 -32
  90. package/types/bit_vec/test.f.d.ts +7 -0
  91. package/types/bit_vec/test.f.js +283 -62
  92. package/types/btree/find/test.f.js +9 -8
  93. package/types/btree/remove/test.f.js +4 -4
  94. package/types/btree/set/test.f.js +4 -4
  95. package/types/btree/test.f.js +7 -7
  96. package/types/byte_set/test.f.js +2 -2
  97. package/types/function/compare/module.f.d.ts +15 -1
  98. package/types/function/compare/module.f.js +1 -1
  99. package/types/function/compare/test.f.js +37 -4
  100. package/types/list/test.f.js +93 -93
  101. package/types/monoid/module.f.d.ts +4 -4
  102. package/types/monoid/module.f.js +3 -3
  103. package/types/monoid/test.f.js +3 -3
  104. package/types/nominal/module.f.d.ts +5 -0
  105. package/types/nominal/module.f.js +4 -0
  106. package/types/nominal/test.f.d.ts +5 -0
  107. package/types/nominal/test.f.js +53 -0
  108. package/types/number/module.f.js +2 -2
  109. package/types/range_map/test.f.js +21 -21
  110. package/types/sorted_list/test.f.js +10 -10
  111. package/types/sorted_set/test.f.js +14 -14
  112. package/types/string/module.f.js +2 -2
  113. package/types/string_set/module.f.js +3 -3
  114. package/bnf/djs/module.f.d.ts +0 -77
  115. package/bnf/djs/module.f.js +0 -207
  116. package/bnf/djs/test.f.d.ts +0 -8
  117. package/bnf/djs/test.f.js +0 -277
  118. package/bnf/func/module.f.d.ts +0 -148
  119. package/bnf/func/module.f.js +0 -132
  120. package/bnf/func/test.f.d.ts +0 -12
  121. package/bnf/func/test.f.js +0 -171
  122. package/bnf/func/testlib.f.d.ts +0 -25
  123. package/bnf/func/testlib.f.js +0 -150
  124. /package/{issues/31-json.f.d.ts → ci/module.d.ts} +0 -0
  125. /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
@@ -0,0 +1,3 @@
1
+ import node from "../io/module.js";
2
+ import x from "./module.f.js";
3
+ await node(x);
@@ -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 Vec } from '../../types/bit_vec/module.f.ts';
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 SHA-2 hash function.
23
+ * Generates an HMAC (Hash-based Message Authentication Code) using the specified hash function.
23
24
  *
24
- * @param sha2 - The SHA-2 hash function implementation to use.
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: (sha2: Sha2) => (k: Vec) => (m: Vec) => Vec;
29
+ export declare const hmac: (hashFunc: Sha2) => Reduce;
@@ -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
- * Repeats a vector to create a padded block of the desired length.
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 sha2 - The SHA-2 hash function implementation to use.
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 = (sha2) => {
45
- const { blockLength } = sha2;
46
- const p = flip(padRepeat)(blockLength >> 3n);
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(sha2);
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));
@@ -1,6 +1,7 @@
1
1
  declare const _default: {
2
2
  example: () => void;
3
3
  sha256: () => void;
4
+ sha384: () => void;
4
5
  sha512: () => void;
5
6
  };
6
7
  export default _default;
@@ -1,23 +1,31 @@
1
- import { msbUtf8 } from "../../text/module.f.js";
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)(msbUtf8('key'))(msbUtf8('The quick brown fox jumps over the lazy dog'));
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)(msbUtf8('key'))(msbUtf8('The quick brown fox jumps over the lazy dog'));
14
- if (r !== 0x1f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8n) {
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)(msbUtf8('key'))(msbUtf8('The quick brown fox jumps over the lazy dog'));
20
- if (r !== 0x1b42af09057bac1e2d41708e48a902e09b5ff7f12ab428a4fe86653c73dd248fb82f948a549f7b791a5b41915ee4d1ec3935357e4e2317250d0372afa2ebeeb3an) {
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, mul, pow }: PrimeField) => (a: bigint) => bigint | null;
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, mul, pow }) => {
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 = pow(a)(sqrt_k);
75
- return mul(result)(result) === a ? result : null;
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(a)(0n) !== 1n) {
61
+ if (f.pow(0n)(a) !== 1n) {
62
62
  throw '**0';
63
63
  }
64
- if (f.pow(a)(1n) !== a) {
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(a)(f.middle)) !== 1n) {
69
+ if (f.abs(f.pow(f.middle)(a)) !== 1n) {
70
70
  throw '**middle';
71
71
  }
72
- if (f.pow(a)(f.sub(f.max)(1n)) !== f.reciprocal(a)) {
72
+ if (f.pow(f.sub(f.max)(1n))(a) !== f.reciprocal(a)) {
73
73
  throw '**(max-1)';
74
74
  }
75
- if (f.pow(a)(f.max) !== 1n) {
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(0n)(f.max) !== 0n) {
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(2n)(3n) !== 8n) {
93
+ if (f.pow(3n)(2n) !== 8n) {
94
94
  throw '2**3';
95
95
  }
96
- if (f.pow(2n)(128n) !== 1n << 128n) {
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(3n)(2n) !== 9n) {
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(3n)(100n) !== 3n ** 100n) {
107
+ if (f.pow(100n)(3n) !== 3n ** 100n) {
108
108
  throw '3**100';
109
109
  }
110
- if (f.pow(3n)(110n) !== 3n ** 110n) {
110
+ if (f.pow(110n)(3n) !== 3n ** 110n) {
111
111
  throw '3**110';
112
112
  }
113
- if (f.pow(3n)(120n) !== 3n ** 120n) {
113
+ if (f.pow(120n)(3n) !== 3n ** 120n) {
114
114
  throw '3**120';
115
115
  }
116
- if (f.pow(3n)(121n) !== 3n ** 121n) {
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
+ };
@@ -0,0 +1,10 @@
1
+ declare const _default: {
2
+ bits2int: () => void;
3
+ int2octets: () => void;
4
+ bit2octets: () => void;
5
+ k: () => void;
6
+ computeK: () => void;
7
+ investigate: () => void;
8
+ a2: () => void;
9
+ };
10
+ export default _default;