@time-file/browser-file-crypto 1.0.3 → 1.1.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/README.ko.md +78 -4
- package/README.md +78 -4
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +398 -7
- package/dist/index.mjs +486 -200
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const ne = 16, ae = 12, re = 256, ce = 1e5, se = 32, ie = 1, oe = 2, Ee = 17, le = 18, pe = 65536, ye = 1, ue = 16, de = 45, fe = 29, w = "AES-GCM", F = "SHA-256", Y = {
|
|
2
2
|
INVALID_INPUT: "Input must be a File, Blob, or ArrayBuffer.",
|
|
3
3
|
PASSWORD_REQUIRED: "Password or keyfile is required for encryption.",
|
|
4
4
|
KEYFILE_REQUIRED: "Keyfile is required to decrypt this file.",
|
|
@@ -10,47 +10,47 @@ const k = 16, G = 12, C = 256, U = 1e5, M = 32, v = 1, V = 2, B = 16, W = 45, x
|
|
|
10
10
|
DOWNLOAD_FAILED: "File download failed.",
|
|
11
11
|
UNSUPPORTED_FORMAT: "Unsupported encryption format."
|
|
12
12
|
};
|
|
13
|
-
class
|
|
13
|
+
class E extends Error {
|
|
14
14
|
/**
|
|
15
15
|
* Creates a new CryptoError.
|
|
16
16
|
*
|
|
17
17
|
* @param code - Error code identifying the type of error
|
|
18
18
|
* @param message - Optional custom message (defaults to predefined message)
|
|
19
19
|
*/
|
|
20
|
-
constructor(
|
|
21
|
-
super(
|
|
20
|
+
constructor(r, e) {
|
|
21
|
+
super(e ?? Y[r]), this.name = "CryptoError", this.code = r, Error.captureStackTrace && Error.captureStackTrace(this, E);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
function
|
|
25
|
-
return n instanceof
|
|
24
|
+
function he(n) {
|
|
25
|
+
return n instanceof E;
|
|
26
26
|
}
|
|
27
|
-
async function
|
|
27
|
+
async function S(n) {
|
|
28
28
|
if (n instanceof ArrayBuffer)
|
|
29
29
|
return n;
|
|
30
30
|
if (n instanceof Blob)
|
|
31
31
|
return n.arrayBuffer();
|
|
32
|
-
throw new
|
|
32
|
+
throw new E("INVALID_INPUT");
|
|
33
33
|
}
|
|
34
|
-
function
|
|
34
|
+
function R(n) {
|
|
35
35
|
return n.buffer.slice(n.byteOffset, n.byteOffset + n.byteLength);
|
|
36
36
|
}
|
|
37
|
-
function
|
|
38
|
-
const
|
|
39
|
-
let
|
|
40
|
-
for (let
|
|
41
|
-
|
|
42
|
-
return btoa(
|
|
43
|
-
}
|
|
44
|
-
function
|
|
45
|
-
const
|
|
46
|
-
for (let
|
|
47
|
-
t
|
|
48
|
-
return
|
|
49
|
-
}
|
|
50
|
-
async function
|
|
51
|
-
const
|
|
37
|
+
function U(n) {
|
|
38
|
+
const r = new Uint8Array(n);
|
|
39
|
+
let e = "";
|
|
40
|
+
for (let t = 0; t < r.byteLength; t++)
|
|
41
|
+
e += String.fromCharCode(r[t]);
|
|
42
|
+
return btoa(e);
|
|
43
|
+
}
|
|
44
|
+
function O(n) {
|
|
45
|
+
const r = atob(n), e = new Uint8Array(r.length);
|
|
46
|
+
for (let t = 0; t < r.length; t++)
|
|
47
|
+
e[t] = r.charCodeAt(t);
|
|
48
|
+
return e.buffer;
|
|
49
|
+
}
|
|
50
|
+
async function I(n, r) {
|
|
51
|
+
const e = new TextEncoder(), t = await crypto.subtle.importKey(
|
|
52
52
|
"raw",
|
|
53
|
-
|
|
53
|
+
e.encode(n),
|
|
54
54
|
"PBKDF2",
|
|
55
55
|
!1,
|
|
56
56
|
["deriveKey"]
|
|
@@ -58,278 +58,564 @@ async function A(n, a) {
|
|
|
58
58
|
return crypto.subtle.deriveKey(
|
|
59
59
|
{
|
|
60
60
|
name: "PBKDF2",
|
|
61
|
-
salt:
|
|
61
|
+
salt: R(r),
|
|
62
62
|
iterations: 1e5,
|
|
63
|
-
hash:
|
|
63
|
+
hash: F
|
|
64
64
|
},
|
|
65
|
-
|
|
66
|
-
{ name:
|
|
65
|
+
t,
|
|
66
|
+
{ name: w, length: 256 },
|
|
67
67
|
!1,
|
|
68
68
|
// non-extractable for security
|
|
69
69
|
["encrypt", "decrypt"]
|
|
70
70
|
);
|
|
71
71
|
}
|
|
72
|
-
async function
|
|
72
|
+
async function T(n) {
|
|
73
73
|
try {
|
|
74
|
-
const
|
|
74
|
+
const r = O(n);
|
|
75
75
|
return await crypto.subtle.importKey(
|
|
76
76
|
"raw",
|
|
77
|
-
|
|
78
|
-
{ name:
|
|
77
|
+
r,
|
|
78
|
+
{ name: w, length: 256 },
|
|
79
79
|
!1,
|
|
80
80
|
// non-extractable for security
|
|
81
81
|
["encrypt", "decrypt"]
|
|
82
82
|
);
|
|
83
83
|
} catch {
|
|
84
|
-
throw new
|
|
84
|
+
throw new E("INVALID_KEYFILE");
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
|
-
function
|
|
87
|
+
function N(n) {
|
|
88
88
|
return crypto.getRandomValues(new Uint8Array(n));
|
|
89
89
|
}
|
|
90
|
-
function
|
|
91
|
-
return
|
|
90
|
+
function b() {
|
|
91
|
+
return N(16);
|
|
92
92
|
}
|
|
93
|
-
function
|
|
94
|
-
return
|
|
93
|
+
function D() {
|
|
94
|
+
return N(12);
|
|
95
95
|
}
|
|
96
|
-
const
|
|
97
|
-
function
|
|
98
|
-
const
|
|
99
|
-
let
|
|
100
|
-
for (let
|
|
101
|
-
const c =
|
|
102
|
-
|
|
96
|
+
const L = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*", H = 16;
|
|
97
|
+
function Re(n = H) {
|
|
98
|
+
const r = Math.max(8, Math.min(128, n)), e = N(r);
|
|
99
|
+
let t = "";
|
|
100
|
+
for (let a = 0; a < r; a++) {
|
|
101
|
+
const c = e[a] % L.length;
|
|
102
|
+
t += L[c];
|
|
103
103
|
}
|
|
104
|
-
return
|
|
104
|
+
return t;
|
|
105
|
+
}
|
|
106
|
+
function M(n, r) {
|
|
107
|
+
const e = new Uint8Array(12);
|
|
108
|
+
e.set(n);
|
|
109
|
+
const t = new DataView(e.buffer), a = t.getUint32(8, !0);
|
|
110
|
+
return t.setUint32(8, a ^ r, !0), e;
|
|
105
111
|
}
|
|
106
|
-
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
112
|
+
function k(n, r) {
|
|
113
|
+
const e = new Uint8Array(n.length + r.length);
|
|
114
|
+
return e.set(n, 0), e.set(r, n.length), e;
|
|
115
|
+
}
|
|
116
|
+
async function m(n, r, e, t) {
|
|
117
|
+
const a = M(e, t), c = await crypto.subtle.encrypt(
|
|
118
|
+
{ name: w, iv: R(a) },
|
|
119
|
+
r,
|
|
120
|
+
R(n)
|
|
121
|
+
), s = new Uint8Array(4 + c.byteLength);
|
|
122
|
+
return new DataView(s.buffer).setUint32(0, c.byteLength, !0), s.set(new Uint8Array(c), 4), s;
|
|
123
|
+
}
|
|
124
|
+
async function V(n, r, e, t, a) {
|
|
125
|
+
const c = M(e, t);
|
|
110
126
|
try {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
127
|
+
const s = await crypto.subtle.decrypt(
|
|
128
|
+
{ name: w, iv: R(c) },
|
|
129
|
+
r,
|
|
130
|
+
R(n)
|
|
131
|
+
);
|
|
132
|
+
return new Uint8Array(s);
|
|
133
|
+
} catch {
|
|
134
|
+
throw t === 0 ? new E(a ? "INVALID_PASSWORD" : "INVALID_KEYFILE") : new E("DECRYPTION_FAILED");
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function v(n, r, e, t) {
|
|
138
|
+
if (n && e) {
|
|
139
|
+
const a = new Uint8Array(34);
|
|
140
|
+
return a[0] = 17, a[1] = 1, new DataView(a.buffer).setUint32(2, r, !0), a.set(e, 6), a.set(t, 22), a;
|
|
141
|
+
} else {
|
|
142
|
+
const a = new Uint8Array(18);
|
|
143
|
+
return a[0] = 18, a[1] = 1, new DataView(a.buffer).setUint32(2, r, !0), a.set(t, 6), a;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function B(n) {
|
|
147
|
+
const r = n[0], e = r === 17;
|
|
148
|
+
if (r !== 17 && r !== 18)
|
|
149
|
+
throw new E("UNSUPPORTED_FORMAT");
|
|
150
|
+
const t = n[1];
|
|
151
|
+
if (t !== 1)
|
|
152
|
+
throw new E("UNSUPPORTED_FORMAT");
|
|
153
|
+
const a = new DataView(n.buffer, n.byteOffset).getUint32(
|
|
154
|
+
2,
|
|
155
|
+
!0
|
|
156
|
+
);
|
|
157
|
+
if (e) {
|
|
158
|
+
const c = n.slice(6, 22), s = n.slice(22, 34);
|
|
159
|
+
return { isPassword: e, version: t, chunkSize: a, salt: c, baseIV: s, headerSize: 34 };
|
|
160
|
+
} else {
|
|
161
|
+
const c = n.slice(6, 18);
|
|
162
|
+
return { isPassword: e, version: t, chunkSize: a, salt: null, baseIV: c, headerSize: 18 };
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async function G(n) {
|
|
166
|
+
const { password: r, keyData: e, chunkSize: t = 65536, onProgress: a } = n;
|
|
167
|
+
if (!r && !e)
|
|
168
|
+
throw new E("PASSWORD_REQUIRED");
|
|
169
|
+
const c = !!r, s = c ? b() : null, i = D();
|
|
170
|
+
a == null || a({
|
|
171
|
+
phase: "deriving_key",
|
|
172
|
+
processedBytes: 0,
|
|
173
|
+
processedChunks: 0
|
|
174
|
+
});
|
|
175
|
+
const p = c ? await I(r, s) : await T(e), l = v(c, t, s, i);
|
|
176
|
+
let o = new Uint8Array(0), y = 0, u = 0;
|
|
177
|
+
return { stream: new TransformStream({
|
|
178
|
+
async transform(d, f) {
|
|
179
|
+
for (o = k(o, d); o.length >= t; ) {
|
|
180
|
+
const _ = o.slice(0, t);
|
|
181
|
+
o = o.slice(t);
|
|
182
|
+
const h = await m(_, p, i, y);
|
|
183
|
+
f.enqueue(h), y++, u += _.length, a == null || a({
|
|
184
|
+
phase: "encrypting",
|
|
185
|
+
processedBytes: u,
|
|
186
|
+
processedChunks: y
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
async flush(d) {
|
|
191
|
+
if (o.length > 0) {
|
|
192
|
+
const f = await m(o, p, i, y);
|
|
193
|
+
d.enqueue(f), u += o.length, y++;
|
|
194
|
+
}
|
|
195
|
+
a == null || a({
|
|
196
|
+
phase: "complete",
|
|
197
|
+
processedBytes: u,
|
|
198
|
+
processedChunks: y,
|
|
199
|
+
progress: 100
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}), header: l };
|
|
203
|
+
}
|
|
204
|
+
function g(n) {
|
|
205
|
+
const { password: r, keyData: e, onProgress: t } = n;
|
|
206
|
+
let a = new Uint8Array(0), c = !1, s = null, i = null, p = 0, l = 0, o = !1, y = 0;
|
|
207
|
+
return new TransformStream({
|
|
208
|
+
async transform(u, A) {
|
|
209
|
+
if (a = k(a, u), !c) {
|
|
210
|
+
if (a.length < 2) return;
|
|
211
|
+
const f = a[0] === 17 ? 34 : 18;
|
|
212
|
+
if (a.length < f) return;
|
|
213
|
+
const _ = a.slice(0, f), h = B(_);
|
|
214
|
+
if (o = h.isPassword, i = h.baseIV, y = h.headerSize, o && !r)
|
|
215
|
+
throw new E("PASSWORD_REQUIRED");
|
|
216
|
+
if (!o && !e)
|
|
217
|
+
throw new E("KEYFILE_REQUIRED");
|
|
218
|
+
t == null || t({
|
|
219
|
+
phase: "deriving_key",
|
|
220
|
+
processedBytes: 0,
|
|
221
|
+
processedChunks: 0
|
|
222
|
+
}), s = o ? await I(r, h.salt) : await T(e), a = a.slice(y), c = !0;
|
|
223
|
+
}
|
|
224
|
+
for (; a.length >= 4; ) {
|
|
225
|
+
const f = 4 + new DataView(
|
|
226
|
+
a.buffer,
|
|
227
|
+
a.byteOffset
|
|
228
|
+
).getUint32(0, !0);
|
|
229
|
+
if (a.length < f) break;
|
|
230
|
+
const _ = a.slice(4, f);
|
|
231
|
+
a = a.slice(f);
|
|
232
|
+
const h = await V(_, s, i, p, o);
|
|
233
|
+
A.enqueue(h), l += h.length, p++, t == null || t({
|
|
234
|
+
phase: "decrypting",
|
|
235
|
+
processedBytes: l,
|
|
236
|
+
processedChunks: p
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
async flush() {
|
|
241
|
+
if (a.length > 0)
|
|
242
|
+
throw new E("INVALID_ENCRYPTED_DATA");
|
|
243
|
+
t == null || t({
|
|
244
|
+
phase: "complete",
|
|
245
|
+
processedBytes: l,
|
|
246
|
+
processedChunks: p,
|
|
247
|
+
progress: 100
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
async function W(n, r) {
|
|
253
|
+
const e = n.size, t = r.onProgress ? (o) => {
|
|
254
|
+
r.onProgress({
|
|
255
|
+
...o,
|
|
256
|
+
totalBytes: e,
|
|
257
|
+
progress: o.phase === "complete" ? 100 : Math.round(o.processedBytes / e * 100)
|
|
258
|
+
});
|
|
259
|
+
} : void 0, { stream: a, header: c } = await G({
|
|
260
|
+
...r,
|
|
261
|
+
onProgress: t
|
|
262
|
+
}), i = n.stream().pipeThrough(a);
|
|
263
|
+
let p = !1;
|
|
264
|
+
const l = i.getReader();
|
|
265
|
+
return new ReadableStream({
|
|
266
|
+
async pull(o) {
|
|
267
|
+
if (!p) {
|
|
268
|
+
o.enqueue(c), p = !0;
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
try {
|
|
272
|
+
const { done: y, value: u } = await l.read();
|
|
273
|
+
y ? o.close() : o.enqueue(u);
|
|
274
|
+
} catch (y) {
|
|
275
|
+
o.error(y);
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
cancel() {
|
|
279
|
+
l.releaseLock();
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
function K(n, r) {
|
|
284
|
+
const e = g(r);
|
|
285
|
+
return n instanceof ReadableStream ? n.pipeThrough(e) : n.stream().pipeThrough(e);
|
|
286
|
+
}
|
|
287
|
+
const x = 100 * 1024 * 1024;
|
|
288
|
+
async function z(n, r) {
|
|
289
|
+
const { password: e, keyData: t, onProgress: a } = r;
|
|
290
|
+
if (!e && !t)
|
|
291
|
+
throw new E("PASSWORD_REQUIRED");
|
|
292
|
+
try {
|
|
293
|
+
a == null || a({ phase: "deriving_key", progress: 0 });
|
|
294
|
+
const c = await S(n);
|
|
295
|
+
return a == null || a({ phase: "deriving_key", progress: 10 }), t ? await Q(c, t, a) : await P(c, e, a);
|
|
114
296
|
} catch (c) {
|
|
115
|
-
throw c instanceof
|
|
297
|
+
throw c instanceof E ? c : new E("ENCRYPTION_FAILED");
|
|
116
298
|
}
|
|
117
299
|
}
|
|
118
|
-
async function
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
const c = await
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
{ name:
|
|
300
|
+
async function P(n, r, e) {
|
|
301
|
+
const t = b(), a = D();
|
|
302
|
+
e == null || e({ phase: "deriving_key", progress: 20 });
|
|
303
|
+
const c = await I(r, t);
|
|
304
|
+
e == null || e({ phase: "encrypting", progress: 30 });
|
|
305
|
+
const s = await crypto.subtle.encrypt(
|
|
306
|
+
{ name: w, iv: R(a) },
|
|
125
307
|
c,
|
|
126
308
|
n
|
|
127
309
|
);
|
|
128
|
-
|
|
129
|
-
const
|
|
130
|
-
29 +
|
|
310
|
+
e == null || e({ phase: "encrypting", progress: 90 });
|
|
311
|
+
const i = new Uint8Array(
|
|
312
|
+
29 + s.byteLength
|
|
131
313
|
);
|
|
132
|
-
return
|
|
314
|
+
return i[0] = 1, i.set(t, 1), i.set(a, 17), i.set(new Uint8Array(s), 29), e == null || e({ phase: "complete", progress: 100 }), new Blob([i], { type: "application/octet-stream" });
|
|
133
315
|
}
|
|
134
|
-
async function
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
|
|
316
|
+
async function Q(n, r, e) {
|
|
317
|
+
const t = D();
|
|
318
|
+
e == null || e({ phase: "deriving_key", progress: 20 });
|
|
319
|
+
const a = await T(r);
|
|
320
|
+
e == null || e({ phase: "encrypting", progress: 30 });
|
|
139
321
|
const c = await crypto.subtle.encrypt(
|
|
140
|
-
{ name:
|
|
141
|
-
|
|
322
|
+
{ name: w, iv: R(t) },
|
|
323
|
+
a,
|
|
142
324
|
n
|
|
143
325
|
);
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
return
|
|
326
|
+
e == null || e({ phase: "encrypting", progress: 90 });
|
|
327
|
+
const s = new Uint8Array(13 + c.byteLength);
|
|
328
|
+
return s[0] = 2, s.set(t, 1), s.set(new Uint8Array(c), 13), e == null || e({ phase: "complete", progress: 100 }), new Blob([s], { type: "application/octet-stream" });
|
|
147
329
|
}
|
|
148
|
-
async function
|
|
149
|
-
const {
|
|
330
|
+
async function we(n, r) {
|
|
331
|
+
const {
|
|
332
|
+
password: e,
|
|
333
|
+
keyData: t,
|
|
334
|
+
onProgress: a,
|
|
335
|
+
autoStreaming: c = !1,
|
|
336
|
+
streamingThreshold: s = x,
|
|
337
|
+
chunkSize: i = 65536
|
|
338
|
+
} = r;
|
|
339
|
+
if (!e && !t)
|
|
340
|
+
throw new E("PASSWORD_REQUIRED");
|
|
341
|
+
if (c && n.size > s) {
|
|
342
|
+
const o = await W(n, {
|
|
343
|
+
password: e,
|
|
344
|
+
keyData: t,
|
|
345
|
+
chunkSize: i,
|
|
346
|
+
onProgress: a ? (u) => {
|
|
347
|
+
a({
|
|
348
|
+
phase: u.phase,
|
|
349
|
+
progress: u.progress ?? Math.round(u.processedBytes / n.size * 100)
|
|
350
|
+
});
|
|
351
|
+
} : void 0
|
|
352
|
+
});
|
|
353
|
+
return await new Response(o).blob();
|
|
354
|
+
} else
|
|
355
|
+
return await z(n, { password: e, keyData: t, onProgress: a });
|
|
356
|
+
}
|
|
357
|
+
async function Z(n, r) {
|
|
358
|
+
const { password: e, keyData: t, onProgress: a } = r;
|
|
150
359
|
try {
|
|
151
|
-
|
|
152
|
-
const c = new Uint8Array(await
|
|
153
|
-
if (
|
|
154
|
-
throw new
|
|
155
|
-
const
|
|
156
|
-
if (
|
|
157
|
-
if (!t)
|
|
158
|
-
throw new p("PASSWORD_REQUIRED");
|
|
159
|
-
return await b(c, t, i);
|
|
160
|
-
} else if (r === 2) {
|
|
360
|
+
a == null || a({ phase: "decrypting", progress: 0 });
|
|
361
|
+
const c = new Uint8Array(await S(n));
|
|
362
|
+
if (a == null || a({ phase: "decrypting", progress: 5 }), c.length < 1)
|
|
363
|
+
throw new E("INVALID_ENCRYPTED_DATA");
|
|
364
|
+
const s = c[0];
|
|
365
|
+
if (s === 1) {
|
|
161
366
|
if (!e)
|
|
162
|
-
throw new
|
|
163
|
-
return await
|
|
164
|
-
} else
|
|
165
|
-
|
|
367
|
+
throw new E("PASSWORD_REQUIRED");
|
|
368
|
+
return await q(c, e, a);
|
|
369
|
+
} else if (s === 2) {
|
|
370
|
+
if (!t)
|
|
371
|
+
throw new E("KEYFILE_REQUIRED");
|
|
372
|
+
return await j(c, t, a);
|
|
373
|
+
} else {
|
|
374
|
+
if (s === 17 || s === 18)
|
|
375
|
+
return await $(n, r);
|
|
376
|
+
throw new E("UNSUPPORTED_FORMAT");
|
|
377
|
+
}
|
|
166
378
|
} catch (c) {
|
|
167
|
-
throw c instanceof
|
|
379
|
+
throw c instanceof E ? c : new E("DECRYPTION_FAILED");
|
|
168
380
|
}
|
|
169
381
|
}
|
|
170
|
-
async function
|
|
382
|
+
async function q(n, r, e) {
|
|
171
383
|
if (n.length < 45)
|
|
172
|
-
throw new
|
|
173
|
-
|
|
174
|
-
const
|
|
175
|
-
|
|
384
|
+
throw new E("INVALID_ENCRYPTED_DATA");
|
|
385
|
+
e == null || e({ phase: "deriving_key", progress: 10 });
|
|
386
|
+
const t = n.slice(1, 17), a = n.slice(17, 29), c = n.slice(29), s = await I(r, t);
|
|
387
|
+
e == null || e({ phase: "decrypting", progress: 30 });
|
|
176
388
|
try {
|
|
177
|
-
const
|
|
178
|
-
{ name:
|
|
179
|
-
|
|
389
|
+
const i = await crypto.subtle.decrypt(
|
|
390
|
+
{ name: w, iv: R(a) },
|
|
391
|
+
s,
|
|
180
392
|
c
|
|
181
393
|
);
|
|
182
|
-
return
|
|
394
|
+
return e == null || e({ phase: "complete", progress: 100 }), new Blob([i]);
|
|
183
395
|
} catch {
|
|
184
|
-
throw new
|
|
396
|
+
throw new E("INVALID_PASSWORD");
|
|
185
397
|
}
|
|
186
398
|
}
|
|
187
|
-
async function
|
|
399
|
+
async function j(n, r, e) {
|
|
188
400
|
if (n.length < 29)
|
|
189
|
-
throw new
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
|
|
401
|
+
throw new E("INVALID_ENCRYPTED_DATA");
|
|
402
|
+
e == null || e({ phase: "decrypting", progress: 10 });
|
|
403
|
+
const t = n.slice(1, 13), a = n.slice(13), c = await T(r);
|
|
404
|
+
e == null || e({ phase: "decrypting", progress: 30 });
|
|
193
405
|
try {
|
|
194
|
-
const
|
|
195
|
-
{ name:
|
|
406
|
+
const s = await crypto.subtle.decrypt(
|
|
407
|
+
{ name: w, iv: R(t) },
|
|
196
408
|
c,
|
|
197
|
-
|
|
409
|
+
a
|
|
198
410
|
);
|
|
199
|
-
return
|
|
411
|
+
return e == null || e({ phase: "complete", progress: 100 }), new Blob([s]);
|
|
200
412
|
} catch {
|
|
201
|
-
throw new
|
|
413
|
+
throw new E("INVALID_KEYFILE");
|
|
202
414
|
}
|
|
203
415
|
}
|
|
204
|
-
async function
|
|
205
|
-
const a =
|
|
206
|
-
|
|
416
|
+
async function $(n, r) {
|
|
417
|
+
const { password: e, keyData: t, onProgress: a } = r, c = n instanceof Blob ? n : new Blob([n]), i = K(c, {
|
|
418
|
+
password: e,
|
|
419
|
+
keyData: t,
|
|
420
|
+
onProgress: a ? (l) => {
|
|
421
|
+
a({
|
|
422
|
+
phase: l.phase,
|
|
423
|
+
progress: l.progress ?? Math.round(l.processedBytes / (l.totalBytes || 1) * 100)
|
|
424
|
+
});
|
|
425
|
+
} : void 0
|
|
426
|
+
});
|
|
427
|
+
return await new Response(i).blob();
|
|
428
|
+
}
|
|
429
|
+
async function _e(n) {
|
|
430
|
+
const r = await S(n), e = new Uint8Array(r);
|
|
431
|
+
if (e.length < 1)
|
|
207
432
|
return "unknown";
|
|
208
|
-
const
|
|
209
|
-
return
|
|
433
|
+
const t = e[0];
|
|
434
|
+
return t === 1 ? "password" : t === 2 ? "keyfile" : t === 17 ? "password-stream" : t === 18 ? "keyfile-stream" : "unknown";
|
|
210
435
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
436
|
+
const J = 34, X = 18;
|
|
437
|
+
async function Ae(n) {
|
|
438
|
+
const r = await S(n), e = new Uint8Array(r);
|
|
439
|
+
if (e.length < 1)
|
|
214
440
|
return !1;
|
|
215
|
-
const
|
|
216
|
-
return
|
|
441
|
+
const t = e[0];
|
|
442
|
+
return t === 1 && e.length >= 45 || t === 2 && e.length >= 29 || t === 17 && e.length >= J || t === 18 && e.length >= X;
|
|
443
|
+
}
|
|
444
|
+
function Se(n) {
|
|
445
|
+
return n === "password-stream" || n === "keyfile-stream";
|
|
217
446
|
}
|
|
218
|
-
function
|
|
219
|
-
const n =
|
|
447
|
+
function Ie() {
|
|
448
|
+
const n = N(32);
|
|
220
449
|
return {
|
|
221
450
|
version: 1,
|
|
222
451
|
algorithm: "AES-256-GCM",
|
|
223
|
-
key:
|
|
452
|
+
key: U(n.buffer),
|
|
224
453
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
225
454
|
};
|
|
226
455
|
}
|
|
227
|
-
function
|
|
456
|
+
function Te(n) {
|
|
228
457
|
try {
|
|
229
|
-
const
|
|
230
|
-
return
|
|
458
|
+
const r = JSON.parse(n);
|
|
459
|
+
return ee(r) ? r : null;
|
|
231
460
|
} catch {
|
|
232
461
|
return null;
|
|
233
462
|
}
|
|
234
463
|
}
|
|
235
|
-
function
|
|
464
|
+
function ee(n) {
|
|
236
465
|
if (typeof n != "object" || n === null)
|
|
237
466
|
return !1;
|
|
238
|
-
const
|
|
239
|
-
return
|
|
467
|
+
const r = n;
|
|
468
|
+
return r.version === 1 && r.algorithm === "AES-256-GCM" && typeof r.key == "string" && r.key.length > 0 && typeof r.createdAt == "string";
|
|
240
469
|
}
|
|
241
|
-
function
|
|
242
|
-
const
|
|
470
|
+
function Ne(n, r, e = "key") {
|
|
471
|
+
const t = {
|
|
243
472
|
version: 1,
|
|
244
473
|
algorithm: "AES-256-GCM",
|
|
245
474
|
key: n,
|
|
246
475
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
247
|
-
},
|
|
248
|
-
|
|
476
|
+
}, a = JSON.stringify(t, null, 2), c = new Blob([a], { type: "application/json" }), s = URL.createObjectURL(c), i = document.createElement("a");
|
|
477
|
+
i.href = s, i.download = `${r}.${e}`, i.style.display = "none", document.body.appendChild(i), i.click(), document.body.removeChild(i), URL.revokeObjectURL(s);
|
|
249
478
|
}
|
|
250
|
-
async function
|
|
251
|
-
const
|
|
252
|
-
return Array.from(
|
|
479
|
+
async function De(n) {
|
|
480
|
+
const r = O(n), e = await crypto.subtle.digest("SHA-256", r), t = new Uint8Array(e);
|
|
481
|
+
return Array.from(t).map((a) => a.toString(16).padStart(2, "0")).join("");
|
|
253
482
|
}
|
|
254
|
-
async function
|
|
255
|
-
const { fileName:
|
|
483
|
+
async function Le(n, r) {
|
|
484
|
+
const { fileName: e, onProgress: t, ...a } = r;
|
|
256
485
|
try {
|
|
257
|
-
|
|
486
|
+
t == null || t({ phase: "downloading", progress: 0 });
|
|
258
487
|
const c = await fetch(n);
|
|
259
488
|
if (!c.ok)
|
|
260
|
-
throw new
|
|
489
|
+
throw new E(
|
|
261
490
|
"DOWNLOAD_FAILED",
|
|
262
491
|
`Download failed: ${c.status} ${c.statusText}`
|
|
263
492
|
);
|
|
264
|
-
const
|
|
265
|
-
let
|
|
266
|
-
|
|
493
|
+
const s = c.headers.get("content-length");
|
|
494
|
+
let i;
|
|
495
|
+
s && c.body ? i = await te(
|
|
267
496
|
c.body,
|
|
268
|
-
parseInt(
|
|
269
|
-
(
|
|
270
|
-
|
|
497
|
+
parseInt(s, 10),
|
|
498
|
+
(l) => {
|
|
499
|
+
t == null || t({ phase: "downloading", progress: Math.round(l * 50) });
|
|
271
500
|
}
|
|
272
|
-
) : (
|
|
273
|
-
const
|
|
274
|
-
...
|
|
275
|
-
onProgress: (
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
phase:
|
|
279
|
-
progress:
|
|
501
|
+
) : (t == null || t({ phase: "downloading", progress: 25 }), i = await c.arrayBuffer()), t == null || t({ phase: "downloading", progress: 50 });
|
|
502
|
+
const p = await Z(i, {
|
|
503
|
+
...a,
|
|
504
|
+
onProgress: (l) => {
|
|
505
|
+
const o = 50 + Math.round(l.progress * 0.45);
|
|
506
|
+
t == null || t({
|
|
507
|
+
phase: l.phase === "complete" ? "complete" : l.phase,
|
|
508
|
+
progress: l.phase === "complete" ? 100 : o
|
|
280
509
|
});
|
|
281
510
|
}
|
|
282
511
|
});
|
|
283
|
-
|
|
512
|
+
C(p, e), t == null || t({ phase: "complete", progress: 100 });
|
|
284
513
|
} catch (c) {
|
|
285
|
-
throw c instanceof
|
|
514
|
+
throw c instanceof E ? c : new E("DOWNLOAD_FAILED");
|
|
286
515
|
}
|
|
287
516
|
}
|
|
288
|
-
async function
|
|
289
|
-
const
|
|
290
|
-
let c = 0,
|
|
291
|
-
for (; !
|
|
292
|
-
const
|
|
293
|
-
if (
|
|
294
|
-
|
|
295
|
-
const
|
|
296
|
-
|
|
517
|
+
async function te(n, r, e) {
|
|
518
|
+
const t = n.getReader(), a = [];
|
|
519
|
+
let c = 0, s = !1;
|
|
520
|
+
for (; !s; ) {
|
|
521
|
+
const l = await t.read();
|
|
522
|
+
if (s = l.done, l.value) {
|
|
523
|
+
a.push(l.value), c += l.value.length;
|
|
524
|
+
const o = c / r;
|
|
525
|
+
e(Math.min(o, 1));
|
|
297
526
|
}
|
|
298
527
|
}
|
|
299
|
-
const
|
|
300
|
-
let
|
|
301
|
-
for (const
|
|
302
|
-
|
|
303
|
-
return
|
|
528
|
+
const i = new Uint8Array(c);
|
|
529
|
+
let p = 0;
|
|
530
|
+
for (const l of a)
|
|
531
|
+
i.set(l, p), p += l.length;
|
|
532
|
+
return i.buffer;
|
|
304
533
|
}
|
|
305
|
-
function
|
|
306
|
-
const
|
|
307
|
-
|
|
534
|
+
function C(n, r) {
|
|
535
|
+
const e = URL.createObjectURL(n), t = document.createElement("a");
|
|
536
|
+
t.href = e, t.download = r, t.style.display = "none", document.body.appendChild(t), t.click(), document.body.removeChild(t), URL.revokeObjectURL(e);
|
|
537
|
+
}
|
|
538
|
+
async function me(n, r) {
|
|
539
|
+
const { fileName: e, password: t, keyData: a, onProgress: c } = r;
|
|
540
|
+
try {
|
|
541
|
+
c == null || c({
|
|
542
|
+
phase: "downloading",
|
|
543
|
+
processedBytes: 0,
|
|
544
|
+
processedChunks: 0,
|
|
545
|
+
progress: 0
|
|
546
|
+
});
|
|
547
|
+
const s = await fetch(n);
|
|
548
|
+
if (!s.ok)
|
|
549
|
+
throw new E(
|
|
550
|
+
"DOWNLOAD_FAILED",
|
|
551
|
+
`Download failed: ${s.status} ${s.statusText}`
|
|
552
|
+
);
|
|
553
|
+
const i = s.headers.get("content-length"), p = i ? parseInt(i, 10) : void 0;
|
|
554
|
+
c == null || c({
|
|
555
|
+
phase: "downloading",
|
|
556
|
+
processedBytes: 0,
|
|
557
|
+
processedChunks: 0,
|
|
558
|
+
totalBytes: p,
|
|
559
|
+
progress: 25
|
|
560
|
+
});
|
|
561
|
+
const l = await s.blob();
|
|
562
|
+
let o = 0;
|
|
563
|
+
const y = K(l, {
|
|
564
|
+
password: t,
|
|
565
|
+
keyData: a,
|
|
566
|
+
onProgress: (d) => {
|
|
567
|
+
o = d.processedBytes, c == null || c({
|
|
568
|
+
...d,
|
|
569
|
+
// Map to 50-95% range
|
|
570
|
+
progress: d.phase === "complete" ? 100 : 50 + Math.round((d.progress ?? 0) * 0.45)
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
}), A = await new Response(y).blob();
|
|
574
|
+
C(A, e), c == null || c({
|
|
575
|
+
phase: "complete",
|
|
576
|
+
processedBytes: o,
|
|
577
|
+
processedChunks: 0,
|
|
578
|
+
progress: 100
|
|
579
|
+
});
|
|
580
|
+
} catch (s) {
|
|
581
|
+
throw s instanceof E ? s : new E("DOWNLOAD_FAILED");
|
|
582
|
+
}
|
|
308
583
|
}
|
|
309
584
|
export {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
585
|
+
w as ALGORITHM,
|
|
586
|
+
ue as AUTH_TAG_LENGTH,
|
|
587
|
+
E as CryptoError,
|
|
588
|
+
pe as DEFAULT_CHUNK_SIZE,
|
|
589
|
+
oe as ENCRYPTION_MARKER_KEYFILE,
|
|
590
|
+
le as ENCRYPTION_MARKER_KEYFILE_STREAM,
|
|
591
|
+
ie as ENCRYPTION_MARKER_PASSWORD,
|
|
592
|
+
Ee as ENCRYPTION_MARKER_PASSWORD_STREAM,
|
|
593
|
+
F as HASH_ALGORITHM,
|
|
594
|
+
ae as IV_LENGTH,
|
|
595
|
+
se as KEYFILE_KEY_LENGTH,
|
|
596
|
+
re as KEY_LENGTH,
|
|
597
|
+
fe as MIN_ENCRYPTED_SIZE_KEYFILE,
|
|
598
|
+
de as MIN_ENCRYPTED_SIZE_PASSWORD,
|
|
599
|
+
ce as PBKDF2_ITERATIONS,
|
|
600
|
+
ne as SALT_LENGTH,
|
|
601
|
+
ye as STREAM_FORMAT_VERSION,
|
|
602
|
+
De as computeKeyFileHash,
|
|
603
|
+
g as createDecryptStream,
|
|
604
|
+
G as createEncryptStream,
|
|
605
|
+
Z as decryptFile,
|
|
606
|
+
K as decryptFileStream,
|
|
607
|
+
Le as downloadAndDecrypt,
|
|
608
|
+
me as downloadAndDecryptStream,
|
|
609
|
+
Ne as downloadKeyFile,
|
|
610
|
+
z as encryptFile,
|
|
611
|
+
we as encryptFileAuto,
|
|
612
|
+
W as encryptFileStream,
|
|
613
|
+
Ie as generateKeyFile,
|
|
614
|
+
Re as generateRandomPassword,
|
|
615
|
+
_e as getEncryptionType,
|
|
616
|
+
he as isCryptoError,
|
|
617
|
+
Ae as isEncryptedFile,
|
|
618
|
+
Se as isStreamingEncryption,
|
|
619
|
+
Te as parseKeyFile
|
|
334
620
|
};
|
|
335
621
|
//# sourceMappingURL=index.mjs.map
|