@amritk/nish-x86_64-linux 0.24.0 → 0.25.0

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 (42) hide show
  1. package/bin/nish +0 -0
  2. package/docs/AI.md +24 -4
  3. package/package.json +1 -1
  4. package/runtime/browser.mjs +4 -3
  5. package/runtime/core/host.d.ts +8 -0
  6. package/runtime/core/host.mjs +50 -2
  7. package/runtime/nish.d.ts +100 -0
  8. package/runtime/nish.h +34 -0
  9. package/runtime/nish.mjs +21 -0
  10. package/runtime/node.mjs +57 -6
  11. package/runtime/runtime-net.c +44 -3
  12. package/runtime/runtime-os.c +115 -12
  13. package/scripts/build.sh +13 -3
  14. package/std/README.md +25 -8
  15. package/std/cli-args.ts +1216 -0
  16. package/std/cli-flags.ts +585 -0
  17. package/std/cli.ts +308 -19
  18. package/std/compress/checksum.ts +132 -20
  19. package/std/compress/deflate.ts +638 -248
  20. package/std/compress/gzip.ts +20 -6
  21. package/std/crypto/LICENSE-fiat-crypto-p384 +21 -0
  22. package/std/crypto/p256.ts +63 -1
  23. package/std/crypto/p384.ts +6044 -0
  24. package/std/crypto/pki-roots.ts +322 -0
  25. package/std/crypto/pki.ts +1207 -0
  26. package/std/crypto/rsa.ts +663 -0
  27. package/std/crypto/x509.ts +1054 -58
  28. package/std/net/dns-config.ts +734 -0
  29. package/std/net/dns-message.ts +517 -0
  30. package/std/net/dns-resolver.ts +1015 -0
  31. package/std/net/dns.ts +478 -0
  32. package/std/net/http1-client.ts +1227 -0
  33. package/std/net/http1-server.ts +7 -2
  34. package/std/net/http1.ts +9 -9
  35. package/std/net/tls/client.ts +1094 -0
  36. package/std/net/tls/codec.ts +585 -3
  37. package/std/net/tls/record-client.ts +1192 -0
  38. package/std/net/tls/verify.ts +221 -0
  39. package/std/net/tls-tcp.ts +642 -11
  40. package/std/net/tls.ts +2 -2
  41. package/std/net/url.ts +559 -4
  42. package/std/yaml-write.ts +415 -0
@@ -0,0 +1,663 @@
1
+ /**
2
+ * `nish/crypto/rsa` — RSA signature verification: RSASSA-PKCS1-v1_5 and
3
+ * RSASSA-PSS over SHA-256, SHA-384 and SHA-512, under a public key read from
4
+ * its DER. Verification only; this module neither signs nor holds a private key.
5
+ *
6
+ * import { RSA_HASH_SHA256, RsaPublicKey, rsaParsePublicKey, rsaVerifyPkcs1v15, rsaVerifyPss } from "nish/crypto/rsa";
7
+ *
8
+ * const key: RsaPublicKey | null = rsaParsePublicKey(der); // PKCS#1 RSAPublicKey
9
+ * const ok: boolean = key !== null && rsaVerifyPkcs1v15(key, RSA_HASH_SHA256, message, sig);
10
+ * const pss: boolean = key !== null && rsaVerifyPss(key, RSA_HASH_SHA256, 32, message, sig);
11
+ *
12
+ * **The key** is the DER of PKCS#1's `RSAPublicKey ::= SEQUENCE { modulus
13
+ * INTEGER, publicExponent INTEGER }` (RFC 8017 §A.1.1), nothing before it and
14
+ * nothing after it. It is read strictly: definite lengths in their shortest
15
+ * form, each INTEGER positive and in its shortest form, a modulus of
16
+ * `RSA_MIN_BITS` to `RSA_MAX_BITS` bits that is odd, and an exponent that is
17
+ * odd, at least 3 and below 2^32 (so below the modulus). Anything else answers
18
+ * `null`. The 2^32 bound is not RFC 8017's; it caps what one verification
19
+ * costs, because the work grows with the exponent's length, and every
20
+ * certificate in use carries 65537 (RSA-3, docs/security/crypto-rsa.md).
21
+ *
22
+ * **Verification** answers `false`, never a panic, for an unknown hash id, a
23
+ * signature that is not exactly as long as the modulus or is not below it, a
24
+ * negative salt length, and any encoding that is not exactly the one RFC 8017
25
+ * defines. PKCS#1 v1.5 builds the whole encoded message it expects, `00 01 FF
26
+ * … FF 00 DigestInfo`, and compares it with what the signature opens to, so no
27
+ * part of the opened block is parsed (Bleichenbacher's 2006 forgery against a
28
+ * parser that skipped trailing bytes). The DigestInfo carries the NULL
29
+ * parameters RFC 8017 §9.2 note 1 prints; the form without them, which the
30
+ * RFC lets a verifier accept, is refused. PSS is RFC 8017 §8.1.2 and §9.1.2
31
+ * step by step, with MGF1 over the same hash as the message, the leftmost
32
+ * bits of the masked block checked to be zero and the 0x01 separator checked.
33
+ *
34
+ * **Variable time, on purpose.** A public key, a signature and a message are
35
+ * all public, so nothing here has a secret to leak: the exponentiation
36
+ * branches on the exponent's bits, the reductions branch on comparisons and
37
+ * the encodings are compared with an early exit. That is why this module does
38
+ * not use `nish:secret` or `nish/crypto/ct`.
39
+ *
40
+ * **The arithmetic** is written for this module from the textbook. Numbers
41
+ * are little-endian `u32` limbs, products are taken in `u64`, and modular
42
+ * multiplication is Montgomery's (P. L. Montgomery, "Modular multiplication
43
+ * without trial division", Math. Comp. 44, 1985) in the coarsely integrated
44
+ * operand scanning form of Ç. K. Koç, T. Acar and B. S. Kaliski, "Analyzing
45
+ * and comparing Montgomery multiplication algorithms" (IEEE Micro, 1996), the
46
+ * same algorithm as A. Menezes, P. van Oorschot and S. Vanstone, *Handbook of
47
+ * Applied Cryptography* (1996), Algorithm 14.36, with one conditional
48
+ * subtraction at the end. The exponent is applied left to right by square
49
+ * and multiply (HAC Algorithm 14.79's binary special case). The closest
50
+ * upstream is BearSSL's `i31` code (`br_i31_montymul`, `br_i31_modpow`), and
51
+ * nothing here follows it: BearSSL keeps 31-bit words and a constant-time
52
+ * structure, this keeps 32-bit words and branches freely.
53
+ *
54
+ * Private names carry the `rsa` prefix because a `std/` module's private
55
+ * functions share the importing program's flat symbol namespace
56
+ * (`docs/wp26-stdlib.md` §3e).
57
+ */
58
+ import { sha256 } from "nish/crypto/sha256"
59
+ import { sha384, sha512 } from "nish/crypto/sha512"
60
+
61
+ /** SHA-256, the hash id `rsaVerifyPkcs1v15` and `rsaVerifyPss` take. The same number as `nish/crypto/x509`'s `X509_HASH_SHA256`. */
62
+ export const RSA_HASH_SHA256: i32 = 1
63
+
64
+ /** SHA-384. */
65
+ export const RSA_HASH_SHA384: i32 = 2
66
+
67
+ /** SHA-512. */
68
+ export const RSA_HASH_SHA512: i32 = 3
69
+
70
+ /** The smallest modulus `rsaParsePublicKey` accepts, in bits. A policy that wants 2048 checks `bits` itself. */
71
+ export const RSA_MIN_BITS: i32 = 1024
72
+
73
+ /** The largest modulus `rsaParsePublicKey` accepts, in bits. */
74
+ export const RSA_MAX_BITS: i32 = 8192
75
+
76
+ /**
77
+ * A public key as `rsaParsePublicKey` read it. One built by hand is not
78
+ * checked: the verifiers answer it without a panic, and their answer means
79
+ * something only for a key the parser would accept. They read `n` and `e`,
80
+ * never `bits`.
81
+ */
82
+ export class RsaPublicKey {
83
+ /** The modulus, big-endian with no leading zero byte. */
84
+ n: u8[]
85
+ /** The public exponent, big-endian with no leading zero byte. */
86
+ e: u8[]
87
+ /** The modulus's length in bits: 2048 for a 2048-bit key. */
88
+ bits: i32
89
+
90
+ constructor(n: u8[], e: u8[], bits: i32) {
91
+ this.n = n
92
+ this.e = e
93
+ this.bits = bits
94
+ }
95
+ }
96
+
97
+ // ---------------------------------------------------------------------------
98
+ // The key's DER (X.690 §8.1, §8.3, §10.1)
99
+ // ---------------------------------------------------------------------------
100
+
101
+ /**
102
+ * Where the contents of the element at `der[at]` start, when it has the
103
+ * identifier `tag` and a definite length in its shortest form that fits
104
+ * before `end`; -1 otherwise. The length is `rsaDerLength`'s answer for the
105
+ * same arguments. Lengths of more than two octets are refused: the largest
106
+ * key's DER is about a kilobyte.
107
+ */
108
+ const rsaDerContents = (der: u8[], at: i32, end: i32, tag: i32): i32 => {
109
+ if (at < 0 || at + 2 > end || toI32(der[at]) !== tag) {
110
+ return -1
111
+ }
112
+ const first: i32 = toI32(der[at + 1])
113
+ let start: i32 = at + 2
114
+ let length: i32 = first
115
+ if (first === 0x81) {
116
+ if (at + 3 > end) {
117
+ return -1
118
+ }
119
+ length = toI32(der[at + 2])
120
+ if (length < 0x80) {
121
+ return -1
122
+ }
123
+ start = at + 3
124
+ } else if (first === 0x82) {
125
+ if (at + 4 > end) {
126
+ return -1
127
+ }
128
+ length = (toI32(der[at + 2]) << 8) | toI32(der[at + 3])
129
+ if (length < 0x100) {
130
+ return -1
131
+ }
132
+ start = at + 4
133
+ } else if (first >= 0x80) {
134
+ return -1
135
+ }
136
+ if (length > end - start) {
137
+ return -1
138
+ }
139
+ return start
140
+ }
141
+
142
+ /** The contents length of the element `rsaDerContents` found at `der[at]`. */
143
+ const rsaDerLength = (der: u8[], at: i32): i32 => {
144
+ const first: i32 = toI32(der[at + 1])
145
+ if (first === 0x81) {
146
+ return toI32(der[at + 2])
147
+ }
148
+ if (first === 0x82) {
149
+ return (toI32(der[at + 2]) << 8) | toI32(der[at + 3])
150
+ }
151
+ return first
152
+ }
153
+
154
+ /**
155
+ * The magnitude of the positive INTEGER whose contents are `der[start ..
156
+ * start + length)`, big-endian with no leading zero byte; `null` for an empty
157
+ * one, a negative one, and one not in its shortest form (a leading 0x00 that
158
+ * a clear top bit after it did not need).
159
+ */
160
+ const rsaDerUnsigned = (der: u8[], start: i32, length: i32): u8[] | null => {
161
+ const end: i32 = start + length
162
+ if (start < 0 || length < 1 || end > toI32(der.length) || toI32(der[start]) >= 0x80) {
163
+ return null
164
+ }
165
+ let from: i32 = start
166
+ if (toI32(der[start]) === 0) {
167
+ if (length === 1 || toI32(der[start + 1]) < 0x80) {
168
+ return null
169
+ }
170
+ from = start + 1
171
+ }
172
+ const out: u8[] = new Array<u8>(end - from)
173
+ for (let i: i32 = from; i < end; i++) {
174
+ out[i - from] = der[i]
175
+ }
176
+ return out
177
+ }
178
+
179
+ /** The number of significant bits in the big-endian `v`, which has no leading zero byte. */
180
+ const rsaBitLength = (v: u8[]): i32 => {
181
+ const length: i32 = toI32(v.length)
182
+ if (length === 0) {
183
+ return 0
184
+ }
185
+ let top: i32 = toI32(v[0])
186
+ let bits: i32 = (length - 1) << 3
187
+ while (top > 0) {
188
+ bits += 1
189
+ top = top >> 1
190
+ }
191
+ return bits
192
+ }
193
+
194
+ /** Whether the big-endian `a` is below `b`, both without a leading zero byte. */
195
+ const rsaBytesBelow = (a: u8[], b: u8[]): boolean => {
196
+ const aLength: i32 = toI32(a.length)
197
+ const bLength: i32 = toI32(b.length)
198
+ if (aLength !== bLength) {
199
+ return aLength < bLength
200
+ }
201
+ for (let i: i32 = 0; i < aLength && i < bLength; i++) {
202
+ if (a[i] !== b[i]) {
203
+ return a[i] < b[i]
204
+ }
205
+ }
206
+ return false
207
+ }
208
+
209
+ /**
210
+ * Reads the DER of a PKCS#1 `RSAPublicKey` (RFC 8017 §A.1.1), the whole of
211
+ * `der`. Answers `null` for anything but one SEQUENCE of two positive,
212
+ * minimally encoded INTEGERs with definite, minimal lengths and nothing
213
+ * after it; for a modulus that is even or not `RSA_MIN_BITS` to
214
+ * `RSA_MAX_BITS` bits long; and for an exponent that is even, below 3, or
215
+ * not below 2^32 (which also keeps it below the modulus).
216
+ */
217
+ export const rsaParsePublicKey = (der: u8[]): RsaPublicKey | null => {
218
+ const total: i32 = toI32(der.length)
219
+ const body: i32 = rsaDerContents(der, 0, total, 0x30)
220
+ if (body < 0 || body + rsaDerLength(der, 0) !== total) {
221
+ return null
222
+ }
223
+ const nStart: i32 = rsaDerContents(der, body, total, 0x02)
224
+ if (nStart < 0) {
225
+ return null
226
+ }
227
+ const nEnd: i32 = nStart + rsaDerLength(der, body)
228
+ const eStart: i32 = rsaDerContents(der, nEnd, total, 0x02)
229
+ if (eStart < 0) {
230
+ return null
231
+ }
232
+ const eLength: i32 = rsaDerLength(der, nEnd)
233
+ if (eStart + eLength !== total) {
234
+ return null
235
+ }
236
+ const n: u8[] | null = rsaDerUnsigned(der, nStart, nEnd - nStart)
237
+ const e: u8[] | null = rsaDerUnsigned(der, eStart, eLength)
238
+ if (n === null || e === null) {
239
+ return null
240
+ }
241
+ const bits: i32 = rsaBitLength(n)
242
+ if (bits < RSA_MIN_BITS || bits > RSA_MAX_BITS || (toI32(n[toI32(n.length) - 1]) & 1) === 0) {
243
+ return null
244
+ }
245
+ const eLast: i32 = toI32(e[toI32(e.length) - 1])
246
+ if (toI32(e.length) > 4 || (eLast & 1) === 0 || (toI32(e.length) === 1 && eLast < 3)) {
247
+ return null
248
+ }
249
+ return new RsaPublicKey(n, e, bits)
250
+ }
251
+
252
+ // ---------------------------------------------------------------------------
253
+ // Montgomery arithmetic on little-endian u32 limbs
254
+ // ---------------------------------------------------------------------------
255
+
256
+ /** The big-endian `bytes` as `limbs` little-endian `u32` limbs, limb 0 the least significant; `bytes` fits. */
257
+ const rsaLimbsFromBytes = (bytes: u8[], limbs: i32): u32[] => {
258
+ const out: u32[] = new Array<u32>(limbs)
259
+ const size: i32 = toI32(out.length)
260
+ const length: i32 = toI32(bytes.length)
261
+ for (let i: i32 = 0; i < length; i++) {
262
+ const shift: i32 = length - 1 - i
263
+ const limb: i32 = shift >> 2
264
+ if (limb >= 0 && limb < size) {
265
+ out[limb] = out[limb] | (toU32(bytes[i]) << toU32((shift & 3) << 3))
266
+ }
267
+ }
268
+ return out
269
+ }
270
+
271
+ /** The limbs `a` as `size` big-endian bytes; the value fits. */
272
+ const rsaBytesFromLimbs = (a: u32[], size: i32): u8[] => {
273
+ const out: u8[] = new Array<u8>(size)
274
+ const limbs: i32 = toI32(a.length)
275
+ for (let i: i32 = 0; i < toI32(out.length); i++) {
276
+ const shift: i32 = size - 1 - i
277
+ const limb: i32 = shift >> 2
278
+ if (limb >= 0 && limb < limbs) {
279
+ out[i] = toU8(a[limb] >> toU32((shift & 3) << 3))
280
+ }
281
+ }
282
+ return out
283
+ }
284
+
285
+ /**
286
+ * -n^-1 mod 2^32 for the odd limb `n0`, by Newton's iteration: an odd `x`
287
+ * with `x * n0 = 1` mod 2^b gives `x (2 - x n0)` with it mod 2^2b, and
288
+ * `x = n0` already holds mod 8, so four steps reach 2^48.
289
+ */
290
+ const rsaMontInverse = (n0: u32): u32 => {
291
+ let x: u32 = n0
292
+ for (let i: i32 = 0; i < 4; i++) {
293
+ const nx: u32 = toU32(toU64(n0) * toU64(x))
294
+ x = toU32(toU64(x) * toU64(toU32(2 - toU64(nx))))
295
+ }
296
+ return toU32(0 - toU64(x))
297
+ }
298
+
299
+ /** Whether the `count`-limb value `a` is at least `n`, compared from the top limb. */
300
+ const rsaAtLeast = (a: u32[], n: u32[], count: i32): boolean => {
301
+ if (count > toI32(a.length) || count > toI32(n.length)) {
302
+ return true
303
+ }
304
+ for (let i: i32 = count - 1; i >= 0; i--) {
305
+ if (a[i] !== n[i]) {
306
+ return a[i] > n[i]
307
+ }
308
+ }
309
+ return true
310
+ }
311
+
312
+ /** `a = a - n` over `count` limbs, dropping the borrow out of the top. */
313
+ const rsaSubInPlace = (a: u32[], n: u32[], count: i32): void => {
314
+ if (count > toI32(a.length) || count > toI32(n.length)) {
315
+ return
316
+ }
317
+ let borrow: u64 = 0
318
+ for (let i: i32 = 0; i < count; i++) {
319
+ const d: u64 = toU64(a[i]) - toU64(n[i]) - borrow
320
+ a[i] = toU32(d)
321
+ borrow = (d >> 32) & 1
322
+ }
323
+ }
324
+
325
+ /**
326
+ * `out = a b R^-1 mod n`, R = 2^(32 count), for `a` and `b` below `n`: Koç,
327
+ * Acar and Kaliski's CIOS. `t` is scratch of `count + 2` limbs. Each row adds
328
+ * `a b[i]` into `t`, then the multiple `m n` of the modulus that clears the
329
+ * low limb, and shifts down a limb; `t` stays below 2n, and one subtraction
330
+ * of `n` brings it below `n`. Every sum is at most (2^32 - 1) + (2^32 - 1)^2
331
+ * + (2^32 - 1) = 2^64 - 1, so a `u64` holds it.
332
+ */
333
+ const rsaMontMul = (out: u32[], a: u32[], b: u32[], n: u32[], n0inv: u32, t: u32[], count: i32): void => {
334
+ if (
335
+ count < 1 ||
336
+ count > toI32(out.length) ||
337
+ count > toI32(a.length) ||
338
+ count > toI32(b.length) ||
339
+ count > toI32(n.length) ||
340
+ count + 2 > toI32(t.length)
341
+ ) {
342
+ return
343
+ }
344
+ for (let i: i32 = 0; i < toI32(t.length); i++) {
345
+ t[i] = 0
346
+ }
347
+ for (let i: i32 = 0; i < count; i++) {
348
+ const bi: u64 = toU64(b[i])
349
+ let carry: u64 = 0
350
+ for (let j: i32 = 0; j < count; j++) {
351
+ const s: u64 = toU64(t[j]) + toU64(a[j]) * bi + carry
352
+ t[j] = toU32(s)
353
+ carry = s >> 32
354
+ }
355
+ const top: u64 = toU64(t[count]) + carry
356
+ t[count] = toU32(top)
357
+ t[count + 1] = toU32(top >> 32)
358
+ const m: u64 = toU64(toU32(toU64(t[0]) * toU64(n0inv)))
359
+ let c: u64 = (toU64(t[0]) + m * toU64(n[0])) >> 32
360
+ for (let j: i32 = 1; j < count; j++) {
361
+ const s: u64 = toU64(t[j]) + m * toU64(n[j]) + c
362
+ t[j - 1] = toU32(s)
363
+ c = s >> 32
364
+ }
365
+ const last: u64 = toU64(t[count]) + c
366
+ t[count - 1] = toU32(last)
367
+ t[count] = t[count + 1] + toU32(last >> 32)
368
+ }
369
+ if (t[count] !== 0 || rsaAtLeast(t, n, count)) {
370
+ rsaSubInPlace(t, n, count)
371
+ }
372
+ for (let i: i32 = 0; i < count; i++) {
373
+ out[i] = t[i]
374
+ }
375
+ }
376
+
377
+ /** `r = 2 r mod n` over `count` limbs, for `r` below `n`; `r[count]` takes the bit the doubling carries out, so the comparison with `n` sees it. */
378
+ const rsaDoubleMod = (r: u32[], n: u32[], count: i32): void => {
379
+ if (count < 1 || count > toI32(n.length) || count + 1 > toI32(r.length)) {
380
+ return
381
+ }
382
+ let carry: u32 = 0
383
+ for (let i: i32 = 0; i < count; i++) {
384
+ const v: u32 = r[i]
385
+ r[i] = (v << 1) | carry
386
+ carry = v >> 31
387
+ }
388
+ r[count] = carry
389
+ if (carry !== 0 || rsaAtLeast(r, n, count)) {
390
+ rsaSubInPlace(r, n, count)
391
+ r[count] = 0
392
+ }
393
+ }
394
+
395
+ /**
396
+ * R^2 mod n, R = 2^(32 count), for the `count`-limb odd `n`. Writing 32 count
397
+ * as `s 2^j` with `s` odd, doubling 1 modulo `n` 32 count + s times gives
398
+ * R 2^s, and each Montgomery squaring of R 2^x gives R 2^2x, so `j` of them
399
+ * reach R 2^(32 count) = R^2: about a quarter of the work of doubling all the
400
+ * way.
401
+ */
402
+ const rsaMontR2 = (n: u32[], n0inv: u32, t: u32[], count: i32): u32[] => {
403
+ let s: i32 = count << 5
404
+ let squarings: i32 = 0
405
+ while (s > 0 && (s & 1) === 0) {
406
+ s = s >> 1
407
+ squarings += 1
408
+ }
409
+ const r: u32[] = new Array<u32>(count + 1)
410
+ r[0] = 1
411
+ for (let k: i32 = 0; k < (count << 5) + s; k++) {
412
+ rsaDoubleMod(r, n, count)
413
+ }
414
+ for (let k: i32 = 0; k < squarings; k++) {
415
+ rsaMontMul(r, r, r, n, n0inv, t, count)
416
+ }
417
+ return r
418
+ }
419
+
420
+ /**
421
+ * `s^e mod n` as `size` big-endian bytes, for an odd `n` and an `s` below it.
422
+ * R^2 mod n comes from `rsaMontR2`; `s` is moved into
423
+ * the Montgomery domain by one multiplication by it, raised by square and
424
+ * multiply from the exponent's top bit, and moved out by a multiplication by 1.
425
+ */
426
+ const rsaModPow = (s: u8[], e: u8[], n: u8[], size: i32): u8[] => {
427
+ const count: i32 = (toI32(n.length) + 3) >> 2
428
+ const nl: u32[] = rsaLimbsFromBytes(n, count)
429
+ const n0inv: u32 = rsaMontInverse(nl[0])
430
+ const t: u32[] = new Array<u32>(count + 2)
431
+ const r2: u32[] = rsaMontR2(nl, n0inv, t, count)
432
+ const base: u32[] = new Array<u32>(count)
433
+ rsaMontMul(base, rsaLimbsFromBytes(s, count), r2, nl, n0inv, t, count)
434
+ const acc: u32[] = new Array<u32>(count)
435
+ for (let i: i32 = 0; i < toI32(acc.length) && i < toI32(base.length); i++) {
436
+ acc[i] = base[i]
437
+ }
438
+ const bits: i32 = rsaBitLength(e)
439
+ const eLength: i32 = toI32(e.length)
440
+ for (let k: i32 = bits - 2; k >= 0; k--) {
441
+ rsaMontMul(acc, acc, acc, nl, n0inv, t, count)
442
+ const at: i32 = eLength - 1 - (k >> 3)
443
+ if (at >= 0 && at < eLength && ((toI32(e[at]) >> (k & 7)) & 1) === 1) {
444
+ rsaMontMul(acc, acc, base, nl, n0inv, t, count)
445
+ }
446
+ }
447
+ const one: u32[] = new Array<u32>(count)
448
+ one[0] = 1
449
+ rsaMontMul(acc, acc, one, nl, n0inv, t, count)
450
+ return rsaBytesFromLimbs(acc, size)
451
+ }
452
+
453
+ /**
454
+ * RSAVP1 (RFC 8017 §5.2.2) after §8.1.2 and §8.2.2's step 1: the signature as
455
+ * `size` big-endian bytes raised to `e` mod `n`, or `null` when the signature
456
+ * is not exactly as long as the modulus or its integer is not below `n`.
457
+ * `size` is the encoded message's length, the modulus's or one byte less; a
458
+ * value too large for it answers `null`.
459
+ */
460
+ const rsaOpen = (key: RsaPublicKey, sig: u8[], size: i32): u8[] | null => {
461
+ const k: i32 = toI32(sig.length)
462
+ if (k !== toI32(key.n.length) || size < 0 || size > k) {
463
+ return null
464
+ }
465
+ let lead: i32 = 0
466
+ while (lead < k && toI32(sig[lead]) === 0) {
467
+ lead += 1
468
+ }
469
+ const trimmed: u8[] = new Array<u8>(k - lead)
470
+ for (let i: i32 = lead; i < k; i++) {
471
+ trimmed[i - lead] = sig[i]
472
+ }
473
+ if (!rsaBytesBelow(trimmed, key.n)) {
474
+ return null
475
+ }
476
+ const m: u8[] = rsaModPow(trimmed, key.e, key.n, k)
477
+ const mLength: i32 = toI32(m.length)
478
+ for (let i: i32 = 0; i < mLength - size && i < mLength; i++) {
479
+ if (toI32(m[i]) !== 0) {
480
+ return null
481
+ }
482
+ }
483
+ const out: u8[] = new Array<u8>(size)
484
+ for (let i: i32 = 0; i < toI32(out.length); i++) {
485
+ out[i] = m[mLength - size + i]
486
+ }
487
+ return out
488
+ }
489
+
490
+ // ---------------------------------------------------------------------------
491
+ // The encodings (RFC 8017 §9.1, §9.2, §B.2.1)
492
+ // ---------------------------------------------------------------------------
493
+
494
+ /** The digest length of the hash id `hash`, or 0 for an id this module does not know. */
495
+ const rsaHashSize = (hash: i32): i32 => {
496
+ if (hash === RSA_HASH_SHA256) {
497
+ return 32
498
+ }
499
+ if (hash === RSA_HASH_SHA384) {
500
+ return 48
501
+ }
502
+ if (hash === RSA_HASH_SHA512) {
503
+ return 64
504
+ }
505
+ return 0
506
+ }
507
+
508
+ /** The digest of `data` under the hash id `hash`, which `rsaHashSize` knows. */
509
+ const rsaDigest = (hash: i32, data: u8[]): u8[] => {
510
+ if (hash === RSA_HASH_SHA384) {
511
+ return sha384(data)
512
+ }
513
+ if (hash === RSA_HASH_SHA512) {
514
+ return sha512(data)
515
+ }
516
+ return sha256(data)
517
+ }
518
+
519
+ /**
520
+ * The DER of the DigestInfo's algorithm and the OCTET STRING header before
521
+ * the digest, RFC 8017 §9.2 note 1: the id-sha256, id-sha384 or id-sha512 OID
522
+ * with NULL parameters. The OIDs differ in their last octet alone.
523
+ */
524
+ const rsaDigestInfoPrefix = (hash: i32, hashSize: i32): u8[] => {
525
+ const out: u8[] = [
526
+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
527
+ 0x04, 0x20,
528
+ ]
529
+ out[1] = toU8(hashSize + 17)
530
+ out[14] = toU8(hash)
531
+ out[18] = toU8(hashSize)
532
+ return out
533
+ }
534
+
535
+ /** Whether `a` and `b` hold the same bytes. Both are public, so it stops at the first difference. */
536
+ const rsaSameBytes = (a: u8[], b: u8[]): boolean => {
537
+ const length: i32 = toI32(a.length)
538
+ if (toI32(b.length) !== length) {
539
+ return false
540
+ }
541
+ for (let i: i32 = 0; i < length && i < toI32(b.length); i++) {
542
+ if (a[i] !== b[i]) {
543
+ return false
544
+ }
545
+ }
546
+ return true
547
+ }
548
+
549
+ /**
550
+ * Verifies an RSASSA-PKCS1-v1_5 signature (RFC 8017 §8.2.2) of `msg` under
551
+ * `key`, with the hash id `hash`. The encoded message the signature should
552
+ * open to, `00 01 FF … FF 00 DigestInfo`, is built whole (EMSA-PKCS1-v1_5,
553
+ * §9.2) and compared with what it does open to. `false` for an unknown hash
554
+ * id, a modulus too short for the encoding, a signature that is not exactly
555
+ * as long as the modulus or not below it, and any other bytes.
556
+ */
557
+ export const rsaVerifyPkcs1v15 = (key: RsaPublicKey, hash: i32, msg: u8[], sig: u8[]): boolean => {
558
+ const hashSize: i32 = rsaHashSize(hash)
559
+ const k: i32 = toI32(key.n.length)
560
+ const prefix: u8[] = rsaDigestInfoPrefix(hash, hashSize)
561
+ const tLength: i32 = toI32(prefix.length) + hashSize
562
+ if (hashSize === 0 || k < tLength + 11) {
563
+ return false
564
+ }
565
+ const em: u8[] | null = rsaOpen(key, sig, k)
566
+ if (em === null) {
567
+ return false
568
+ }
569
+ const expected: u8[] = [0x00, 0x01]
570
+ for (let i: i32 = 2; i < k - tLength - 1; i++) {
571
+ expected.push(0xff)
572
+ }
573
+ expected.push(0x00)
574
+ for (const byte of prefix) {
575
+ expected.push(byte)
576
+ }
577
+ for (const byte of rsaDigest(hash, msg)) {
578
+ expected.push(byte)
579
+ }
580
+ return rsaSameBytes(em, expected)
581
+ }
582
+
583
+ /**
584
+ * MGF1 (RFC 8017 §B.2.1) with the hash id `hash` over `seed`, `length` bytes:
585
+ * the digests of `seed || C` for the four-byte counters C = 0, 1, …, joined.
586
+ */
587
+ const rsaMgf1 = (hash: i32, seed: u8[], length: i32): u8[] => {
588
+ const out: u8[] = []
589
+ for (let counter: i32 = 0; toI32(out.length) < length; counter++) {
590
+ const input: u8[] = []
591
+ for (const byte of seed) {
592
+ input.push(byte)
593
+ }
594
+ input.push(toU8(counter >> 24))
595
+ input.push(toU8(counter >> 16))
596
+ input.push(toU8(counter >> 8))
597
+ input.push(toU8(counter))
598
+ for (const byte of rsaDigest(hash, input)) {
599
+ if (toI32(out.length) < length) {
600
+ out.push(byte)
601
+ }
602
+ }
603
+ }
604
+ return out
605
+ }
606
+
607
+ /**
608
+ * Verifies an RSASSA-PSS signature (RFC 8017 §8.1.2) of `msg` under `key`,
609
+ * with the hash id `hash` for the message and for MGF1, and a salt of exactly
610
+ * `saltLen` bytes. Every check of EMSA-PSS-VERIFY (§9.1.2) is made: the
611
+ * length, the trailing 0xbc, the leftmost `8 emLen - emBits` bits of the
612
+ * masked block and of the unmasked one, the zero octets and the 0x01 before
613
+ * the salt, and the hash. `false` for any of them, an unknown hash id, a
614
+ * negative `saltLen`, and a signature that is not exactly as long as the
615
+ * modulus or not below it.
616
+ */
617
+ export const rsaVerifyPss = (key: RsaPublicKey, hash: i32, saltLen: i32, msg: u8[], sig: u8[]): boolean => {
618
+ const hashSize: i32 = rsaHashSize(hash)
619
+ if (hashSize === 0 || saltLen < 0) {
620
+ return false
621
+ }
622
+ const emBits: i32 = rsaBitLength(key.n) - 1
623
+ const emLen: i32 = (emBits + 7) >> 3
624
+ if (saltLen > emLen || emLen < hashSize + saltLen + 2) {
625
+ return false
626
+ }
627
+ const em: u8[] | null = rsaOpen(key, sig, emLen)
628
+ if (em === null || toI32(em[emLen - 1]) !== 0xbc) {
629
+ return false
630
+ }
631
+ const dbLength: i32 = emLen - hashSize - 1
632
+ const full: i32 = 0xff
633
+ const topMask: i32 = full >> ((emLen << 3) - emBits)
634
+ if ((toI32(em[0]) & ~topMask) !== 0) {
635
+ return false
636
+ }
637
+ const h: u8[] = []
638
+ for (let i: i32 = dbLength; i < emLen - 1; i++) {
639
+ h.push(em[i])
640
+ }
641
+ const db: u8[] = rsaMgf1(hash, h, dbLength)
642
+ for (let i: i32 = 0; i < dbLength && i < toI32(db.length); i++) {
643
+ db[i] = db[i] ^ em[i]
644
+ }
645
+ db[0] = toU8(toI32(db[0]) & topMask)
646
+ const zeros: i32 = emLen - hashSize - saltLen - 2
647
+ for (let i: i32 = 0; i < zeros && i < toI32(db.length); i++) {
648
+ if (toI32(db[i]) !== 0) {
649
+ return false
650
+ }
651
+ }
652
+ if (toI32(db[zeros]) !== 0x01) {
653
+ return false
654
+ }
655
+ const prime: u8[] = [0, 0, 0, 0, 0, 0, 0, 0]
656
+ for (const byte of rsaDigest(hash, msg)) {
657
+ prime.push(byte)
658
+ }
659
+ for (let i: i32 = dbLength - saltLen; i >= 0 && i < dbLength && i < toI32(db.length); i++) {
660
+ prime.push(db[i])
661
+ }
662
+ return rsaSameBytes(rsaDigest(hash, prime), h)
663
+ }