@amritk/nish-aarch64-linux 0.13.0 → 0.15.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.
- package/bin/nish +0 -0
- package/package.json +1 -1
- package/runtime/nish.d.ts +156 -0
- package/runtime/nish.h +89 -0
- package/runtime/nish.mjs +58 -0
- package/runtime/runtime-host.c +178 -0
- package/runtime/runtime-net.c +528 -0
- package/runtime/runtime-os.c +15 -0
- package/runtime/shim.mjs +137 -0
- package/scripts/build.sh +9 -7
- package/std/README.md +80 -0
- package/std/crypto/LICENSE-bearssl +21 -0
- package/std/crypto/LICENSE-fiat-crypto +21 -0
- package/std/crypto/aes.ts +899 -0
- package/std/crypto/base64url.ts +145 -0
- package/std/crypto/chacha20poly1305.ts +698 -0
- package/std/crypto/ct.ts +64 -0
- package/std/crypto/hkdf.ts +118 -0
- package/std/crypto/hmac.ts +155 -0
- package/std/crypto/p256.ts +4337 -0
- package/std/crypto/sha256.ts +444 -0
- package/std/crypto/sha512.ts +510 -0
- package/std/crypto/x25519.ts +509 -0
- package/std/crypto/x509.ts +1214 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `nish/crypto/base64url` — RFC 4648 §5 base64url, unpadded, as JWS and the
|
|
3
|
+
* relay's grants spell a key or a tag inside a URL or a header.
|
|
4
|
+
*
|
|
5
|
+
* The alphabet is `A-Z a-z 0-9 - _`, and there is no `=`: the length of the
|
|
6
|
+
* text already says how many bytes the last group holds (RFC 4648 §3.2 lets a
|
|
7
|
+
* specification that knows its lengths drop the padding, and RFC 7515 §2 does).
|
|
8
|
+
*
|
|
9
|
+
* **Decoding is strict, so that each byte string has exactly one spelling.**
|
|
10
|
+
* `base64urlDecode` answers `null` for a `=` anywhere, for any character outside
|
|
11
|
+
* the alphabet (whitespace included), for a length of 1 mod 4 — six bits, not a
|
|
12
|
+
* byte — and for a final character whose unused low bits are not zero (RFC 4648
|
|
13
|
+
* §3.5). A lenient decoder would let `AB` and `AA` both mean `00`, and a token
|
|
14
|
+
* compared or cached by its text would then have two identities.
|
|
15
|
+
*
|
|
16
|
+
* **Neither direction indexes or branches on the data.** What is encoded here
|
|
17
|
+
* is usually a key, a nonce or a MAC, and a lookup table indexed by a secret
|
|
18
|
+
* sextet leaves its trace in the cache. So a sextet becomes a character, and a
|
|
19
|
+
* character a sextet, by arithmetic on range masks: `(lo - 1 - c) & (c - hi - 1)`
|
|
20
|
+
* is negative exactly when `lo <= c <= hi`, and an arithmetic shift by 31 turns
|
|
21
|
+
* that sign into an all-ones or all-zeros mask. A malformed character is not
|
|
22
|
+
* refused where it is found either: the verdict is ORed into one word and read
|
|
23
|
+
* once, after the whole text. The text's length is public and is tested first.
|
|
24
|
+
*
|
|
25
|
+
* Private helpers share the importing program's flat symbol namespace
|
|
26
|
+
* (`docs/wp26-stdlib.md` §3e), which is why each one carries the module's name.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* All ones when `lo <= c <= hi`, else zero, without a branch. `c` is a byte or
|
|
31
|
+
* a sextet, so neither subtraction can overflow.
|
|
32
|
+
*/
|
|
33
|
+
const base64urlRangeMask = (c: i32, lo: i32, hi: i32): i32 => ((lo - 1 - c) & (c - hi - 1)) >> 31
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The URL-alphabet character for the sextet `v` (`0 <= v <= 63`).
|
|
37
|
+
*
|
|
38
|
+
* It starts from `'A' + v` and adds, for each range `v` has passed, the step
|
|
39
|
+
* from the previous range's first character to this one's: 26 lands on `a`, 52
|
|
40
|
+
* on `0`, 62 on `-` and 63 on `_`.
|
|
41
|
+
*/
|
|
42
|
+
const base64urlCharOf = (v: i32): i32 =>
|
|
43
|
+
65 +
|
|
44
|
+
v +
|
|
45
|
+
(base64urlRangeMask(v, 26, 63) & 6) -
|
|
46
|
+
(base64urlRangeMask(v, 52, 63) & 75) -
|
|
47
|
+
(base64urlRangeMask(v, 62, 63) & 13) +
|
|
48
|
+
(base64urlRangeMask(v, 63, 63) & 49)
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The sextet the byte `c` stands for, or `-1` when `c` is not in the alphabet.
|
|
52
|
+
* Each range contributes its value under its own mask, and a byte in none of
|
|
53
|
+
* them has every bit set by the final OR.
|
|
54
|
+
*/
|
|
55
|
+
const base64urlSextetOf = (c: i32): i32 => {
|
|
56
|
+
const upper: i32 = base64urlRangeMask(c, 65, 90)
|
|
57
|
+
const lower: i32 = base64urlRangeMask(c, 97, 122)
|
|
58
|
+
const digit: i32 = base64urlRangeMask(c, 48, 57)
|
|
59
|
+
const dash: i32 = base64urlRangeMask(c, 45, 45)
|
|
60
|
+
const underscore: i32 = base64urlRangeMask(c, 95, 95)
|
|
61
|
+
const value: i32 =
|
|
62
|
+
(upper & (c - 65)) | (lower & (c - 71)) | (digit & (c + 4)) | (dash & 62) | (underscore & 63)
|
|
63
|
+
return value | ~(upper | lower | digit | dash | underscore)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* `data` as unpadded base64url: four characters per three bytes, and two or
|
|
68
|
+
* three for a short final group.
|
|
69
|
+
*
|
|
70
|
+
* Bytes go into a bit accumulator eight at a time and come out six at a time,
|
|
71
|
+
* so one index walks the input and the only branches are on how many bits are
|
|
72
|
+
* waiting — which depends on the position, never on the bytes.
|
|
73
|
+
*/
|
|
74
|
+
export const base64urlEncode = (data: u8[]): string => {
|
|
75
|
+
const parts: string[] = []
|
|
76
|
+
let acc: i32 = 0
|
|
77
|
+
let bits: i32 = 0
|
|
78
|
+
for (let k: i32 = 0; k < toI32(data.length); k++) {
|
|
79
|
+
// At most four bits wait from the bytes before, so twelve are live here;
|
|
80
|
+
// the mask keeps the accumulator from growing without bound.
|
|
81
|
+
acc = ((acc << 8) | toI32(data[k])) & 0xfff
|
|
82
|
+
bits += 8
|
|
83
|
+
while (bits >= 6) {
|
|
84
|
+
bits -= 6
|
|
85
|
+
parts.push(String.fromCharCode(base64urlCharOf((acc >> bits) & 63)))
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Two or four bits of a final byte are left: they go out as the high bits of
|
|
89
|
+
// one more sextet, filled out with zeros.
|
|
90
|
+
if (bits > 0) {
|
|
91
|
+
parts.push(String.fromCharCode(base64urlCharOf((acc << (6 - bits)) & 63)))
|
|
92
|
+
}
|
|
93
|
+
return parts.join("")
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The bytes `text` spells in unpadded base64url, or `null` when it is not the
|
|
98
|
+
* one canonical spelling of any byte string — see the module comment for the
|
|
99
|
+
* four refusals.
|
|
100
|
+
*
|
|
101
|
+
* The same accumulator as `base64urlEncode`, run the other way: six bits in per
|
|
102
|
+
* character, eight out per byte.
|
|
103
|
+
*/
|
|
104
|
+
export const base64urlDecode = (text: string): u8[] | null => {
|
|
105
|
+
const n: i32 = toI32(text.length)
|
|
106
|
+
const tail: i32 = n & 3
|
|
107
|
+
// Six bits cannot finish a byte, so a single character after the last full
|
|
108
|
+
// group spells nothing.
|
|
109
|
+
if (tail === 1) {
|
|
110
|
+
return null
|
|
111
|
+
}
|
|
112
|
+
// Three bytes per full group of four, and one fewer than the characters in a
|
|
113
|
+
// short final group; `n * 3 / 4` would overflow for a text over 700 MB.
|
|
114
|
+
const out: u8[] = new Array<u8>((n >> 2) * 3 + (tail === 0 ? 0 : tail - 1))
|
|
115
|
+
const outLen: i32 = toI32(out.length)
|
|
116
|
+
// All ones once any character is outside the alphabet (its sextet of `-1`
|
|
117
|
+
// shifted right by 31), and non-zero once the text ends on a bit that
|
|
118
|
+
// encodes no byte.
|
|
119
|
+
let bad: i32 = 0
|
|
120
|
+
let acc: i32 = 0
|
|
121
|
+
let bits: i32 = 0
|
|
122
|
+
let j: i32 = 0
|
|
123
|
+
for (let k: i32 = 0; k < n; k++) {
|
|
124
|
+
const v: i32 = base64urlSextetOf(toI32(text.charCodeAt(k)))
|
|
125
|
+
bad = bad | (v >> 31)
|
|
126
|
+
acc = ((acc << 6) | (v & 63)) & 0xfff
|
|
127
|
+
bits += 6
|
|
128
|
+
if (bits >= 8) {
|
|
129
|
+
bits -= 8
|
|
130
|
+
// Always true — `out` was sized from the same length — but written out
|
|
131
|
+
// so that the store keeps no bounds check.
|
|
132
|
+
if (j >= 0 && j < outLen) {
|
|
133
|
+
out[j] = toU8((acc >> bits) & 255)
|
|
134
|
+
}
|
|
135
|
+
j++
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// The two or four bits left over belong to no byte, and must be zero so that
|
|
139
|
+
// `AA` is the only spelling of a zero byte and `AB` is refused (RFC 4648 §3.5).
|
|
140
|
+
bad = bad | (acc & ((1 << bits) - 1))
|
|
141
|
+
if (bad !== 0) {
|
|
142
|
+
return null
|
|
143
|
+
}
|
|
144
|
+
return out
|
|
145
|
+
}
|