@gcoredev/as-jwt 1.0.0-alpha.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.
- package/LICENSE +201 -0
- package/README.md +85 -0
- package/assembly/index.ts +80 -0
- package/assembly/tsconfig.json +4 -0
- package/assembly/utils.ts +31 -0
- package/modules/as-base64/LICENSE +21 -0
- package/modules/as-base64/README.md +15 -0
- package/modules/as-base64/assembly/index.ts +256 -0
- package/modules/as-base64/assembly/tsconfig.json +6 -0
- package/modules/as-base64/package.json +21 -0
- package/modules/as-hmac-sha2/README.md +40 -0
- package/modules/as-hmac-sha2/assembly/index.ts +5 -0
- package/modules/as-hmac-sha2/assembly/sha256.ts +257 -0
- package/modules/as-hmac-sha2/assembly/sha512.ts +272 -0
- package/modules/as-hmac-sha2/assembly/tsconfig.json +6 -0
- package/modules/as-hmac-sha2/assembly/utils.ts +75 -0
- package/modules/as-hmac-sha2/index.js +5 -0
- package/modules/as-hmac-sha2/package.json +37 -0
- package/package.json +62 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "as-base64",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"types": "assembly/index.ts",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Willem Wyndham <hello@near.org>",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "asp"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"@as-pect/cli": "^6.1.1",
|
|
12
|
+
"assemblyscript": "^0.19.1"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"crypto",
|
|
16
|
+
"AssemblyScript",
|
|
17
|
+
"encoder",
|
|
18
|
+
"decoder",
|
|
19
|
+
"base64"
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# HMAC-SHA-256 and HMAC-SHA-512 for AssemblyScript
|
|
2
|
+
|
|
3
|
+
Self-contained implementations of SHA-256, SHA-512, HMAC-SHA-256 and HMAC-SHA-512 for AssemblyScript.
|
|
4
|
+
|
|
5
|
+
Simple hashing:
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
let msg = Uint8Array.wrap(String.UTF8.encode("test"));
|
|
9
|
+
let h = Sha256.hash(msg);
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Chunked input:
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
let st = new Sha256();
|
|
16
|
+
st.update(msg1);
|
|
17
|
+
st.update(msg2);
|
|
18
|
+
let h = st.final();
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
HMAC:
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
let msg = Uint8Array.wrap(String.UTF8.encode("message"));
|
|
25
|
+
let key = Uint8Array.wrap(String.UTF8.encode("key"));
|
|
26
|
+
let mac = Sha256.hmac(msg, key);
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Constant-time check for equality:
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
let ok = verify(mac, expected_mac);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Constant-time hexadecimal encoding/decoding:
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
let hex = bin2hex(h);
|
|
39
|
+
let bin = hex2bin(hex);
|
|
40
|
+
```
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
type aisize = i32;
|
|
2
|
+
|
|
3
|
+
function setU8(t: Uint8Array, s: Uint8Array, o: isize = 0): void {
|
|
4
|
+
memory.copy(t.dataStart + o, s.dataStart, s.length);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function store64_be(x: Uint8Array, offset: isize, u: u64): void {
|
|
8
|
+
store<u64>(changetype<usize>(x.buffer) + offset, bswap(u));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function load32_be(x: Uint8Array, offset: isize): u32 {
|
|
12
|
+
return bswap(load<u32>(changetype<usize>(x.buffer) + offset));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function store32_be(x: Uint8Array, offset: isize, u: u32): void {
|
|
16
|
+
store<u32>(changetype<usize>(x.buffer) + offset, bswap(u));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
class Internal {
|
|
20
|
+
@inline static Sigma0(x: u32): u32 {
|
|
21
|
+
return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@inline static Sigma1(x: u32): u32 {
|
|
25
|
+
return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@inline static sigma0(x: u32): u32 {
|
|
29
|
+
return rotr(x, 7) ^ rotr(x, 18) ^ (x >> 3);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@inline static sigma1(x: u32): u32 {
|
|
33
|
+
return rotr(x, 17) ^ rotr(x, 19) ^ (x >> 10);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@inline static Ch(x: u32, y: u32, z: u32): u32 {
|
|
37
|
+
return z ^ (x & (y ^ z));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@inline static Maj(x: u32, y: u32, z: u32): u32 {
|
|
41
|
+
return (x & (y ^ z)) ^ (y & z);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static expand(w: StaticArray<u32>): void {
|
|
45
|
+
for (let i = 0; i < 16; i++) {
|
|
46
|
+
unchecked(w[i] += w[(i + 9) & 15] + Internal.sigma1(w[(i + 14) & 15]) + Internal.sigma0(w[(i + 1) & 15]));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static handle(r: StaticArray<u32>, w: StaticArray<u32>, c: u32[]): void {
|
|
51
|
+
for (let i = 0; i < 16; i++) {
|
|
52
|
+
var x = (r[7 & (7 - i)] + w[i] + c[i]);
|
|
53
|
+
x += unchecked(Internal.Sigma1(r[7 & (4 - i)]));
|
|
54
|
+
x += unchecked(Internal.Ch(r[7 & (4 - i)], r[7 & (5 - i)], r[7 & (6 - i)]));
|
|
55
|
+
unchecked(r[7 & (3 - i)] += x);
|
|
56
|
+
x += unchecked(Internal.Sigma0(r[7 & (0 - i)]));
|
|
57
|
+
x += unchecked(Internal.Maj(r[7 & (0 - i)], r[7 & (1 - i)], r[7 & (2 - i)]));
|
|
58
|
+
unchecked(r[7 & (7 - i)] = x);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static K: u32[] = [
|
|
63
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
64
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
65
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
66
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
67
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
68
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
69
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
70
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
static _hashblocks(st: Uint8Array, m: Uint8Array, n_: isize): isize {
|
|
74
|
+
let z = new StaticArray<u32>(8),
|
|
75
|
+
r = new StaticArray<u32>(8),
|
|
76
|
+
w = new StaticArray<u32>(16);
|
|
77
|
+
for (let i = 0; i < 8; ++i) {
|
|
78
|
+
unchecked(z[i] = r[i] = load32_be(st, i << 2));
|
|
79
|
+
}
|
|
80
|
+
let pos = 0, n = n_;
|
|
81
|
+
while (n >= 64) {
|
|
82
|
+
for (let i = 0; i < 16; ++i) {
|
|
83
|
+
w[i] = load32_be(m, (i << 2) + pos);
|
|
84
|
+
}
|
|
85
|
+
Internal.handle(r, w, Internal.K.slice(0));
|
|
86
|
+
Internal.expand(w);
|
|
87
|
+
Internal.handle(r, w, Internal.K.slice(16));
|
|
88
|
+
Internal.expand(w);
|
|
89
|
+
Internal.handle(r, w, Internal.K.slice(32));
|
|
90
|
+
Internal.expand(w);
|
|
91
|
+
Internal.handle(r, w, Internal.K.slice(48));
|
|
92
|
+
for (let i = 0; i < 8; ++i) {
|
|
93
|
+
let x = unchecked(r[i] + z[i]);
|
|
94
|
+
unchecked(z[i] = x);
|
|
95
|
+
unchecked(r[i] = x);
|
|
96
|
+
}
|
|
97
|
+
pos += 64;
|
|
98
|
+
n -= 64;
|
|
99
|
+
}
|
|
100
|
+
for (let i = 0; i < 8; ++i) {
|
|
101
|
+
store32_be(st, i << 2, unchecked(z[i]));
|
|
102
|
+
}
|
|
103
|
+
return n;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static iv: u8[] = [
|
|
107
|
+
0x6a, 0x09, 0xe6, 0x67, 0xbb, 0x67, 0xae, 0x85, 0x3c, 0x6e, 0xf3, 0x72, 0xa5, 0x4f, 0xf5, 0x3a,
|
|
108
|
+
0x51, 0x0e, 0x52, 0x7f, 0x9b, 0x05, 0x68, 0x8c, 0x1f, 0x83, 0xd9, 0xab, 0x5b, 0xe0, 0xcd, 0x19,
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
static _hashInit(): Uint8Array {
|
|
112
|
+
let st = new Uint8Array(32 + 64);
|
|
113
|
+
|
|
114
|
+
for (let i = 0; i < 32; ++i) {
|
|
115
|
+
st[i] = Internal.iv[i];
|
|
116
|
+
}
|
|
117
|
+
return st;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
static _hashUpdate(st: Uint8Array, m: Uint8Array, n: isize, r: isize): isize {
|
|
121
|
+
let obuffered = st.subarray(32);
|
|
122
|
+
let buffered = new Uint8Array(64);
|
|
123
|
+
setU8(buffered, obuffered.subarray(0, 64));
|
|
124
|
+
|
|
125
|
+
let still_available_in_buffer = <isize>64 - r;
|
|
126
|
+
let copiable_to_buffer = min(n, still_available_in_buffer);
|
|
127
|
+
setU8(buffered, m.subarray(0, <aisize>copiable_to_buffer), r);
|
|
128
|
+
r += copiable_to_buffer;
|
|
129
|
+
n -= copiable_to_buffer;
|
|
130
|
+
let pos: isize = 0;
|
|
131
|
+
if (r === 64) {
|
|
132
|
+
Internal._hashblocks(st, buffered, 64);
|
|
133
|
+
r = 0;
|
|
134
|
+
pos = copiable_to_buffer;
|
|
135
|
+
}
|
|
136
|
+
if (n == 0) {
|
|
137
|
+
setU8(obuffered, buffered);
|
|
138
|
+
return r;
|
|
139
|
+
}
|
|
140
|
+
let left = m.subarray(<aisize>pos);
|
|
141
|
+
r = Internal._hashblocks(st, left, left.length);
|
|
142
|
+
if (r > 0) {
|
|
143
|
+
setU8(obuffered, left.subarray(left.length - <aisize>r));
|
|
144
|
+
}
|
|
145
|
+
return r;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
static _hashFinal(st: Uint8Array, out: Uint8Array, t: isize, r: isize): void {
|
|
149
|
+
let buffered = st.subarray(32);
|
|
150
|
+
let padded = new Uint8Array(128);
|
|
151
|
+
setU8(padded, buffered.subarray(0, <aisize>r));
|
|
152
|
+
padded[<aisize>r] = 0x80;
|
|
153
|
+
if (r < 56) {
|
|
154
|
+
store64_be(padded, 64 - 8, t << 3);
|
|
155
|
+
Internal._hashblocks(st, padded, 64);
|
|
156
|
+
} else {
|
|
157
|
+
store64_be(padded, 128 - 8, t << 3);
|
|
158
|
+
Internal._hashblocks(st, padded, 128);
|
|
159
|
+
}
|
|
160
|
+
for (let i = 0; i < 32; ++i) {
|
|
161
|
+
out[i] = st[i];
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
static _hash(out: Uint8Array, m: Uint8Array, n: isize): void {
|
|
166
|
+
let st = Internal._hashInit();
|
|
167
|
+
let r = Internal._hashUpdate(st, m, n, 0);
|
|
168
|
+
|
|
169
|
+
Internal._hashFinal(st, out, n, r);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
static _hmac(m: Uint8Array, k: Uint8Array): Uint8Array {
|
|
173
|
+
if (k.length > 64) {
|
|
174
|
+
k = Sha256.hash(k);
|
|
175
|
+
}
|
|
176
|
+
let b = new Uint8Array(64);
|
|
177
|
+
setU8(b, k);
|
|
178
|
+
for (let i = 0; i < b.length; ++i) {
|
|
179
|
+
b[i] ^= 0x36;
|
|
180
|
+
}
|
|
181
|
+
let out = new Uint8Array(32);
|
|
182
|
+
let st = Internal._hashInit();
|
|
183
|
+
let r = Internal._hashUpdate(st, b, b.length, 0);
|
|
184
|
+
r = Internal._hashUpdate(st, m, m.length, r);
|
|
185
|
+
Internal._hashFinal(st, out, b.length + m.length, r);
|
|
186
|
+
for (let i = 0; i < b.length; ++i) {
|
|
187
|
+
b[i] ^= 0x6a;
|
|
188
|
+
}
|
|
189
|
+
st = Internal._hashInit();
|
|
190
|
+
r = Internal._hashUpdate(st, b, b.length, 0);
|
|
191
|
+
r = Internal._hashUpdate(st, out, out.length, r);
|
|
192
|
+
Internal._hashFinal(st, out, b.length + out.length, r);
|
|
193
|
+
return out;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Hash function output size, in bytes
|
|
199
|
+
*/
|
|
200
|
+
export const SHA256_HASH_BYTES: isize = 32;
|
|
201
|
+
|
|
202
|
+
export class Sha256 {
|
|
203
|
+
r: u64 = 0;
|
|
204
|
+
t: u64 = 0;
|
|
205
|
+
st: Uint8Array;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Initialize a multipart hash computation
|
|
209
|
+
* @returns A hash function state
|
|
210
|
+
*/
|
|
211
|
+
constructor() {
|
|
212
|
+
let st = Internal._hashInit();
|
|
213
|
+
this.st = st;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Absorb data to be hashed
|
|
218
|
+
* @param m (partial) message
|
|
219
|
+
*/
|
|
220
|
+
update(m: Uint8Array): void {
|
|
221
|
+
let n = m.length;
|
|
222
|
+
this.t += n;
|
|
223
|
+
this.r = Internal._hashUpdate(this.st, m, n, this.r as isize);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Finalize a hash computation
|
|
228
|
+
* @returns Hash
|
|
229
|
+
*/
|
|
230
|
+
final(): Uint8Array {
|
|
231
|
+
let h = new Uint8Array(<aisize>SHA256_HASH_BYTES);
|
|
232
|
+
Internal._hashFinal(this.st, h, this.t as isize, this.r as isize);
|
|
233
|
+
return h;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Compute a hash for a single-part message
|
|
238
|
+
* @param m Message
|
|
239
|
+
* @returns Hash
|
|
240
|
+
*/
|
|
241
|
+
static hash(m: Uint8Array): Uint8Array {
|
|
242
|
+
let h = new Uint8Array(<aisize>SHA256_HASH_BYTES);
|
|
243
|
+
Internal._hash(h, m, m.length);
|
|
244
|
+
return h;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* HMAC-SHA-256
|
|
249
|
+
* @param m Message
|
|
250
|
+
* @param k Key
|
|
251
|
+
* @returns `HMAC-SHA-256(m, k)`
|
|
252
|
+
*/
|
|
253
|
+
static hmac(m: Uint8Array, k: Uint8Array): Uint8Array {
|
|
254
|
+
return Internal._hmac(m, k);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
type aisize = i32;
|
|
2
|
+
|
|
3
|
+
function setU8(t: Uint8Array, s: Uint8Array, o: isize = 0): void {
|
|
4
|
+
memory.copy(t.dataStart + o, s.dataStart, s.length);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function load64_be(x: Uint8Array, offset: isize): u64 {
|
|
8
|
+
return bswap(load<u64>(changetype<usize>(x.buffer) + offset));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function store64_be(x: Uint8Array, offset: isize, u: u64): void {
|
|
12
|
+
store<u64>(changetype<usize>(x.buffer) + offset, bswap(u));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
class Internal {
|
|
16
|
+
@inline static Sigma0(x: u64): u64 {
|
|
17
|
+
return rotr(x, 28) ^ rotr(x, 34) ^ rotr(x, 39);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@inline static Sigma1(x: u64): u64 {
|
|
21
|
+
return rotr(x, 14) ^ rotr(x, 18) ^ rotr(x, 41);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@inline static sigma0(x: u64): u64 {
|
|
25
|
+
return rotr(x, 1) ^ rotr(x, 8) ^ (x >> 7);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@inline static sigma1(x: u64): u64 {
|
|
29
|
+
return rotr(x, 19) ^ rotr(x, 61) ^ (x >> 6);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@inline static Ch(x: u64, y: u64, z: u64): u64 {
|
|
33
|
+
return z ^ (x & (y ^ z));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@inline static Maj(x: u64, y: u64, z: u64): u64 {
|
|
37
|
+
return (x & (y ^ z)) ^ (y & z);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static expand(w: StaticArray<u64>): void {
|
|
41
|
+
for (let i = 0; i < 16; i++) {
|
|
42
|
+
unchecked(w[i] += w[(i + 9) & 15] + Internal.sigma1(w[(i + 14) & 15]) + Internal.sigma0(w[(i + 1) & 15]));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static handle(r: StaticArray<u64>, w: StaticArray<u64>, c: u64[]): void {
|
|
47
|
+
for (let i = 0; i < 16; i++) {
|
|
48
|
+
var x = unchecked(r[7 & (7 - i)] + w[i] + c[i]);
|
|
49
|
+
x += unchecked(Internal.Sigma1(r[7 & (4 - i)]));
|
|
50
|
+
x += unchecked(Internal.Ch(r[7 & (4 - i)], r[7 & (5 - i)], r[7 & (6 - i)]));
|
|
51
|
+
unchecked(r[7 & (3 - i)] += x);
|
|
52
|
+
x += unchecked(Internal.Sigma0(r[7 & (0 - i)]));
|
|
53
|
+
x += unchecked(Internal.Maj(r[7 & (0 - i)], r[7 & (1 - i)], r[7 & (2 - i)]));
|
|
54
|
+
unchecked(r[7 & (7 - i)] = x);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
static K: u64[] = [
|
|
59
|
+
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
|
|
60
|
+
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
|
|
61
|
+
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
|
|
62
|
+
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
|
|
63
|
+
0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
|
|
64
|
+
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
|
|
65
|
+
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
|
|
66
|
+
0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
|
|
67
|
+
0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
|
|
68
|
+
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
|
|
69
|
+
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
|
|
70
|
+
0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
|
|
71
|
+
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
|
|
72
|
+
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
|
|
73
|
+
0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
|
|
74
|
+
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
|
|
75
|
+
0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
|
|
76
|
+
0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
|
|
77
|
+
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
|
|
78
|
+
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
static _hashblocks(st: Uint8Array, m: Uint8Array, n_: isize): isize {
|
|
82
|
+
let z = new StaticArray<u64>(8),
|
|
83
|
+
r = new StaticArray<u64>(8),
|
|
84
|
+
w = new StaticArray<u64>(16);
|
|
85
|
+
for (let i = 0; i < 8; ++i) {
|
|
86
|
+
z[i] = load64_be(st, i << 3);
|
|
87
|
+
r[i] = z[i];
|
|
88
|
+
}
|
|
89
|
+
let pos = 0, n = n_;
|
|
90
|
+
while (n >= 128) {
|
|
91
|
+
for (let i = 0; i < 16; ++i) {
|
|
92
|
+
w[i] = load64_be(m, (i << 3) + pos);
|
|
93
|
+
}
|
|
94
|
+
Internal.handle(r, w, Internal.K.slice(0));
|
|
95
|
+
Internal.expand(w);
|
|
96
|
+
Internal.handle(r, w, Internal.K.slice(16));
|
|
97
|
+
Internal.expand(w);
|
|
98
|
+
Internal.handle(r, w, Internal.K.slice(32));
|
|
99
|
+
Internal.expand(w);
|
|
100
|
+
Internal.handle(r, w, Internal.K.slice(48));
|
|
101
|
+
Internal.expand(w);
|
|
102
|
+
Internal.handle(r, w, Internal.K.slice(64));
|
|
103
|
+
for (let i = 0; i < 8; ++i) {
|
|
104
|
+
let x = r[i] + z[i];
|
|
105
|
+
z[i] = x;
|
|
106
|
+
r[i] = x;
|
|
107
|
+
}
|
|
108
|
+
pos += 128;
|
|
109
|
+
n -= 128;
|
|
110
|
+
}
|
|
111
|
+
for (let i = 0; i < 8; ++i) {
|
|
112
|
+
store64_be(st, i << 3, z[i]);
|
|
113
|
+
}
|
|
114
|
+
return n;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
static iv: u8[] = [
|
|
118
|
+
0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08, 0xbb, 0x67, 0xae, 0x85, 0x84, 0xca, 0xa7, 0x3b,
|
|
119
|
+
0x3c, 0x6e, 0xf3, 0x72, 0xfe, 0x94, 0xf8, 0x2b, 0xa5, 0x4f, 0xf5, 0x3a, 0x5f, 0x1d, 0x36, 0xf1,
|
|
120
|
+
0x51, 0x0e, 0x52, 0x7f, 0xad, 0xe6, 0x82, 0xd1, 0x9b, 0x05, 0x68, 0x8c, 0x2b, 0x3e, 0x6c, 0x1f,
|
|
121
|
+
0x1f, 0x83, 0xd9, 0xab, 0xfb, 0x41, 0xbd, 0x6b, 0x5b, 0xe0, 0xcd, 0x19, 0x13, 0x7e, 0x21, 0x79,
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
static _hashInit(): Uint8Array {
|
|
125
|
+
let st = new Uint8Array(64 + 128);
|
|
126
|
+
|
|
127
|
+
for (let i = 0; i < 64; ++i) {
|
|
128
|
+
st[i] = Internal.iv[i];
|
|
129
|
+
}
|
|
130
|
+
return st;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
static _hashUpdate(st: Uint8Array, m: Uint8Array, n: isize, r: isize): isize {
|
|
134
|
+
let obuffered = st.subarray(64);
|
|
135
|
+
let buffered = new Uint8Array(128);
|
|
136
|
+
setU8(buffered, obuffered.subarray(0, 128)); // extra copy work around compiler bugs
|
|
137
|
+
|
|
138
|
+
let still_available_in_buffer = <isize>128 - r;
|
|
139
|
+
let copiable_to_buffer = min(n, still_available_in_buffer);
|
|
140
|
+
setU8(buffered, m.subarray(0, <aisize>copiable_to_buffer), r);
|
|
141
|
+
r += copiable_to_buffer;
|
|
142
|
+
n -= copiable_to_buffer;
|
|
143
|
+
let pos: isize = 0;
|
|
144
|
+
if (r === 128) {
|
|
145
|
+
Internal._hashblocks(st, buffered, 128);
|
|
146
|
+
r = 0;
|
|
147
|
+
pos = copiable_to_buffer;
|
|
148
|
+
}
|
|
149
|
+
if (n == 0) {
|
|
150
|
+
setU8(obuffered, buffered);
|
|
151
|
+
return r;
|
|
152
|
+
}
|
|
153
|
+
let left = m.subarray(<aisize>pos);
|
|
154
|
+
r = Internal._hashblocks(st, left, left.length);
|
|
155
|
+
if (r > 0) {
|
|
156
|
+
setU8(obuffered, left.subarray(left.length - <aisize>r));
|
|
157
|
+
}
|
|
158
|
+
return r;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
static _hashFinal(st: Uint8Array, out: Uint8Array, t: isize, r: isize): void {
|
|
162
|
+
let buffered = st.subarray(64);
|
|
163
|
+
let padded = new Uint8Array(256);
|
|
164
|
+
setU8(padded, buffered.subarray(0, <aisize>r));
|
|
165
|
+
padded[<aisize>r] = 0x80;
|
|
166
|
+
if (r < 112) {
|
|
167
|
+
store64_be(padded, 128 - 8, t << 3);
|
|
168
|
+
Internal._hashblocks(st, padded, 128);
|
|
169
|
+
} else {
|
|
170
|
+
store64_be(padded, 256 - 8, t << 3);
|
|
171
|
+
Internal._hashblocks(st, padded, 256);
|
|
172
|
+
}
|
|
173
|
+
for (let i = 0; i < 64; ++i) {
|
|
174
|
+
out[i] = st[i];
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
static _hash(out: Uint8Array, m: Uint8Array, n: isize): void {
|
|
179
|
+
let st = Internal._hashInit();
|
|
180
|
+
let r = Internal._hashUpdate(st, m, n, 0);
|
|
181
|
+
Internal._hashFinal(st, out, n, r);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// HMAC
|
|
185
|
+
|
|
186
|
+
static _hmac(m: Uint8Array, k: Uint8Array): Uint8Array {
|
|
187
|
+
if (k.length > 128) {
|
|
188
|
+
k = Sha512.hash(k);
|
|
189
|
+
}
|
|
190
|
+
let b = new Uint8Array(128);
|
|
191
|
+
setU8(b, k);
|
|
192
|
+
for (let i = 0; i < b.length; ++i) {
|
|
193
|
+
b[i] ^= 0x36;
|
|
194
|
+
}
|
|
195
|
+
let out = new Uint8Array(64);
|
|
196
|
+
let st = Internal._hashInit();
|
|
197
|
+
let r = Internal._hashUpdate(st, b, b.length, 0);
|
|
198
|
+
r = Internal._hashUpdate(st, m, m.length, r);
|
|
199
|
+
Internal._hashFinal(st, out, b.length + m.length, r);
|
|
200
|
+
for (let i = 0; i < b.length; ++i) {
|
|
201
|
+
b[i] ^= 0x6a;
|
|
202
|
+
}
|
|
203
|
+
st = Internal._hashInit();
|
|
204
|
+
r = Internal._hashUpdate(st, b, b.length, 0);
|
|
205
|
+
r = Internal._hashUpdate(st, out, out.length, r);
|
|
206
|
+
Internal._hashFinal(st, out, b.length + out.length, r);
|
|
207
|
+
return out;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Hash function output size, in bytes
|
|
214
|
+
*/
|
|
215
|
+
export const SHA512_HASH_BYTES: isize = 64;
|
|
216
|
+
|
|
217
|
+
export class Sha512 {
|
|
218
|
+
r: u64 = 0;
|
|
219
|
+
t: u64 = 0;
|
|
220
|
+
st: Uint8Array;
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Initialize a multipart hash computation
|
|
224
|
+
* @returns A hash function state
|
|
225
|
+
*/
|
|
226
|
+
constructor() {
|
|
227
|
+
let st = Internal._hashInit();
|
|
228
|
+
this.st = st;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Absorb data to be hashed
|
|
233
|
+
* @param m (partial) message
|
|
234
|
+
*/
|
|
235
|
+
update(m: Uint8Array): void {
|
|
236
|
+
let n = m.length;
|
|
237
|
+
this.t += n;
|
|
238
|
+
this.r = Internal._hashUpdate(this.st, m, n, this.r as isize);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Finalize a hash computation
|
|
243
|
+
* @returns Hash
|
|
244
|
+
*/
|
|
245
|
+
final(): Uint8Array {
|
|
246
|
+
let h = new Uint8Array(<aisize>SHA512_HASH_BYTES);
|
|
247
|
+
Internal._hashFinal(this.st, h, this.t as isize, this.r as isize);
|
|
248
|
+
return h;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Compute a hash for a single-part message
|
|
253
|
+
* @param m Message
|
|
254
|
+
* @returns Hash
|
|
255
|
+
*/
|
|
256
|
+
static hash(m: Uint8Array): Uint8Array {
|
|
257
|
+
let h = new Uint8Array(<aisize>SHA512_HASH_BYTES);
|
|
258
|
+
Internal._hash(h, m, m.length);
|
|
259
|
+
return h;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* HMAC-SHA-512
|
|
264
|
+
* @param m Message
|
|
265
|
+
* @param k Key
|
|
266
|
+
* @returns `HMAC-SHA-512(m, k)`
|
|
267
|
+
*/
|
|
268
|
+
static hmac(m: Uint8Array, k: Uint8Array): Uint8Array {
|
|
269
|
+
return Internal._hmac(m, k);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
type aisize = i32;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* (best-effort) Constant-time hexadecimal encoding
|
|
5
|
+
* @param bin Binary data
|
|
6
|
+
* @returns Hex-encoded representation
|
|
7
|
+
*/
|
|
8
|
+
export function bin2hex(bin: Uint8Array): string {
|
|
9
|
+
let bin_len = bin.length;
|
|
10
|
+
let hex = "";
|
|
11
|
+
for (let i = 0; i < bin_len; i++) {
|
|
12
|
+
let bin_i = bin[i] as u32;
|
|
13
|
+
let c = bin_i & 0xf;
|
|
14
|
+
let b = bin_i >> 4;
|
|
15
|
+
let x: u32 = ((87 + c + (((c - 10) >> 8) & ~38)) << 8) |
|
|
16
|
+
(87 + b + (((b - 10) >> 8) & ~38));
|
|
17
|
+
hex += String.fromCharCode(x as u8);
|
|
18
|
+
x >>= 8;
|
|
19
|
+
hex += String.fromCharCode(x as u8);
|
|
20
|
+
}
|
|
21
|
+
return hex;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* (best-effort) Constant-time hexadecimal decoding
|
|
26
|
+
* @param hex Hex-encoded data
|
|
27
|
+
* @returns Raw binary representation
|
|
28
|
+
*/
|
|
29
|
+
function hex2bin(hex: string): Uint8Array | null {
|
|
30
|
+
let hex_len = hex.length;
|
|
31
|
+
if ((hex_len & 1) !== 0) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
let bin = new Uint8Array(<aisize>(hex_len / 2));
|
|
35
|
+
let c_acc = 0;
|
|
36
|
+
let bin_pos = 0;
|
|
37
|
+
let state = false;
|
|
38
|
+
for (let hex_pos = 0; hex_pos < hex_len; hex_pos++) {
|
|
39
|
+
let c = hex.charCodeAt(hex_pos) as u32;
|
|
40
|
+
let c_num = c ^ 48;
|
|
41
|
+
let c_num0 = (c_num - 10) >> 8;
|
|
42
|
+
let c_alpha = (c & ~32) - 55;
|
|
43
|
+
let c_alpha0 = ((c_alpha - 10) ^ (c_alpha - 16)) >> 8;
|
|
44
|
+
if ((c_num0 | c_alpha0) === 0) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
let c_val = ((c_num0 & c_num) | (c_alpha0 & c_alpha)) as u8;
|
|
48
|
+
if (state === false) {
|
|
49
|
+
c_acc = c_val << 4;
|
|
50
|
+
} else {
|
|
51
|
+
bin[bin_pos++] = c_acc | c_val;
|
|
52
|
+
}
|
|
53
|
+
state = !state;
|
|
54
|
+
}
|
|
55
|
+
return bin;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* (best-effort) Constant-time verification that x == y
|
|
61
|
+
* @param x array 1
|
|
62
|
+
* @param y array 2
|
|
63
|
+
* @returns true if both arrays contain the same data
|
|
64
|
+
*/
|
|
65
|
+
export function verify(x: Uint8Array, y: Uint8Array): bool {
|
|
66
|
+
let d: u8 = 0;
|
|
67
|
+
|
|
68
|
+
if (x.length != y.length) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
for (let i = 0; i < x.length; ++i) {
|
|
72
|
+
d |= x[i] ^ y[i];
|
|
73
|
+
}
|
|
74
|
+
return d === 0;
|
|
75
|
+
}
|