@secrecy/lib 1.86.2 → 1.86.4-fix-md5.1
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/dist/lib/base-client.js +6 -5
- package/dist/lib/cache.js +14 -5
- package/dist/lib/client/SecrecyCloudClient.js +4 -2
- package/dist/lib/client/SecrecyMailClient.js +12 -5
- package/dist/lib/client/data-link.js +6 -12
- package/dist/lib/client/helpers.js +21 -1
- package/dist/lib/client/index.js +6 -8
- package/dist/lib/client/upload.js +12 -14
- package/dist/lib/client.js +6 -10
- package/dist/lib/crypto/data.js +146 -91
- package/dist/lib/crypto/domain.js +1 -3
- package/dist/lib/crypto/helpers.js +23 -1
- package/dist/lib/crypto/index.js +2 -2
- package/dist/lib/error/client.js +7 -1
- package/dist/lib/react/index.js +69 -0
- package/dist/lib/transformer.js +3 -2
- package/dist/lib/utils/popup-tools.js +31 -13
- package/dist/lib/versioning.js +1 -1
- package/dist/lib/worker/generated/md5.js +2 -0
- package/dist/lib/worker/generated/sodium.js +2 -0
- package/dist/lib/worker/md5.js +2 -2
- package/dist/lib/worker/sodium.js +17 -15
- package/dist/types/base-client.d.ts +2 -0
- package/dist/types/cache.d.ts +7 -6
- package/dist/types/client/SecrecyMailClient.d.ts +23 -1
- package/dist/types/client/data-link.d.ts +4 -4
- package/dist/types/client/helpers.d.ts +12 -0
- package/dist/types/client/index.d.ts +4 -2
- package/dist/types/client/types/data.d.ts +2 -1
- package/dist/types/client.d.ts +67 -74
- package/dist/types/crypto/data.d.ts +11 -1
- package/dist/types/crypto/domain.d.ts +0 -1
- package/dist/types/crypto/helpers.d.ts +7 -0
- package/dist/types/crypto/index.d.ts +3 -3
- package/dist/types/error/client.d.ts +8 -0
- package/dist/types/error/index.d.ts +4 -0
- package/dist/types/react/index.d.ts +20 -0
- package/dist/types/sodium.d.ts +5 -0
- package/dist/types/utils/popup-tools.d.ts +4 -2
- package/dist/types/versioning.d.ts +1 -1
- package/dist/types/worker/generated/md5.d.ts +1 -0
- package/dist/types/worker/generated/sodium.d.ts +1 -0
- package/package.json +37 -13
- package/dist/lib/client/SecrecyDbClient.js +0 -3
- package/dist/lib/worker/workerCodes.js +0 -254
- package/dist/types/client/SecrecyDbClient.d.ts +0 -4
- package/dist/types/worker/workerCodes.d.ts +0 -2
package/dist/lib/crypto/data.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { setup, sodium } from '../sodium.js';
|
|
2
2
|
import SparkMD5 from 'spark-md5';
|
|
3
|
-
import { chunks } from '../utils/array.js';
|
|
4
3
|
function assert(c, message) {
|
|
5
4
|
if (!c) {
|
|
6
5
|
throw new Error(message);
|
|
@@ -9,7 +8,19 @@ function assert(c, message) {
|
|
|
9
8
|
export function secretStreamKeygen() {
|
|
10
9
|
return sodium.crypto_secretstream_xchacha20poly1305_keygen();
|
|
11
10
|
}
|
|
11
|
+
function assertKey(key) {
|
|
12
|
+
assert(key.byteLength === sodium.crypto_secretstream_xchacha20poly1305_KEYBYTES, `key must be KEYBYTES (${sodium.crypto_secretstream_xchacha20poly1305_KEYBYTES}) long`);
|
|
13
|
+
}
|
|
14
|
+
// The wrappers return the secretstream state as a raw address in the wasm
|
|
15
|
+
// heap and never release it: wipe it (it holds the stream key) and free it.
|
|
16
|
+
function wipeState(state) {
|
|
17
|
+
const lib = sodium.libsodium;
|
|
18
|
+
const size = lib._crypto_secretstream_xchacha20poly1305_statebytes();
|
|
19
|
+
lib.HEAPU8.fill(0, state, state + size);
|
|
20
|
+
lib._free(state);
|
|
21
|
+
}
|
|
12
22
|
function encrypt(key) {
|
|
23
|
+
assertKey(key);
|
|
13
24
|
let destroyed = false;
|
|
14
25
|
const { state, header } = sodium.crypto_secretstream_xchacha20poly1305_init_push(key);
|
|
15
26
|
const encrypt = (tag, plaintext) => {
|
|
@@ -19,6 +30,7 @@ function encrypt(key) {
|
|
|
19
30
|
function destroy() {
|
|
20
31
|
assert(!destroyed, 'state already destroyed');
|
|
21
32
|
destroyed = true;
|
|
33
|
+
wipeState(state);
|
|
22
34
|
}
|
|
23
35
|
return {
|
|
24
36
|
encrypt,
|
|
@@ -27,18 +39,19 @@ function encrypt(key) {
|
|
|
27
39
|
};
|
|
28
40
|
}
|
|
29
41
|
function decrypt(header, key) {
|
|
30
|
-
assert(header.byteLength
|
|
31
|
-
sodium.crypto_secretstream_xchacha20poly1305_HEADERBYTES, `header must be
|
|
32
|
-
|
|
42
|
+
assert(header.byteLength ===
|
|
43
|
+
sodium.crypto_secretstream_xchacha20poly1305_HEADERBYTES, `header must be HEADERBYTES (${sodium.crypto_secretstream_xchacha20poly1305_HEADERBYTES}) long`);
|
|
44
|
+
assertKey(key);
|
|
33
45
|
let destroyed = false;
|
|
34
46
|
const state = sodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key);
|
|
35
47
|
const decrypt = (ciphertext) => {
|
|
36
48
|
assert(!destroyed, 'state already destroyed');
|
|
37
|
-
return sodium.crypto_secretstream_xchacha20poly1305_pull(state, ciphertext);
|
|
49
|
+
return sodium.crypto_secretstream_xchacha20poly1305_pull(state, ciphertext, null);
|
|
38
50
|
};
|
|
39
51
|
function destroy() {
|
|
40
52
|
assert(!destroyed, 'state already destroyed');
|
|
41
53
|
destroyed = true;
|
|
54
|
+
wipeState(state);
|
|
42
55
|
}
|
|
43
56
|
return {
|
|
44
57
|
decrypt,
|
|
@@ -46,104 +59,146 @@ function decrypt(header, key) {
|
|
|
46
59
|
};
|
|
47
60
|
}
|
|
48
61
|
export const CHUNK_SIZE = 8192;
|
|
62
|
+
/**
|
|
63
|
+
* Encrypt `data` as a secretstream: the header followed by one authenticated
|
|
64
|
+
* chunk per CHUNK_SIZE bytes of plaintext. The last chunk (an empty one for
|
|
65
|
+
* empty data) is always tagged `TAG_FINAL` so that truncation is detected.
|
|
66
|
+
*/
|
|
49
67
|
export async function encryptSecretStream(key, data, progress, signal) {
|
|
50
68
|
await setup();
|
|
51
69
|
const { encrypt: crypt, destroy, header } = encrypt(key);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
70
|
+
try {
|
|
71
|
+
const chunkCount = Math.max(1, Math.ceil(data.byteLength / CHUNK_SIZE));
|
|
72
|
+
const max = header.byteLength +
|
|
73
|
+
data.byteLength +
|
|
74
|
+
chunkCount * sodium.crypto_secretstream_xchacha20poly1305_ABYTES;
|
|
75
|
+
void progress?.({
|
|
76
|
+
percent: 0,
|
|
77
|
+
total: max,
|
|
78
|
+
current: 0,
|
|
79
|
+
});
|
|
80
|
+
const final = new Uint8Array(max);
|
|
81
|
+
const sparkEncrypted = new SparkMD5.ArrayBuffer();
|
|
82
|
+
final.set(header);
|
|
83
|
+
sparkEncrypted.append(header.buffer);
|
|
84
|
+
let total = header.byteLength;
|
|
85
|
+
void progress?.({
|
|
86
|
+
percent: total / max,
|
|
87
|
+
total: max,
|
|
88
|
+
current: total,
|
|
89
|
+
});
|
|
90
|
+
let lastPercent = total / max;
|
|
91
|
+
for (let i = 0; i < chunkCount; i++) {
|
|
92
|
+
if (signal?.aborted === true) {
|
|
93
|
+
throw new Error(`Encrypt aborted`);
|
|
94
|
+
}
|
|
95
|
+
const chunk = data.subarray(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE);
|
|
96
|
+
const tag = i === chunkCount - 1
|
|
97
|
+
? sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL
|
|
98
|
+
: sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE;
|
|
99
|
+
const encrypted = crypt(tag, chunk);
|
|
100
|
+
sparkEncrypted.append(encrypted.buffer);
|
|
101
|
+
final.set(encrypted, total);
|
|
102
|
+
total += encrypted.byteLength;
|
|
103
|
+
const percent = total / max;
|
|
104
|
+
if (percent > lastPercent + 0.01) {
|
|
105
|
+
void progress?.({
|
|
106
|
+
percent,
|
|
107
|
+
total: max,
|
|
108
|
+
current: total,
|
|
109
|
+
});
|
|
110
|
+
lastPercent = percent;
|
|
111
|
+
}
|
|
91
112
|
}
|
|
113
|
+
void progress?.({
|
|
114
|
+
percent: 1,
|
|
115
|
+
total,
|
|
116
|
+
current: total,
|
|
117
|
+
});
|
|
118
|
+
return {
|
|
119
|
+
data: final,
|
|
120
|
+
md5Encrypted: sparkEncrypted.end(),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
destroy();
|
|
92
125
|
}
|
|
93
|
-
destroy();
|
|
94
|
-
void progress?.({
|
|
95
|
-
percent: 1,
|
|
96
|
-
total,
|
|
97
|
-
current: total,
|
|
98
|
-
});
|
|
99
|
-
return {
|
|
100
|
-
data: final.slice(0, total),
|
|
101
|
-
md5Encrypted: sparkEncrypted.end(),
|
|
102
|
-
md5: spark.end(),
|
|
103
|
-
};
|
|
104
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Decrypt a secretstream produced by `encryptSecretStream`. Throws if any
|
|
129
|
+
* chunk fails authentication, if data follows the `TAG_FINAL` chunk, or if the
|
|
130
|
+
* stream ends without it (truncation).
|
|
131
|
+
*/
|
|
105
132
|
export async function decryptSecretStream(key, data, progress, signal) {
|
|
106
133
|
await setup();
|
|
107
|
-
const
|
|
108
|
-
data = data.slice(sodium.crypto_secretstream_xchacha20poly1305_HEADERBYTES);
|
|
109
|
-
const { decrypt: decryptFn, destroy } = decrypt(header, key);
|
|
134
|
+
const headerBytes = sodium.crypto_secretstream_xchacha20poly1305_HEADERBYTES;
|
|
110
135
|
const chunkSize = CHUNK_SIZE + sodium.crypto_secretstream_xchacha20poly1305_ABYTES;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
136
|
+
// A valid stream always holds at least one (possibly empty) chunk.
|
|
137
|
+
if (data.byteLength <
|
|
138
|
+
headerBytes + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) {
|
|
139
|
+
throw new Error('Unable to decrypt the data: the data is too short!');
|
|
140
|
+
}
|
|
141
|
+
const header = data.slice(0, headerBytes);
|
|
142
|
+
const body = data.subarray(headerBytes);
|
|
143
|
+
const chunkCount = Math.ceil(body.byteLength / chunkSize);
|
|
144
|
+
const max = body.byteLength -
|
|
145
|
+
chunkCount * sodium.crypto_secretstream_xchacha20poly1305_ABYTES;
|
|
146
|
+
const { decrypt: decryptFn, destroy } = decrypt(header, key);
|
|
147
|
+
try {
|
|
148
|
+
void progress?.({
|
|
149
|
+
percent: 0,
|
|
150
|
+
total: max,
|
|
151
|
+
current: 0,
|
|
152
|
+
});
|
|
153
|
+
const final = new Uint8Array(max);
|
|
154
|
+
let total = 0;
|
|
155
|
+
let finalTagSeen = false;
|
|
156
|
+
let lastPercent = total / max;
|
|
157
|
+
for (let i = 0; i < chunkCount; i++) {
|
|
158
|
+
if (signal?.aborted === true) {
|
|
159
|
+
throw new Error(`Decrypt aborted`);
|
|
160
|
+
}
|
|
161
|
+
const chunk = body.subarray(i * chunkSize, (i + 1) * chunkSize);
|
|
162
|
+
if (finalTagSeen) {
|
|
163
|
+
throw new Error('Unable to decrypt the data: unexpected data after the final chunk!');
|
|
164
|
+
}
|
|
165
|
+
const messageTag = decryptFn(chunk);
|
|
166
|
+
if (typeof messageTag === 'boolean') {
|
|
167
|
+
throw new Error('Unable to decrypt the data!');
|
|
168
|
+
}
|
|
169
|
+
if (messageTag.tag ===
|
|
170
|
+
sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL) {
|
|
171
|
+
finalTagSeen = true;
|
|
172
|
+
}
|
|
173
|
+
else if (messageTag.tag !==
|
|
174
|
+
sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE) {
|
|
175
|
+
throw new Error('Unable to decrypt the data: unexpected chunk tag!');
|
|
176
|
+
}
|
|
177
|
+
final.set(messageTag.message, total);
|
|
178
|
+
total += messageTag.message.byteLength;
|
|
179
|
+
const percent = total / max;
|
|
180
|
+
if (percent > lastPercent + 0.01) {
|
|
181
|
+
void progress?.({
|
|
182
|
+
percent,
|
|
183
|
+
total: max,
|
|
184
|
+
current: total,
|
|
185
|
+
});
|
|
186
|
+
lastPercent = percent;
|
|
187
|
+
}
|
|
127
188
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const percent = total / max;
|
|
131
|
-
if (percent > lastPercent + 0.01) {
|
|
132
|
-
void progress?.({
|
|
133
|
-
percent,
|
|
134
|
-
total: max,
|
|
135
|
-
current: total,
|
|
136
|
-
});
|
|
137
|
-
lastPercent = percent;
|
|
189
|
+
if (!finalTagSeen) {
|
|
190
|
+
throw new Error('Unable to decrypt the data: the data is truncated!');
|
|
138
191
|
}
|
|
192
|
+
void progress?.({
|
|
193
|
+
percent: 1,
|
|
194
|
+
total,
|
|
195
|
+
current: total,
|
|
196
|
+
});
|
|
197
|
+
return final;
|
|
198
|
+
}
|
|
199
|
+
finally {
|
|
200
|
+
destroy();
|
|
139
201
|
}
|
|
140
|
-
destroy();
|
|
141
|
-
void progress?.({
|
|
142
|
-
percent: 1,
|
|
143
|
-
total,
|
|
144
|
-
current: total,
|
|
145
|
-
});
|
|
146
|
-
return final.slice(0, total);
|
|
147
202
|
}
|
|
148
203
|
// async function mainSecretStream(random: Uint8Array): Promise<vo id> {
|
|
149
204
|
// const key = secretstreamKeygen();
|
|
@@ -11,12 +11,11 @@ import { concatenate } from '../utils/array.js';
|
|
|
11
11
|
*/
|
|
12
12
|
export async function encryptDataAndKey({ data, currentIdentity, keyPairs, progress, signal, }) {
|
|
13
13
|
const dataKey = secretStreamKeygen();
|
|
14
|
-
const { data: encryptedData,
|
|
14
|
+
const { data: encryptedData, md5Encrypted } = await encrypt(dataKey, data, progress, signal);
|
|
15
15
|
if (!currentIdentity || !keyPairs) {
|
|
16
16
|
return {
|
|
17
17
|
encryptedData,
|
|
18
18
|
dataKey,
|
|
19
|
-
md5Data,
|
|
20
19
|
md5Encrypted,
|
|
21
20
|
};
|
|
22
21
|
}
|
|
@@ -29,7 +28,6 @@ export async function encryptDataAndKey({ data, currentIdentity, keyPairs, progr
|
|
|
29
28
|
encryptedDataKey: encDataKey,
|
|
30
29
|
encryptedData,
|
|
31
30
|
dataKey,
|
|
32
|
-
md5Data,
|
|
33
31
|
md5Encrypted,
|
|
34
32
|
};
|
|
35
33
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { encryptCryptoBox } from '.';
|
|
1
|
+
import { decryptSecretBox, encryptCryptoBox, encryptSecretBox } from '.';
|
|
2
2
|
import { sodium } from '../sodium';
|
|
3
|
+
import { concatenate } from '../utils/array.js';
|
|
3
4
|
import { encryptSecretStream, secretStreamKeygen } from './data';
|
|
4
5
|
export function generatePassword() {
|
|
5
6
|
return sodium.randombytes_buf(16, 'hex');
|
|
@@ -7,6 +8,27 @@ export function generatePassword() {
|
|
|
7
8
|
export function derivePassword(password, salt) {
|
|
8
9
|
return sodium.crypto_pwhash(sodium.crypto_secretbox_KEYBYTES, password, salt, sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE, sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE, sodium.crypto_pwhash_ALG_ARGON2ID13, 'hex');
|
|
9
10
|
}
|
|
11
|
+
const PASSWORD_KEY_VERSION = 1;
|
|
12
|
+
/**
|
|
13
|
+
* Wrap a data key under a password, with a random salt:
|
|
14
|
+
* `version (1 byte) || salt || nonce || secretbox(key)`.
|
|
15
|
+
*/
|
|
16
|
+
export function encryptKeyWithPassword(key, password) {
|
|
17
|
+
const salt = sodium.randombytes_buf(sodium.crypto_pwhash_SALTBYTES);
|
|
18
|
+
return concatenate(new Uint8Array([PASSWORD_KEY_VERSION]), salt, encryptSecretBox(key, derivePassword(password, salt)));
|
|
19
|
+
}
|
|
20
|
+
/** Unwrap a data key produced by `encryptKeyWithPassword`. */
|
|
21
|
+
export function decryptKeyWithPassword(wrapped, password) {
|
|
22
|
+
const boxBytes = sodium.crypto_secretbox_NONCEBYTES +
|
|
23
|
+
sodium.crypto_secretbox_MACBYTES +
|
|
24
|
+
sodium.crypto_secretstream_xchacha20poly1305_KEYBYTES;
|
|
25
|
+
if (wrapped.byteLength === 1 + sodium.crypto_pwhash_SALTBYTES + boxBytes &&
|
|
26
|
+
wrapped[0] === PASSWORD_KEY_VERSION) {
|
|
27
|
+
const salt = wrapped.slice(1, 1 + sodium.crypto_pwhash_SALTBYTES);
|
|
28
|
+
return decryptSecretBox(wrapped.slice(1 + sodium.crypto_pwhash_SALTBYTES), derivePassword(password, salt));
|
|
29
|
+
}
|
|
30
|
+
throw new Error('Unsupported password protected key format');
|
|
31
|
+
}
|
|
10
32
|
export async function encryptName(name, nameKey) {
|
|
11
33
|
const { data } = await encryptSecretStream(sodium.from_hex(nameKey), sodium.from_string(name));
|
|
12
34
|
return sodium.to_hex(data);
|
package/dist/lib/crypto/index.js
CHANGED
|
@@ -10,7 +10,7 @@ export function generateCryptoBoxKeyPair() {
|
|
|
10
10
|
}
|
|
11
11
|
export function decryptCryptoBox(data, publicKeyAlice, privateKeyBob) {
|
|
12
12
|
if (data.length < sodium.crypto_box_NONCEBYTES + sodium.crypto_box_MACBYTES) {
|
|
13
|
-
throw 'data too short';
|
|
13
|
+
throw new Error('data too short');
|
|
14
14
|
}
|
|
15
15
|
const nonce = data.slice(0, sodium.crypto_box_NONCEBYTES);
|
|
16
16
|
const cipher = data.slice(sodium.crypto_box_NONCEBYTES);
|
|
@@ -27,7 +27,7 @@ export function encryptSecretBox(data, key) {
|
|
|
27
27
|
export function decryptSecretBox(data, key) {
|
|
28
28
|
if (data.length <
|
|
29
29
|
sodium.crypto_secretbox_NONCEBYTES + sodium.crypto_secretbox_MACBYTES) {
|
|
30
|
-
throw 'data too short';
|
|
30
|
+
throw new Error('data too short');
|
|
31
31
|
}
|
|
32
32
|
const nonce = data.slice(0, sodium.crypto_secretbox_NONCEBYTES);
|
|
33
33
|
const cipher = data.slice(sodium.crypto_secretbox_NONCEBYTES);
|
package/dist/lib/error/client.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
export const clientErrorCodeKey = z.enum([
|
|
2
|
+
export const clientErrorCodeKey = z.enum([
|
|
3
|
+
'NOT_FOUND',
|
|
4
|
+
'DATA_TOO_SHORT',
|
|
5
|
+
'POPUP_BLOCKED',
|
|
6
|
+
'POPUP_CLOSED',
|
|
7
|
+
'SERVER_ENVIRONMENT',
|
|
8
|
+
]);
|
|
3
9
|
export const clientError = z.object({
|
|
4
10
|
name: z.literal('ClientError'),
|
|
5
11
|
code: clientErrorCodeKey,
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { createContext, createElement, useCallback, useContext, useEffect, useMemo, useState, } from 'react';
|
|
2
|
+
import { initSecrecy, login as secrecyLogin } from '../client/helpers.js';
|
|
3
|
+
const SecrecyContext = createContext(null);
|
|
4
|
+
export function SecrecyProvider(props) {
|
|
5
|
+
const { appId, session, redirect, secrecyUrls, children } = props;
|
|
6
|
+
const [client, setClient] = useState(null);
|
|
7
|
+
const [status, setStatus] = useState('idle');
|
|
8
|
+
const [error, setError] = useState(null);
|
|
9
|
+
const secrecyUrlsKey = JSON.stringify(secrecyUrls ?? null);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
let cancelled = false;
|
|
12
|
+
setStatus('loading');
|
|
13
|
+
initSecrecy({ appId, session, redirect, secrecyUrls })
|
|
14
|
+
.then((result) => {
|
|
15
|
+
if (cancelled)
|
|
16
|
+
return;
|
|
17
|
+
setClient(result);
|
|
18
|
+
setStatus(result !== null ? 'authenticated' : 'idle');
|
|
19
|
+
})
|
|
20
|
+
.catch((err) => {
|
|
21
|
+
if (cancelled)
|
|
22
|
+
return;
|
|
23
|
+
setError(err);
|
|
24
|
+
setStatus('error');
|
|
25
|
+
});
|
|
26
|
+
return () => {
|
|
27
|
+
cancelled = true;
|
|
28
|
+
};
|
|
29
|
+
// secrecyUrls is tracked through secrecyUrlsKey, a stable primitive.
|
|
30
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
31
|
+
}, [appId, session, redirect, secrecyUrlsKey]);
|
|
32
|
+
const login = useCallback(async () => {
|
|
33
|
+
setStatus('loading');
|
|
34
|
+
setError(null);
|
|
35
|
+
try {
|
|
36
|
+
const result = await secrecyLogin({
|
|
37
|
+
appId,
|
|
38
|
+
session,
|
|
39
|
+
secrecyUrls,
|
|
40
|
+
forceLogin: true,
|
|
41
|
+
});
|
|
42
|
+
setClient(result);
|
|
43
|
+
setStatus('authenticated');
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
setError(err);
|
|
47
|
+
setStatus('error');
|
|
48
|
+
}
|
|
49
|
+
// secrecyUrls is tracked through secrecyUrlsKey, a stable primitive.
|
|
50
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
51
|
+
}, [appId, session, secrecyUrlsKey]);
|
|
52
|
+
const logout = useCallback(async () => {
|
|
53
|
+
if (client === null) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
await client.logout();
|
|
57
|
+
setClient(null);
|
|
58
|
+
setStatus('idle');
|
|
59
|
+
}, [client]);
|
|
60
|
+
const value = useMemo(() => ({ client, status, error, login, logout }), [client, status, error, login, logout]);
|
|
61
|
+
return createElement(SecrecyContext.Provider, { value }, children);
|
|
62
|
+
}
|
|
63
|
+
export function useSecrecy() {
|
|
64
|
+
const ctx = useContext(SecrecyContext);
|
|
65
|
+
if (ctx === null) {
|
|
66
|
+
throw new Error('useSecrecy() must be used within a <SecrecyProvider>');
|
|
67
|
+
}
|
|
68
|
+
return ctx;
|
|
69
|
+
}
|
package/dist/lib/transformer.js
CHANGED
|
@@ -10,9 +10,10 @@ superjson.registerCustom({
|
|
|
10
10
|
serialize: (v) => v.toJSON(),
|
|
11
11
|
deserialize: (v) => Temporal.PlainDateTime.from(v),
|
|
12
12
|
}, 'Temporal.PlainDateTime');
|
|
13
|
+
const hasBuffer = typeof globalThis.Buffer !== 'undefined';
|
|
13
14
|
superjson.registerCustom({
|
|
14
|
-
isApplicable: (v) => v instanceof Buffer,
|
|
15
|
+
isApplicable: (v) => hasBuffer && v instanceof globalThis.Buffer,
|
|
15
16
|
serialize: (v) => [...v],
|
|
16
|
-
deserialize: (v) => Buffer.from(v),
|
|
17
|
+
deserialize: (v) => globalThis.Buffer.from(v),
|
|
17
18
|
}, 'buffer');
|
|
18
19
|
export const transformer = superjson;
|
|
@@ -10,7 +10,6 @@ const defaultOptions = {
|
|
|
10
10
|
scrollbars: 'no',
|
|
11
11
|
centered: true,
|
|
12
12
|
};
|
|
13
|
-
let popupCount = 1;
|
|
14
13
|
/**
|
|
15
14
|
* Return options converted to a string
|
|
16
15
|
*
|
|
@@ -23,12 +22,11 @@ function optionsToString(options) {
|
|
|
23
22
|
.join(',');
|
|
24
23
|
}
|
|
25
24
|
/**
|
|
26
|
-
* Get
|
|
25
|
+
* Get an unpredictable, unique name on each call
|
|
27
26
|
* @return {String}
|
|
28
27
|
*/
|
|
29
28
|
function defaultPopupName() {
|
|
30
|
-
|
|
31
|
-
return `Popup ${popupCount}`;
|
|
29
|
+
return `secrecy-${crypto.randomUUID()}`;
|
|
32
30
|
}
|
|
33
31
|
/**
|
|
34
32
|
* Convert "centered: true" key into concrete left and top arguments
|
|
@@ -100,21 +98,30 @@ function popupExecute(execute, url, name, options, callback) {
|
|
|
100
98
|
//
|
|
101
99
|
};
|
|
102
100
|
const optionsString = optionsToString(popupOptions);
|
|
101
|
+
// Only the page we opened may answer: the popup name is predictable, so
|
|
102
|
+
// without these checks any window could inject a response (e.g. an
|
|
103
|
+
// attacker's session and keys on login).
|
|
104
|
+
const expectedOrigin = new URL(url, window.location.href).origin;
|
|
103
105
|
const win = execute(url, popupName, optionsString);
|
|
104
106
|
let isMessageSent = false;
|
|
105
107
|
let interval;
|
|
106
108
|
function popupCallbackOnce(err, data) {
|
|
107
109
|
if (!isMessageSent) {
|
|
108
110
|
isMessageSent = true;
|
|
111
|
+
window.removeEventListener('message', onMessage);
|
|
112
|
+
clearInterval(interval);
|
|
109
113
|
popupCallback(err, data);
|
|
110
114
|
}
|
|
111
115
|
}
|
|
112
116
|
function onMessage(message) {
|
|
113
|
-
|
|
114
|
-
|
|
117
|
+
if (win === null ||
|
|
118
|
+
message.source !== win ||
|
|
119
|
+
message.origin !== expectedOrigin) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const data = message.data;
|
|
123
|
+
if (data !== undefined && data !== null && data.id === popupName) {
|
|
115
124
|
popupCallbackOnce(undefined, data.data);
|
|
116
|
-
window.removeEventListener('message', onMessage);
|
|
117
|
-
clearInterval(interval);
|
|
118
125
|
}
|
|
119
126
|
}
|
|
120
127
|
window.addEventListener('message', onMessage, false);
|
|
@@ -123,13 +130,21 @@ function popupExecute(execute, url, name, options, callback) {
|
|
|
123
130
|
if (win === null || win.closed) {
|
|
124
131
|
setTimeout(function delayWindowClosing() {
|
|
125
132
|
clearInterval(interval);
|
|
126
|
-
popupCallbackOnce(
|
|
133
|
+
popupCallbackOnce({
|
|
134
|
+
name: 'ClientError',
|
|
135
|
+
code: 'POPUP_CLOSED',
|
|
136
|
+
message: 'The popup was closed before completing',
|
|
137
|
+
});
|
|
127
138
|
}, 500);
|
|
128
139
|
}
|
|
129
140
|
}, 100);
|
|
130
141
|
}
|
|
131
142
|
else {
|
|
132
|
-
popupCallbackOnce(
|
|
143
|
+
popupCallbackOnce({
|
|
144
|
+
name: 'ClientError',
|
|
145
|
+
code: 'POPUP_BLOCKED',
|
|
146
|
+
message: 'The popup was blocked by the browser',
|
|
147
|
+
});
|
|
133
148
|
}
|
|
134
149
|
return win;
|
|
135
150
|
}
|
|
@@ -172,9 +187,12 @@ export function popupWithPost(url, postData, name, options, callback) {
|
|
|
172
187
|
* Return html that when executed, will trigger the popup to callback with a response
|
|
173
188
|
*
|
|
174
189
|
* @param {Object}
|
|
190
|
+
* @param {String} targetOrigin origin of the opener allowed to receive `data`
|
|
175
191
|
* @return {String}
|
|
176
192
|
*/
|
|
177
|
-
export function popupResponse(id, data) {
|
|
178
|
-
|
|
179
|
-
|
|
193
|
+
export function popupResponse(id, data, targetOrigin) {
|
|
194
|
+
// Escape "<" so the payload cannot close the script tag.
|
|
195
|
+
const jsonData = JSON.stringify({ id, data }).replaceAll('<', '\\u003c');
|
|
196
|
+
const origin = JSON.stringify(targetOrigin).replaceAll('<', '\\u003c');
|
|
197
|
+
return `<script>window.opener.postMessage(${jsonData}, ${origin});setTimeout(function() { window.close(); }, 50);</script>`;
|
|
180
198
|
}
|
package/dist/lib/versioning.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SECRECY_LIB_VERSION = '
|
|
1
|
+
export const SECRECY_LIB_VERSION = '0.0.0-development';
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
// Generated by scripts/build-workers.ts, do not edit.
|
|
2
|
+
export const workerMd5Script = "(()=>{var D=Object.create;var{getPrototypeOf:E,defineProperty:F,getOwnPropertyNames:G}=Object;var v=Object.prototype.hasOwnProperty;function H(o){return this[o]}var K,N,R=(o,u,s)=>{var _=o!=null&&typeof o===\"object\";if(_){var y=u?K??=new WeakMap:N??=new WeakMap,b=y.get(o);if(b)return b}s=o!=null?D(E(o)):{};let l=u||!o||!o.__esModule||!v.call(o,\"default\")?F(s,\"default\",{value:o,enumerable:!0}):s;if(o&&typeof o===\"object\"||typeof o===\"function\"){for(let g of G(o))if(!v.call(l,g))F(l,g,{get:H.bind(o,g),enumerable:!0})}if(_)y.set(o,l);return l};var Z=(o,u)=>()=>(u||o((u={exports:{}}).exports,u),u.exports);var S=Z(function(w,U){(function(o){if(typeof w===\"object\")U.exports=o();else if(typeof define===\"function\"&&define.amd)define(o);else{var u;try{u=window}catch(s){u=self}u.SparkMD5=o()}})(function(o){var u=function(i,f){return i+f&4294967295},s=[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"a\",\"b\",\"c\",\"d\",\"e\",\"f\"];function _(i,f,r,t,n,e){return f=u(u(f,i),u(t,e)),u(f<<n|f>>>32-n,r)}function y(i,f){var r=i[0],t=i[1],n=i[2],e=i[3];r+=(t&n|~t&e)+f[0]-680876936|0,r=(r<<7|r>>>25)+t|0,e+=(r&t|~r&n)+f[1]-389564586|0,e=(e<<12|e>>>20)+r|0,n+=(e&r|~e&t)+f[2]+606105819|0,n=(n<<17|n>>>15)+e|0,t+=(n&e|~n&r)+f[3]-1044525330|0,t=(t<<22|t>>>10)+n|0,r+=(t&n|~t&e)+f[4]-176418897|0,r=(r<<7|r>>>25)+t|0,e+=(r&t|~r&n)+f[5]+1200080426|0,e=(e<<12|e>>>20)+r|0,n+=(e&r|~e&t)+f[6]-1473231341|0,n=(n<<17|n>>>15)+e|0,t+=(n&e|~n&r)+f[7]-45705983|0,t=(t<<22|t>>>10)+n|0,r+=(t&n|~t&e)+f[8]+1770035416|0,r=(r<<7|r>>>25)+t|0,e+=(r&t|~r&n)+f[9]-1958414417|0,e=(e<<12|e>>>20)+r|0,n+=(e&r|~e&t)+f[10]-42063|0,n=(n<<17|n>>>15)+e|0,t+=(n&e|~n&r)+f[11]-1990404162|0,t=(t<<22|t>>>10)+n|0,r+=(t&n|~t&e)+f[12]+1804603682|0,r=(r<<7|r>>>25)+t|0,e+=(r&t|~r&n)+f[13]-40341101|0,e=(e<<12|e>>>20)+r|0,n+=(e&r|~e&t)+f[14]-1502002290|0,n=(n<<17|n>>>15)+e|0,t+=(n&e|~n&r)+f[15]+1236535329|0,t=(t<<22|t>>>10)+n|0,r+=(t&e|n&~e)+f[1]-165796510|0,r=(r<<5|r>>>27)+t|0,e+=(r&n|t&~n)+f[6]-1069501632|0,e=(e<<9|e>>>23)+r|0,n+=(e&t|r&~t)+f[11]+643717713|0,n=(n<<14|n>>>18)+e|0,t+=(n&r|e&~r)+f[0]-373897302|0,t=(t<<20|t>>>12)+n|0,r+=(t&e|n&~e)+f[5]-701558691|0,r=(r<<5|r>>>27)+t|0,e+=(r&n|t&~n)+f[10]+38016083|0,e=(e<<9|e>>>23)+r|0,n+=(e&t|r&~t)+f[15]-660478335|0,n=(n<<14|n>>>18)+e|0,t+=(n&r|e&~r)+f[4]-405537848|0,t=(t<<20|t>>>12)+n|0,r+=(t&e|n&~e)+f[9]+568446438|0,r=(r<<5|r>>>27)+t|0,e+=(r&n|t&~n)+f[14]-1019803690|0,e=(e<<9|e>>>23)+r|0,n+=(e&t|r&~t)+f[3]-187363961|0,n=(n<<14|n>>>18)+e|0,t+=(n&r|e&~r)+f[8]+1163531501|0,t=(t<<20|t>>>12)+n|0,r+=(t&e|n&~e)+f[13]-1444681467|0,r=(r<<5|r>>>27)+t|0,e+=(r&n|t&~n)+f[2]-51403784|0,e=(e<<9|e>>>23)+r|0,n+=(e&t|r&~t)+f[7]+1735328473|0,n=(n<<14|n>>>18)+e|0,t+=(n&r|e&~r)+f[12]-1926607734|0,t=(t<<20|t>>>12)+n|0,r+=(t^n^e)+f[5]-378558|0,r=(r<<4|r>>>28)+t|0,e+=(r^t^n)+f[8]-2022574463|0,e=(e<<11|e>>>21)+r|0,n+=(e^r^t)+f[11]+1839030562|0,n=(n<<16|n>>>16)+e|0,t+=(n^e^r)+f[14]-35309556|0,t=(t<<23|t>>>9)+n|0,r+=(t^n^e)+f[1]-1530992060|0,r=(r<<4|r>>>28)+t|0,e+=(r^t^n)+f[4]+1272893353|0,e=(e<<11|e>>>21)+r|0,n+=(e^r^t)+f[7]-155497632|0,n=(n<<16|n>>>16)+e|0,t+=(n^e^r)+f[10]-1094730640|0,t=(t<<23|t>>>9)+n|0,r+=(t^n^e)+f[13]+681279174|0,r=(r<<4|r>>>28)+t|0,e+=(r^t^n)+f[0]-358537222|0,e=(e<<11|e>>>21)+r|0,n+=(e^r^t)+f[3]-722521979|0,n=(n<<16|n>>>16)+e|0,t+=(n^e^r)+f[6]+76029189|0,t=(t<<23|t>>>9)+n|0,r+=(t^n^e)+f[9]-640364487|0,r=(r<<4|r>>>28)+t|0,e+=(r^t^n)+f[12]-421815835|0,e=(e<<11|e>>>21)+r|0,n+=(e^r^t)+f[15]+530742520|0,n=(n<<16|n>>>16)+e|0,t+=(n^e^r)+f[2]-995338651|0,t=(t<<23|t>>>9)+n|0,r+=(n^(t|~e))+f[0]-198630844|0,r=(r<<6|r>>>26)+t|0,e+=(t^(r|~n))+f[7]+1126891415|0,e=(e<<10|e>>>22)+r|0,n+=(r^(e|~t))+f[14]-1416354905|0,n=(n<<15|n>>>17)+e|0,t+=(e^(n|~r))+f[5]-57434055|0,t=(t<<21|t>>>11)+n|0,r+=(n^(t|~e))+f[12]+1700485571|0,r=(r<<6|r>>>26)+t|0,e+=(t^(r|~n))+f[3]-1894986606|0,e=(e<<10|e>>>22)+r|0,n+=(r^(e|~t))+f[10]-1051523|0,n=(n<<15|n>>>17)+e|0,t+=(e^(n|~r))+f[1]-2054922799|0,t=(t<<21|t>>>11)+n|0,r+=(n^(t|~e))+f[8]+1873313359|0,r=(r<<6|r>>>26)+t|0,e+=(t^(r|~n))+f[15]-30611744|0,e=(e<<10|e>>>22)+r|0,n+=(r^(e|~t))+f[6]-1560198380|0,n=(n<<15|n>>>17)+e|0,t+=(e^(n|~r))+f[13]+1309151649|0,t=(t<<21|t>>>11)+n|0,r+=(n^(t|~e))+f[4]-145523070|0,r=(r<<6|r>>>26)+t|0,e+=(t^(r|~n))+f[11]-1120210379|0,e=(e<<10|e>>>22)+r|0,n+=(r^(e|~t))+f[2]+718787259|0,n=(n<<15|n>>>17)+e|0,t+=(e^(n|~r))+f[9]-343485551|0,t=(t<<21|t>>>11)+n|0,i[0]=r+i[0]|0,i[1]=t+i[1]|0,i[2]=n+i[2]|0,i[3]=e+i[3]|0}function b(i){var f=[],r;for(r=0;r<64;r+=4)f[r>>2]=i.charCodeAt(r)+(i.charCodeAt(r+1)<<8)+(i.charCodeAt(r+2)<<16)+(i.charCodeAt(r+3)<<24);return f}function l(i){var f=[],r;for(r=0;r<64;r+=4)f[r>>2]=i[r]+(i[r+1]<<8)+(i[r+2]<<16)+(i[r+3]<<24);return f}function g(i){var f=i.length,r=[1732584193,-271733879,-1732584194,271733878],t,n,e,a,c,p;for(t=64;t<=f;t+=64)y(r,b(i.substring(t-64,t)));i=i.substring(t-64),n=i.length,e=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(t=0;t<n;t+=1)e[t>>2]|=i.charCodeAt(t)<<(t%4<<3);if(e[t>>2]|=128<<(t%4<<3),t>55){y(r,e);for(t=0;t<16;t+=1)e[t]=0}return a=f*8,a=a.toString(16).match(/(.*?)(.{0,8})$/),c=parseInt(a[2],16),p=parseInt(a[1],16)||0,e[14]=c,e[15]=p,y(r,e),r}function T(i){var f=i.length,r=[1732584193,-271733879,-1732584194,271733878],t,n,e,a,c,p;for(t=64;t<=f;t+=64)y(r,l(i.subarray(t-64,t)));i=t-64<f?i.subarray(t-64):new Uint8Array(0),n=i.length,e=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(t=0;t<n;t+=1)e[t>>2]|=i[t]<<(t%4<<3);if(e[t>>2]|=128<<(t%4<<3),t>55){y(r,e);for(t=0;t<16;t+=1)e[t]=0}return a=f*8,a=a.toString(16).match(/(.*?)(.{0,8})$/),c=parseInt(a[2],16),p=parseInt(a[1],16)||0,e[14]=c,e[15]=p,y(r,e),r}function L(i){var f=\"\",r;for(r=0;r<4;r+=1)f+=s[i>>r*8+4&15]+s[i>>r*8&15];return f}function d(i){var f;for(f=0;f<i.length;f+=1)i[f]=L(i[f]);return i.join(\"\")}if(d(g(\"hello\"))!==\"5d41402abc4b2a76b9719d911017c592\")u=function(i,f){var r=(i&65535)+(f&65535),t=(i>>16)+(f>>16)+(r>>16);return t<<16|r&65535};if(typeof ArrayBuffer<\"u\"&&!ArrayBuffer.prototype.slice)(function(){function i(f,r){if(f=f|0||0,f<0)return Math.max(f+r,0);return Math.min(f,r)}ArrayBuffer.prototype.slice=function(f,r){var t=this.byteLength,n=i(f,t),e=t,a,c,p,B;if(r!==o)e=i(r,t);if(n>e)return new ArrayBuffer(0);return a=e-n,c=new ArrayBuffer(a),p=new Uint8Array(c),B=new Uint8Array(this,n,a),p.set(B),c}})();function m(i){if(/[\\u0080-\\uFFFF]/.test(i))i=unescape(encodeURIComponent(i));return i}function M(i,f){var r=i.length,t=new ArrayBuffer(r),n=new Uint8Array(t),e;for(e=0;e<r;e+=1)n[e]=i.charCodeAt(e);return f?n:t}function x(i){return String.fromCharCode.apply(null,new Uint8Array(i))}function j(i,f,r){var t=new Uint8Array(i.byteLength+f.byteLength);return t.set(new Uint8Array(i)),t.set(new Uint8Array(f),i.byteLength),r?t:t.buffer}function A(i){var f=[],r=i.length,t;for(t=0;t<r-1;t+=2)f.push(parseInt(i.substr(t,2),16));return String.fromCharCode.apply(String,f)}function h(){this.reset()}return h.prototype.append=function(i){return this.appendBinary(m(i)),this},h.prototype.appendBinary=function(i){this._buff+=i,this._length+=i.length;var f=this._buff.length,r;for(r=64;r<=f;r+=64)y(this._hash,b(this._buff.substring(r-64,r)));return this._buff=this._buff.substring(r-64),this},h.prototype.end=function(i){var f=this._buff,r=f.length,t,n=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],e;for(t=0;t<r;t+=1)n[t>>2]|=f.charCodeAt(t)<<(t%4<<3);if(this._finish(n,r),e=d(this._hash),i)e=A(e);return this.reset(),e},h.prototype.reset=function(){return this._buff=\"\",this._length=0,this._hash=[1732584193,-271733879,-1732584194,271733878],this},h.prototype.getState=function(){return{buff:this._buff,length:this._length,hash:this._hash.slice()}},h.prototype.setState=function(i){return this._buff=i.buff,this._length=i.length,this._hash=i.hash,this},h.prototype.destroy=function(){delete this._hash,delete this._buff,delete this._length},h.prototype._finish=function(i,f){var r=f,t,n,e;if(i[r>>2]|=128<<(r%4<<3),r>55){y(this._hash,i);for(r=0;r<16;r+=1)i[r]=0}t=this._length*8,t=t.toString(16).match(/(.*?)(.{0,8})$/),n=parseInt(t[2],16),e=parseInt(t[1],16)||0,i[14]=n,i[15]=e,y(this._hash,i)},h.hash=function(i,f){return h.hashBinary(m(i),f)},h.hashBinary=function(i,f){var r=g(i),t=d(r);return f?A(t):t},h.ArrayBuffer=function(){this.reset()},h.ArrayBuffer.prototype.append=function(i){var f=j(this._buff.buffer,i,!0),r=f.length,t;this._length+=i.byteLength;for(t=64;t<=r;t+=64)y(this._hash,l(f.subarray(t-64,t)));return this._buff=t-64<r?new Uint8Array(f.buffer.slice(t-64)):new Uint8Array(0),this},h.ArrayBuffer.prototype.end=function(i){var f=this._buff,r=f.length,t=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],n,e;for(n=0;n<r;n+=1)t[n>>2]|=f[n]<<(n%4<<3);if(this._finish(t,r),e=d(this._hash),i)e=A(e);return this.reset(),e},h.ArrayBuffer.prototype.reset=function(){return this._buff=new Uint8Array(0),this._length=0,this._hash=[1732584193,-271733879,-1732584194,271733878],this},h.ArrayBuffer.prototype.getState=function(){var i=h.prototype.getState.call(this);return i.buff=x(i.buff),i},h.ArrayBuffer.prototype.setState=function(i){return i.buff=M(i.buff,!0),h.prototype.setState.call(this,i)},h.ArrayBuffer.prototype.destroy=h.prototype.destroy,h.ArrayBuffer.prototype._finish=h.prototype._finish,h.ArrayBuffer.hash=function(i,f){var r=T(new Uint8Array(i)),t=d(r);return f?A(t):t},h})});var I=R(S(),1);function*C(o,u){for(let s=0;s<o.length;s+=u)yield o.slice(s,s+u)}var q=8192;self.onmessage=({data:o})=>{if(o.event===\"md5\"){let u=new I.default.ArrayBuffer;for(let s of C(o.data,q))u.append(s.buffer);postMessage({event:\"md5-result\",data:u.end()})}};})();\n";
|