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.
Files changed (114) hide show
  1. package/bnf/data/module.f.d.ts +6 -0
  2. package/bnf/data/module.f.js +57 -4
  3. package/bnf/data/test.f.d.ts +1 -0
  4. package/bnf/data/test.f.js +67 -1
  5. package/ci/module.f.d.ts +3 -0
  6. package/ci/module.f.js +169 -0
  7. package/ci/module.js +3 -0
  8. package/crypto/hmac/module.f.d.ts +5 -4
  9. package/crypto/hmac/module.f.js +9 -18
  10. package/crypto/hmac/test.f.d.ts +1 -0
  11. package/crypto/hmac/test.f.js +16 -8
  12. package/crypto/secp/module.f.d.ts +14 -11
  13. package/crypto/secp/module.f.js +33 -13
  14. package/crypto/secp/test.f.js +12 -13
  15. package/crypto/sha2/module.f.d.ts +11 -5
  16. package/crypto/sha2/module.f.js +4 -3
  17. package/crypto/sha2/test.f.d.ts +4 -1
  18. package/crypto/sha2/test.f.js +41 -31
  19. package/crypto/sign/module.f.d.ts +17 -4
  20. package/crypto/sign/module.f.js +141 -46
  21. package/crypto/sign/test.f.d.ts +11 -1
  22. package/crypto/sign/test.f.js +631 -1
  23. package/dev/tf/all.test.js +9 -1
  24. package/djs/ast/module.f.d.ts +3 -3
  25. package/djs/ast/test.f.js +7 -8
  26. package/djs/parser/module.f.d.ts +3 -3
  27. package/djs/parser/module.f.js +4 -4
  28. package/djs/parser/test.f.js +76 -77
  29. package/djs/serializer/module.f.d.ts +8 -8
  30. package/djs/serializer/module.f.js +4 -7
  31. package/djs/serializer/test.f.js +8 -9
  32. package/djs/tokenizer/module.f.d.ts +2 -2
  33. package/djs/tokenizer/module.f.js +3 -5
  34. package/djs/tokenizer/test.f.js +8 -10
  35. package/djs/transpiler/module.f.d.ts +3 -3
  36. package/djs/transpiler/module.f.js +2 -0
  37. package/fsc/bnf.f.d.ts +1 -1
  38. package/fsc/bnf.f.js +39 -51
  39. package/fsc/json.f.d.ts +1 -1
  40. package/fsc/json.f.js +56 -81
  41. package/fsc/test.f.js +4 -6
  42. package/fsm/module.f.js +3 -3
  43. package/fsm/test.f.js +21 -25
  44. package/html/module.f.js +17 -4
  45. package/html/test.f.d.ts +7 -0
  46. package/html/test.f.js +37 -0
  47. package/issues/031-json.f.d.ts +1 -0
  48. package/js/tokenizer/module.f.d.ts +4 -4
  49. package/js/tokenizer/module.f.js +12 -17
  50. package/js/tokenizer/test.f.js +9 -11
  51. package/json/module.f.d.ts +6 -6
  52. package/json/module.f.js +5 -10
  53. package/json/parser/module.f.d.ts +4 -4
  54. package/json/parser/module.f.js +7 -4
  55. package/json/parser/test.f.js +47 -49
  56. package/json/serializer/module.f.d.ts +6 -6
  57. package/json/serializer/module.f.js +3 -2
  58. package/json/serializer/test.f.js +13 -13
  59. package/json/test.f.js +13 -15
  60. package/json/tokenizer/module.f.d.ts +4 -4
  61. package/json/tokenizer/module.f.js +6 -7
  62. package/json/tokenizer/test.f.js +7 -9
  63. package/nanvm-lib/tests/vm/test.f.js +1 -1
  64. package/package.json +5 -5
  65. package/path/module.f.d.ts +3 -2
  66. package/text/ascii/test.f.js +2 -2
  67. package/text/module.f.d.ts +3 -2
  68. package/text/module.f.js +2 -2
  69. package/text/test.f.js +3 -3
  70. package/text/utf16/test.f.js +2 -2
  71. package/text/utf8/test.f.js +2 -2
  72. package/types/array/test.f.js +2 -2
  73. package/types/bigint/module.f.d.ts +6 -3
  74. package/types/bigint/module.f.js +12 -11
  75. package/types/bigint/test.f.d.ts +2 -0
  76. package/types/bigint/test.f.js +21 -2
  77. package/types/bit_vec/module.f.d.ts +66 -34
  78. package/types/bit_vec/module.f.js +97 -32
  79. package/types/bit_vec/test.f.d.ts +7 -0
  80. package/types/bit_vec/test.f.js +283 -62
  81. package/types/btree/find/test.f.js +9 -8
  82. package/types/btree/remove/test.f.js +4 -4
  83. package/types/btree/set/test.f.js +4 -4
  84. package/types/btree/test.f.js +7 -7
  85. package/types/byte_set/test.f.js +2 -2
  86. package/types/function/compare/module.f.d.ts +15 -1
  87. package/types/function/compare/module.f.js +1 -1
  88. package/types/function/compare/test.f.js +37 -4
  89. package/types/list/test.f.js +93 -93
  90. package/types/monoid/module.f.d.ts +4 -4
  91. package/types/monoid/module.f.js +3 -3
  92. package/types/monoid/test.f.js +3 -3
  93. package/types/nominal/module.f.d.ts +5 -0
  94. package/types/nominal/module.f.js +4 -0
  95. package/types/nominal/test.f.d.ts +5 -0
  96. package/types/nominal/test.f.js +53 -0
  97. package/types/number/module.f.js +2 -2
  98. package/{crypto → types}/prime_field/module.f.d.ts +2 -2
  99. package/{crypto → types}/prime_field/module.f.js +5 -4
  100. package/{crypto → types}/prime_field/test.f.js +13 -13
  101. package/types/range_map/test.f.js +21 -21
  102. package/types/sorted_list/test.f.js +10 -10
  103. package/types/sorted_set/test.f.js +14 -14
  104. package/types/string/module.f.js +2 -2
  105. package/types/string_set/module.f.js +3 -3
  106. package/bnf/func/module.f.d.ts +0 -148
  107. package/bnf/func/module.f.js +0 -132
  108. package/bnf/func/test.f.d.ts +0 -12
  109. package/bnf/func/test.f.js +0 -171
  110. package/bnf/func/testlib.f.d.ts +0 -25
  111. package/bnf/func/testlib.f.js +0 -150
  112. /package/{issues/31-json.f.d.ts → ci/module.d.ts} +0 -0
  113. /package/issues/{31-json.f.js → 031-json.f.js} +0 -0
  114. /package/{crypto → types}/prime_field/test.f.d.ts +0 -0
@@ -1,4 +1,4 @@
1
- import { prime_field, sqrt } from "../prime_field/module.f.js";
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 = (a) => (b) => {
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
+ });
@@ -1,11 +1,11 @@
1
- import { prime_field } from "../prime_field/module.f.js";
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 } = curve(param);
8
- const f = (m) => (pList) => pList.map(i => mul(i)(m));
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])(3n); // Multiply a point by 3
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(p)(0n) !== null) {
89
+ if (mul(0n)(p) !== null) {
91
90
  throw 'O';
92
91
  }
93
- if (mul(p)(1n) !== p) {
92
+ if (mul(1n)(p) !== p) {
94
93
  throw 'p';
95
94
  }
96
- if (mul(p)(n) !== null) {
95
+ if (mul(n)(p) !== null) {
97
96
  throw 'n';
98
97
  }
99
98
  const pn = neg(p);
100
- if (!eq(mul(p)(n - 1n))(pn)) {
99
+ if (!eq(mul(n - 1n)(p))(pn)) {
101
100
  throw 'n - 1';
102
101
  }
103
102
  const f = s => {
104
- const r = mul(p)(s);
103
+ const r = mul(s)(p);
105
104
  point_check(r);
106
- const rn = mul(pn)(s);
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: (state: State) => (v: Vec) => State;
29
- readonly end: (hashLength: bigint) => (state: State) => bigint;
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: (state: State) => (v: Vec) => State;
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) => bigint;
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;
@@ -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
- const lastChunkLength = chunkLength - 65n;
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: (state) => (v) => {
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(flip(append))(init);
172
+ const f = fold(append)(init);
172
173
  return (list) => end(f(list));
173
174
  };
174
175
  export const base32 = base({
@@ -6,7 +6,7 @@ declare const _default: {
6
6
  };
7
7
  b64: () => {
8
8
  s512: () => void;
9
- s385: () => void;
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;
@@ -1,12 +1,11 @@
1
- import { msbUtf8 } from "../../text/module.f.js";
2
- import { empty, msb, vec } from "../../types/bit_vec/module.f.js";
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 { concat: beConcat } = msb;
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
- s385: () => {
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)(0x1e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855n),
75
- sha224: () => checkEmpty(sha224)(0x1d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42fn),
76
- sha512: () => checkEmpty(sha512)(0x1cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3en),
77
- sha384: () => checkEmpty(sha384)(0x138b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95bn),
78
- sha512x256: () => checkEmpty(sha512x256)(0x1c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967an),
79
- sha512x224: () => checkEmpty(sha512x224)(0x16ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4n),
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 = 0x1730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525n;
82
+ const e = 0x730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525n;
84
83
  {
85
- const s = msbUtf8("The quick brown fox jumps over the lazy dog");
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(msbUtf8)(s));
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 = msbUtf8("The quick brown fox jumps over the lazy dog.");
99
+ const s = utf8("The quick brown fox jumps over the lazy dog.");
101
100
  const h = computeSync(sha224)([s]);
102
- if (h !== 0x1619cba8e8e05826e9b8c519c0a5c68f4fb653e8a3d8aa04bb2c8cd4cn) {
101
+ if (uint(h) !== 0x619cba8e8e05826e9b8c519c0a5c68f4fb653e8a3d8aa04bb2c8cd4cn) {
103
102
  throw h;
104
103
  }
105
104
  },
106
105
  () => {
107
- const s = msbUtf8("hello world");
108
- if (s !== 0x168656c6c6f20776f726c64n) {
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(state)(s);
111
+ state = sha256.append(s)(state);
113
112
  const h = sha256.end(state);
114
- if (h !== 0x1b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9n) {
113
+ if (uint(h) !== 0xb94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9n) {
115
114
  throw h;
116
115
  }
117
116
  }
118
117
  ],
119
118
  fill: () => {
120
- const times = repeat({ identity: empty, operation: beConcat })(vec(32n)(0x31313131n));
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(state)(r);
126
- const h = sha256.end(state);
127
- if (h >> 224n !== 0x18a83665fn) {
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(state)(r);
133
+ state = sha256.append(r)(state);
135
134
  const h = sha256.end(state);
136
- if (h !== 0x13138bb9bc78df27c473ecfd1410f7bd45ebac1f59cf3ff9cfe4db77aab7aedd3n) {
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 { type Init } from '../secp/module.f.ts';
3
- import type { Sha2 } from '../sha2/module.f.ts';
4
- export declare const newPrivateKey: (i: Init) => (random: Vec) => Vec;
5
- export declare const sign: (sha2: Sha2) => (curveInit: Init) => (privateKey: Vec) => (messageHash: Vec) => readonly [bigint, bigint];
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 {};
@@ -1,53 +1,148 @@
1
- import { listToVec, msb, uint, vec, vec8, length } from "../../types/bit_vec/module.f.js";
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 { curve } from "../secp/module.f.js";
4
- const concat = listToVec(msb);
5
- const v00 = vec8(0x00n);
6
- const v01 = vec8(0x01n);
7
- /**
8
- * The size of the result equals the size of the hash.
9
- *
10
- * @param sha2 SHA2 hash function
11
- * @returns A function that accepts a private key, a message hash and returns `k`.
12
- */
13
- const createK = (sha2) => {
14
- const h = hmac(sha2);
15
- let vs = vec(sha2.hashLength);
16
- let k0 = vs(0x00n);
17
- let v0 = vs(0x01n);
18
- return (privateKey) => (messageHash) => {
19
- const pm = concat([privateKey, messageHash]);
20
- let k = k0;
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 = h(k)(concat([v, v00, pm]));
23
- v = h(k)(v);
24
- k = h(k)(concat([v, v01, pm]));
25
- v = h(k)(v);
26
- return uint(h(k)(v));
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 newPrivateKey = (i) => (random) => {
30
- const { nf } = curve(i);
31
- if (length(nf.max) < length(random)) {
32
- throw "need more random bits";
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
- return uint(random) % nf.p;
35
- };
36
- export const sign = (sha2) => (curveInit) => (privateKey) => (messageHash) => {
37
- const { mul, pf } = curve(curveInit);
38
- // const curveVec = vec(length(pf.max))
39
- //`k` is a unique for each `z` and secret.
40
- const k = createK(sha2)(privateKey)(messageHash) % pf.p;
41
- // `R = G * k`.
42
- const rp = mul(curveInit.g)(k);
43
- // `r = R.x`
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
  };
@@ -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;