@amritk/nish-x86_64-linux 0.13.0 → 0.14.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 +65 -0
- package/runtime/nish.h +31 -0
- package/runtime/nish.mjs +35 -0
- package/runtime/runtime-host.c +178 -0
- package/runtime/runtime-os.c +15 -0
- package/runtime/shim.mjs +122 -0
- package/scripts/build.sh +8 -7
- package/std/README.md +40 -0
- package/std/crypto/base64url.ts +145 -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/sha256.ts +444 -0
- package/std/crypto/sha512.ts +510 -0
- package/std/crypto/x25519.ts +494 -0
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `nish/crypto/sha512` — SHA-512 and SHA-384, written from FIPS 180-4.
|
|
3
|
+
*
|
|
4
|
+
* Both hashes are one compression function over eight 64-bit words: SHA-384
|
|
5
|
+
* starts from its own initial value (§5.3.4) and keeps the first 48 bytes of
|
|
6
|
+
* the result (§6.5), SHA-512 starts from §5.3.5 and keeps all 64. So one
|
|
7
|
+
* engine does the work, and `Sha512` and `Sha384` are the two ways to start it.
|
|
8
|
+
*
|
|
9
|
+
* A hasher streams: `update` any number of windows, `copy` to take an
|
|
10
|
+
* independent hasher at the same point (TLS 1.3 hashes its transcript and
|
|
11
|
+
* reads intermediate hashes of it), then `digest` once. The work depends on how
|
|
12
|
+
* many bytes arrive and never on their values: there is no branch and no table
|
|
13
|
+
* index on message data, so a secret message (an HMAC key, a transcript) is
|
|
14
|
+
* hashed in time that says nothing about it but its length.
|
|
15
|
+
*
|
|
16
|
+
* The constants are the fractional parts of the cube roots of the first eighty
|
|
17
|
+
* primes (§4.2.3) and of the square roots of the first sixteen (§5.3.4, §5.3.5),
|
|
18
|
+
* as FIPS 180-4 defines them. A literal past 2^53 cannot be written exactly, so
|
|
19
|
+
* each is spelled as its two 32-bit halves.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/** The length of a SHA-512 digest, in bytes. */
|
|
23
|
+
export const SHA512_SIZE: i32 = 64
|
|
24
|
+
/** The length of a SHA-384 digest, in bytes. */
|
|
25
|
+
export const SHA384_SIZE: i32 = 48
|
|
26
|
+
/** The block both hashes compress, in bytes. */
|
|
27
|
+
export const SHA512_BLOCK: i32 = 128
|
|
28
|
+
|
|
29
|
+
/** The block offset at which padding writes the 128-bit message length (§5.1.2). */
|
|
30
|
+
const LENGTH_AT: i32 = 112
|
|
31
|
+
|
|
32
|
+
/** SHA-512's rounds per block, and so the length of its message schedule (§6.4.2). */
|
|
33
|
+
const ROUNDS: i32 = 80
|
|
34
|
+
|
|
35
|
+
/** Offset zero, spelled as an `i32` so a method argument keeps that type in f64 mode (`reject_method_arg_literal`). */
|
|
36
|
+
const OFFSET_ZERO: i32 = 0
|
|
37
|
+
|
|
38
|
+
const w64 = (hi: u32, lo: u32): u64 => (toU64(hi) << 32) | toU64(lo)
|
|
39
|
+
|
|
40
|
+
/** ROTR^n (§3.2), for 0 < n < 64. */
|
|
41
|
+
const rotr = (x: u64, n: u64): u64 => (x >> n) | (x << (64 - n))
|
|
42
|
+
|
|
43
|
+
// The four functions of §4.1.3.
|
|
44
|
+
const bigSigma0 = (x: u64): u64 => rotr(x, 28) ^ rotr(x, 34) ^ rotr(x, 39)
|
|
45
|
+
const bigSigma1 = (x: u64): u64 => rotr(x, 14) ^ rotr(x, 18) ^ rotr(x, 41)
|
|
46
|
+
const smallSigma0 = (x: u64): u64 => rotr(x, 1) ^ rotr(x, 8) ^ (x >> 7)
|
|
47
|
+
const smallSigma1 = (x: u64): u64 => rotr(x, 19) ^ rotr(x, 61) ^ (x >> 6)
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* K{512}_t (§4.2.3): the first 64 bits of the fractional parts of the cube
|
|
51
|
+
* roots of the first eighty primes.
|
|
52
|
+
*
|
|
53
|
+
* A function over a `switch` rather than an array, because a module constant
|
|
54
|
+
* cannot be an array and building one per hasher costs eighty stores on every
|
|
55
|
+
* `new` and every `copy()`. Every arm is a constant once `w64` folds, and LLVM
|
|
56
|
+
* turns such a `switch` into one read-only table, so a round reads K with one
|
|
57
|
+
* load. `t` is the round number, never message data.
|
|
58
|
+
*/
|
|
59
|
+
const roundConstant = (t: i32): u64 => {
|
|
60
|
+
switch (t) {
|
|
61
|
+
case 0:
|
|
62
|
+
return w64(0x428a2f98, 0xd728ae22)
|
|
63
|
+
case 1:
|
|
64
|
+
return w64(0x71374491, 0x23ef65cd)
|
|
65
|
+
case 2:
|
|
66
|
+
return w64(0xb5c0fbcf, 0xec4d3b2f)
|
|
67
|
+
case 3:
|
|
68
|
+
return w64(0xe9b5dba5, 0x8189dbbc)
|
|
69
|
+
case 4:
|
|
70
|
+
return w64(0x3956c25b, 0xf348b538)
|
|
71
|
+
case 5:
|
|
72
|
+
return w64(0x59f111f1, 0xb605d019)
|
|
73
|
+
case 6:
|
|
74
|
+
return w64(0x923f82a4, 0xaf194f9b)
|
|
75
|
+
case 7:
|
|
76
|
+
return w64(0xab1c5ed5, 0xda6d8118)
|
|
77
|
+
case 8:
|
|
78
|
+
return w64(0xd807aa98, 0xa3030242)
|
|
79
|
+
case 9:
|
|
80
|
+
return w64(0x12835b01, 0x45706fbe)
|
|
81
|
+
case 10:
|
|
82
|
+
return w64(0x243185be, 0x4ee4b28c)
|
|
83
|
+
case 11:
|
|
84
|
+
return w64(0x550c7dc3, 0xd5ffb4e2)
|
|
85
|
+
case 12:
|
|
86
|
+
return w64(0x72be5d74, 0xf27b896f)
|
|
87
|
+
case 13:
|
|
88
|
+
return w64(0x80deb1fe, 0x3b1696b1)
|
|
89
|
+
case 14:
|
|
90
|
+
return w64(0x9bdc06a7, 0x25c71235)
|
|
91
|
+
case 15:
|
|
92
|
+
return w64(0xc19bf174, 0xcf692694)
|
|
93
|
+
case 16:
|
|
94
|
+
return w64(0xe49b69c1, 0x9ef14ad2)
|
|
95
|
+
case 17:
|
|
96
|
+
return w64(0xefbe4786, 0x384f25e3)
|
|
97
|
+
case 18:
|
|
98
|
+
return w64(0x0fc19dc6, 0x8b8cd5b5)
|
|
99
|
+
case 19:
|
|
100
|
+
return w64(0x240ca1cc, 0x77ac9c65)
|
|
101
|
+
case 20:
|
|
102
|
+
return w64(0x2de92c6f, 0x592b0275)
|
|
103
|
+
case 21:
|
|
104
|
+
return w64(0x4a7484aa, 0x6ea6e483)
|
|
105
|
+
case 22:
|
|
106
|
+
return w64(0x5cb0a9dc, 0xbd41fbd4)
|
|
107
|
+
case 23:
|
|
108
|
+
return w64(0x76f988da, 0x831153b5)
|
|
109
|
+
case 24:
|
|
110
|
+
return w64(0x983e5152, 0xee66dfab)
|
|
111
|
+
case 25:
|
|
112
|
+
return w64(0xa831c66d, 0x2db43210)
|
|
113
|
+
case 26:
|
|
114
|
+
return w64(0xb00327c8, 0x98fb213f)
|
|
115
|
+
case 27:
|
|
116
|
+
return w64(0xbf597fc7, 0xbeef0ee4)
|
|
117
|
+
case 28:
|
|
118
|
+
return w64(0xc6e00bf3, 0x3da88fc2)
|
|
119
|
+
case 29:
|
|
120
|
+
return w64(0xd5a79147, 0x930aa725)
|
|
121
|
+
case 30:
|
|
122
|
+
return w64(0x06ca6351, 0xe003826f)
|
|
123
|
+
case 31:
|
|
124
|
+
return w64(0x14292967, 0x0a0e6e70)
|
|
125
|
+
case 32:
|
|
126
|
+
return w64(0x27b70a85, 0x46d22ffc)
|
|
127
|
+
case 33:
|
|
128
|
+
return w64(0x2e1b2138, 0x5c26c926)
|
|
129
|
+
case 34:
|
|
130
|
+
return w64(0x4d2c6dfc, 0x5ac42aed)
|
|
131
|
+
case 35:
|
|
132
|
+
return w64(0x53380d13, 0x9d95b3df)
|
|
133
|
+
case 36:
|
|
134
|
+
return w64(0x650a7354, 0x8baf63de)
|
|
135
|
+
case 37:
|
|
136
|
+
return w64(0x766a0abb, 0x3c77b2a8)
|
|
137
|
+
case 38:
|
|
138
|
+
return w64(0x81c2c92e, 0x47edaee6)
|
|
139
|
+
case 39:
|
|
140
|
+
return w64(0x92722c85, 0x1482353b)
|
|
141
|
+
case 40:
|
|
142
|
+
return w64(0xa2bfe8a1, 0x4cf10364)
|
|
143
|
+
case 41:
|
|
144
|
+
return w64(0xa81a664b, 0xbc423001)
|
|
145
|
+
case 42:
|
|
146
|
+
return w64(0xc24b8b70, 0xd0f89791)
|
|
147
|
+
case 43:
|
|
148
|
+
return w64(0xc76c51a3, 0x0654be30)
|
|
149
|
+
case 44:
|
|
150
|
+
return w64(0xd192e819, 0xd6ef5218)
|
|
151
|
+
case 45:
|
|
152
|
+
return w64(0xd6990624, 0x5565a910)
|
|
153
|
+
case 46:
|
|
154
|
+
return w64(0xf40e3585, 0x5771202a)
|
|
155
|
+
case 47:
|
|
156
|
+
return w64(0x106aa070, 0x32bbd1b8)
|
|
157
|
+
case 48:
|
|
158
|
+
return w64(0x19a4c116, 0xb8d2d0c8)
|
|
159
|
+
case 49:
|
|
160
|
+
return w64(0x1e376c08, 0x5141ab53)
|
|
161
|
+
case 50:
|
|
162
|
+
return w64(0x2748774c, 0xdf8eeb99)
|
|
163
|
+
case 51:
|
|
164
|
+
return w64(0x34b0bcb5, 0xe19b48a8)
|
|
165
|
+
case 52:
|
|
166
|
+
return w64(0x391c0cb3, 0xc5c95a63)
|
|
167
|
+
case 53:
|
|
168
|
+
return w64(0x4ed8aa4a, 0xe3418acb)
|
|
169
|
+
case 54:
|
|
170
|
+
return w64(0x5b9cca4f, 0x7763e373)
|
|
171
|
+
case 55:
|
|
172
|
+
return w64(0x682e6ff3, 0xd6b2b8a3)
|
|
173
|
+
case 56:
|
|
174
|
+
return w64(0x748f82ee, 0x5defb2fc)
|
|
175
|
+
case 57:
|
|
176
|
+
return w64(0x78a5636f, 0x43172f60)
|
|
177
|
+
case 58:
|
|
178
|
+
return w64(0x84c87814, 0xa1f0ab72)
|
|
179
|
+
case 59:
|
|
180
|
+
return w64(0x8cc70208, 0x1a6439ec)
|
|
181
|
+
case 60:
|
|
182
|
+
return w64(0x90befffa, 0x23631e28)
|
|
183
|
+
case 61:
|
|
184
|
+
return w64(0xa4506ceb, 0xde82bde9)
|
|
185
|
+
case 62:
|
|
186
|
+
return w64(0xbef9a3f7, 0xb2c67915)
|
|
187
|
+
case 63:
|
|
188
|
+
return w64(0xc67178f2, 0xe372532b)
|
|
189
|
+
case 64:
|
|
190
|
+
return w64(0xca273ece, 0xea26619c)
|
|
191
|
+
case 65:
|
|
192
|
+
return w64(0xd186b8c7, 0x21c0c207)
|
|
193
|
+
case 66:
|
|
194
|
+
return w64(0xeada7dd6, 0xcde0eb1e)
|
|
195
|
+
case 67:
|
|
196
|
+
return w64(0xf57d4f7f, 0xee6ed178)
|
|
197
|
+
case 68:
|
|
198
|
+
return w64(0x06f067aa, 0x72176fba)
|
|
199
|
+
case 69:
|
|
200
|
+
return w64(0x0a637dc5, 0xa2c898a6)
|
|
201
|
+
case 70:
|
|
202
|
+
return w64(0x113f9804, 0xbef90dae)
|
|
203
|
+
case 71:
|
|
204
|
+
return w64(0x1b710b35, 0x131c471b)
|
|
205
|
+
case 72:
|
|
206
|
+
return w64(0x28db77f5, 0x23047d84)
|
|
207
|
+
case 73:
|
|
208
|
+
return w64(0x32caab7b, 0x40c72493)
|
|
209
|
+
case 74:
|
|
210
|
+
return w64(0x3c9ebe0a, 0x15c9bebc)
|
|
211
|
+
case 75:
|
|
212
|
+
return w64(0x431d67c4, 0x9c100d4c)
|
|
213
|
+
case 76:
|
|
214
|
+
return w64(0x4cc5d4be, 0xcb3e42b6)
|
|
215
|
+
case 77:
|
|
216
|
+
return w64(0x597f299c, 0xfc657e2a)
|
|
217
|
+
case 78:
|
|
218
|
+
return w64(0x5fcb6fab, 0x3ad6faec)
|
|
219
|
+
case 79:
|
|
220
|
+
return w64(0x6c44198c, 0x4a475817)
|
|
221
|
+
// Unreachable: `t` is a round number, 0 to 79. A `default` of its own
|
|
222
|
+
// keeps K_79 inside the table, so the lookup needs no range test first.
|
|
223
|
+
default:
|
|
224
|
+
return 0
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** H(0) for SHA-512 (§5.3.5). */
|
|
229
|
+
const sha512Initial = (): u64[] => [
|
|
230
|
+
w64(0x6a09e667, 0xf3bcc908),
|
|
231
|
+
w64(0xbb67ae85, 0x84caa73b),
|
|
232
|
+
w64(0x3c6ef372, 0xfe94f82b),
|
|
233
|
+
w64(0xa54ff53a, 0x5f1d36f1),
|
|
234
|
+
w64(0x510e527f, 0xade682d1),
|
|
235
|
+
w64(0x9b05688c, 0x2b3e6c1f),
|
|
236
|
+
w64(0x1f83d9ab, 0xfb41bd6b),
|
|
237
|
+
w64(0x5be0cd19, 0x137e2179),
|
|
238
|
+
]
|
|
239
|
+
|
|
240
|
+
/** H(0) for SHA-384 (§5.3.4). */
|
|
241
|
+
const sha384Initial = (): u64[] => [
|
|
242
|
+
w64(0xcbbb9d5d, 0xc1059ed8),
|
|
243
|
+
w64(0x629a292a, 0x367cd507),
|
|
244
|
+
w64(0x9159015a, 0x3070dd17),
|
|
245
|
+
w64(0x152fecd8, 0xf70e5939),
|
|
246
|
+
w64(0x67332667, 0xffc00b31),
|
|
247
|
+
w64(0x8eb44a87, 0x68581511),
|
|
248
|
+
w64(0xdb0c2e0d, 0x64f98fa7),
|
|
249
|
+
w64(0x47b5481d, 0xbefa4fa4),
|
|
250
|
+
]
|
|
251
|
+
|
|
252
|
+
/** The big-endian 64-bit word at `buf[off]`. */
|
|
253
|
+
const loadWord = (buf: u8[], off: i32): u64 => {
|
|
254
|
+
let word: u64 = 0
|
|
255
|
+
for (let i: i32 = 0; i < 8; i++) {
|
|
256
|
+
word = (word << 8) | toU64(buf[off + i])
|
|
257
|
+
}
|
|
258
|
+
return word
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** Writes `word` big-endian into `buf[off]` .. `buf[off + 7]`. */
|
|
262
|
+
const storeWord = (buf: u8[], off: i32, word: u64): void => {
|
|
263
|
+
for (let i: i32 = 0; i < 8; i++) {
|
|
264
|
+
buf[off + i] = toU8(word >> toU64((7 - i) * 8))
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* The state both hashes share: the hash value, the partial block, and the
|
|
270
|
+
* message length in bytes. §5.1.2 appends the length in bits as 128 bits; a
|
|
271
|
+
* byte count in a `u64` shifted left by three fills those 128 bits for any
|
|
272
|
+
* message shorter than 2^64 bytes, which is every message there can be.
|
|
273
|
+
*/
|
|
274
|
+
class Sha512Engine {
|
|
275
|
+
state: u64[]
|
|
276
|
+
block: u8[]
|
|
277
|
+
/** The message schedule W_0 .. W_79, kept so a block allocates nothing. */
|
|
278
|
+
schedule: u64[]
|
|
279
|
+
count: u64 = 0
|
|
280
|
+
filled: i32 = 0
|
|
281
|
+
finished: boolean = false
|
|
282
|
+
|
|
283
|
+
constructor(initial: u64[]) {
|
|
284
|
+
this.state = initial
|
|
285
|
+
this.block = new Array<u8>(SHA512_BLOCK)
|
|
286
|
+
this.schedule = new Array<u64>(ROUNDS)
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** One application of §6.4.2 to the block at `src[off]` .. `src[off + 127]`. */
|
|
290
|
+
compress(src: u8[], off: i32): void {
|
|
291
|
+
const w = this.schedule
|
|
292
|
+
const h = this.state
|
|
293
|
+
const wLen: i32 = toI32(w.length)
|
|
294
|
+
for (let t: i32 = 0; t < 16 && t < wLen; t++) {
|
|
295
|
+
w[t] = loadWord(src, off + 8 * t)
|
|
296
|
+
}
|
|
297
|
+
for (let t: i32 = 16; t < wLen; t++) {
|
|
298
|
+
// Named offsets rather than `w[t - 2]`, so the bounds prover sees each index.
|
|
299
|
+
const t2: i32 = t - 2
|
|
300
|
+
const t7: i32 = t - 7
|
|
301
|
+
const t15: i32 = t - 15
|
|
302
|
+
const t16: i32 = t - 16
|
|
303
|
+
w[t] = smallSigma1(w[t2]) + w[t7] + smallSigma0(w[t15]) + w[t16]
|
|
304
|
+
}
|
|
305
|
+
let a = h[0]
|
|
306
|
+
let b = h[1]
|
|
307
|
+
let c = h[2]
|
|
308
|
+
let d = h[3]
|
|
309
|
+
let e = h[4]
|
|
310
|
+
let f = h[5]
|
|
311
|
+
let g = h[6]
|
|
312
|
+
let hh = h[7]
|
|
313
|
+
// §6.4.2 step 4, eight rounds per pass. Rather than shift eight words down
|
|
314
|
+
// each round, the rounds rename them: T1 accumulates in the word that
|
|
315
|
+
// becomes the new `a`, and the word that becomes the new `e` is `d + T1`,
|
|
316
|
+
// so after eight rounds every word is back in its own name. Each index is
|
|
317
|
+
// `u` minus a constant, which the bounds prover can see; `u + 1` it cannot.
|
|
318
|
+
for (let u: i32 = 7; u < ROUNDS && u < wLen; u += 8) {
|
|
319
|
+
const r0: i32 = u - 7
|
|
320
|
+
const r1: i32 = u - 6
|
|
321
|
+
const r2: i32 = u - 5
|
|
322
|
+
const r3: i32 = u - 4
|
|
323
|
+
const r4: i32 = u - 3
|
|
324
|
+
const r5: i32 = u - 2
|
|
325
|
+
const r6: i32 = u - 1
|
|
326
|
+
hh = hh + bigSigma1(e) + ((e & f) ^ (~e & g)) + roundConstant(r0) + w[r0]
|
|
327
|
+
d = d + hh
|
|
328
|
+
hh = hh + bigSigma0(a) + ((a & b) ^ (a & c) ^ (b & c))
|
|
329
|
+
g = g + bigSigma1(d) + ((d & e) ^ (~d & f)) + roundConstant(r1) + w[r1]
|
|
330
|
+
c = c + g
|
|
331
|
+
g = g + bigSigma0(hh) + ((hh & a) ^ (hh & b) ^ (a & b))
|
|
332
|
+
f = f + bigSigma1(c) + ((c & d) ^ (~c & e)) + roundConstant(r2) + w[r2]
|
|
333
|
+
b = b + f
|
|
334
|
+
f = f + bigSigma0(g) + ((g & hh) ^ (g & a) ^ (hh & a))
|
|
335
|
+
e = e + bigSigma1(b) + ((b & c) ^ (~b & d)) + roundConstant(r3) + w[r3]
|
|
336
|
+
a = a + e
|
|
337
|
+
e = e + bigSigma0(f) + ((f & g) ^ (f & hh) ^ (g & hh))
|
|
338
|
+
d = d + bigSigma1(a) + ((a & b) ^ (~a & c)) + roundConstant(r4) + w[r4]
|
|
339
|
+
hh = hh + d
|
|
340
|
+
d = d + bigSigma0(e) + ((e & f) ^ (e & g) ^ (f & g))
|
|
341
|
+
c = c + bigSigma1(hh) + ((hh & a) ^ (~hh & b)) + roundConstant(r5) + w[r5]
|
|
342
|
+
g = g + c
|
|
343
|
+
c = c + bigSigma0(d) + ((d & e) ^ (d & f) ^ (e & f))
|
|
344
|
+
b = b + bigSigma1(g) + ((g & hh) ^ (~g & a)) + roundConstant(r6) + w[r6]
|
|
345
|
+
f = f + b
|
|
346
|
+
b = b + bigSigma0(c) + ((c & d) ^ (c & e) ^ (d & e))
|
|
347
|
+
a = a + bigSigma1(f) + ((f & g) ^ (~f & hh)) + roundConstant(u) + w[u]
|
|
348
|
+
e = e + a
|
|
349
|
+
a = a + bigSigma0(b) + ((b & c) ^ (b & d) ^ (c & d))
|
|
350
|
+
}
|
|
351
|
+
h[0] = h[0] + a
|
|
352
|
+
h[1] = h[1] + b
|
|
353
|
+
h[2] = h[2] + c
|
|
354
|
+
h[3] = h[3] + d
|
|
355
|
+
h[4] = h[4] + e
|
|
356
|
+
h[5] = h[5] + f
|
|
357
|
+
h[6] = h[6] + g
|
|
358
|
+
h[7] = h[7] + hh
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
absorb(data: u8[], off: i32, len: i32): void {
|
|
362
|
+
if (this.finished) {
|
|
363
|
+
panic("sha512: update after digest")
|
|
364
|
+
}
|
|
365
|
+
if (off < 0 || len < 0 || off > toI32(data.length) - len) {
|
|
366
|
+
panic("sha512: the window is outside the buffer")
|
|
367
|
+
}
|
|
368
|
+
this.count = this.count + toU64(len)
|
|
369
|
+
let at = off
|
|
370
|
+
let left = len
|
|
371
|
+
if (this.filled > 0) {
|
|
372
|
+
const room: i32 = SHA512_BLOCK - this.filled
|
|
373
|
+
const take: i32 = left < room ? left : room
|
|
374
|
+
for (let i: i32 = 0; i < take; i++) {
|
|
375
|
+
this.block[this.filled + i] = data[at + i]
|
|
376
|
+
}
|
|
377
|
+
this.filled = this.filled + take
|
|
378
|
+
at = at + take
|
|
379
|
+
left = left - take
|
|
380
|
+
if (this.filled < SHA512_BLOCK) {
|
|
381
|
+
return
|
|
382
|
+
}
|
|
383
|
+
this.compress(this.block, OFFSET_ZERO)
|
|
384
|
+
this.filled = 0
|
|
385
|
+
}
|
|
386
|
+
while (left >= SHA512_BLOCK) {
|
|
387
|
+
this.compress(data, at)
|
|
388
|
+
at = at + SHA512_BLOCK
|
|
389
|
+
left = left - SHA512_BLOCK
|
|
390
|
+
}
|
|
391
|
+
for (let i: i32 = 0; i < left; i++) {
|
|
392
|
+
this.block[i] = data[at + i]
|
|
393
|
+
}
|
|
394
|
+
this.filled = left
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Makes `twin` this engine at the same point. `twin` is a fresh engine of the
|
|
399
|
+
* same hash, so its arrays are reused rather than allocated a second time.
|
|
400
|
+
*/
|
|
401
|
+
copyInto(twin: Sha512Engine): void {
|
|
402
|
+
for (let i: i32 = 0; i < 8; i++) {
|
|
403
|
+
twin.state[i] = this.state[i]
|
|
404
|
+
}
|
|
405
|
+
for (let i: i32 = 0; i < this.filled; i++) {
|
|
406
|
+
twin.block[i] = this.block[i]
|
|
407
|
+
}
|
|
408
|
+
twin.filled = this.filled
|
|
409
|
+
twin.count = this.count
|
|
410
|
+
twin.finished = this.finished
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/** Pads (§5.1.2), compresses what is left, and answers the first `size` bytes of H(N) (§6.4.2, §6.5). */
|
|
414
|
+
finish(size: i32): u8[] {
|
|
415
|
+
if (this.finished) {
|
|
416
|
+
panic("sha512: digest taken twice")
|
|
417
|
+
}
|
|
418
|
+
this.finished = true
|
|
419
|
+
const block = this.block
|
|
420
|
+
const blockLen: i32 = toI32(block.length)
|
|
421
|
+
block[this.filled] = 0x80
|
|
422
|
+
for (let i: i32 = this.filled + 1; i >= 0 && i < blockLen; i++) {
|
|
423
|
+
block[i] = 0
|
|
424
|
+
}
|
|
425
|
+
if (this.filled >= LENGTH_AT) {
|
|
426
|
+
this.compress(block, OFFSET_ZERO)
|
|
427
|
+
for (let i: i32 = 0; i < LENGTH_AT && i < blockLen; i++) {
|
|
428
|
+
block[i] = 0
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
storeWord(block, LENGTH_AT, this.count >> 61)
|
|
432
|
+
storeWord(block, LENGTH_AT + 8, this.count << 3)
|
|
433
|
+
this.compress(block, OFFSET_ZERO)
|
|
434
|
+
// Both sizes are whole words, so the digest is the first `size / 8` of them.
|
|
435
|
+
const out = new Array<u8>(size)
|
|
436
|
+
for (let i: i32 = 0; i < size / 8 && i < 8; i++) {
|
|
437
|
+
storeWord(out, 8 * i, this.state[i])
|
|
438
|
+
}
|
|
439
|
+
return out
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* A streaming SHA-512 hasher. `update` takes a window `(data, off, len)`;
|
|
445
|
+
* `digest` answers a fresh 64-byte array, after which the hasher is spent and
|
|
446
|
+
* another `update` or `digest` panics.
|
|
447
|
+
*/
|
|
448
|
+
export class Sha512 {
|
|
449
|
+
engine: Sha512Engine
|
|
450
|
+
|
|
451
|
+
constructor() {
|
|
452
|
+
this.engine = new Sha512Engine(sha512Initial())
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
update(data: u8[], off: i32, len: i32): void {
|
|
456
|
+
this.engine.absorb(data, off, len)
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/** An independent hasher at the same point: updating either leaves the other alone. */
|
|
460
|
+
copy(): Sha512 {
|
|
461
|
+
const twin = new Sha512()
|
|
462
|
+
this.engine.copyInto(twin.engine)
|
|
463
|
+
return twin
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
digest(): u8[] {
|
|
467
|
+
return this.engine.finish(SHA512_SIZE)
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* A streaming SHA-384 hasher, with `Sha512`'s methods. `digest` answers a
|
|
473
|
+
* fresh 48-byte array.
|
|
474
|
+
*/
|
|
475
|
+
export class Sha384 {
|
|
476
|
+
engine: Sha512Engine
|
|
477
|
+
|
|
478
|
+
constructor() {
|
|
479
|
+
this.engine = new Sha512Engine(sha384Initial())
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
update(data: u8[], off: i32, len: i32): void {
|
|
483
|
+
this.engine.absorb(data, off, len)
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/** An independent hasher at the same point: updating either leaves the other alone. */
|
|
487
|
+
copy(): Sha384 {
|
|
488
|
+
const twin = new Sha384()
|
|
489
|
+
this.engine.copyInto(twin.engine)
|
|
490
|
+
return twin
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
digest(): u8[] {
|
|
494
|
+
return this.engine.finish(SHA384_SIZE)
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/** The SHA-512 digest of all of `data`, as a fresh 64-byte array. */
|
|
499
|
+
export const sha512 = (data: u8[]): u8[] => {
|
|
500
|
+
const hasher = new Sha512()
|
|
501
|
+
hasher.update(data, OFFSET_ZERO, toI32(data.length))
|
|
502
|
+
return hasher.digest()
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/** The SHA-384 digest of all of `data`, as a fresh 48-byte array. */
|
|
506
|
+
export const sha384 = (data: u8[]): u8[] => {
|
|
507
|
+
const hasher = new Sha384()
|
|
508
|
+
hasher.update(data, OFFSET_ZERO, toI32(data.length))
|
|
509
|
+
return hasher.digest()
|
|
510
|
+
}
|