@time-file/browser-file-crypto 1.1.0 → 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 +37 -3
- package/README.md +37 -3
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +135 -1
- package/dist/index.mjs +411 -319
- 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,44 +10,44 @@ const J = 16, P = 12, X = 256, ee = 1e5, te = 32, ne = 1, re = 2, ae = 17, ce =
|
|
|
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(e ??
|
|
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
|
|
37
|
+
function U(n) {
|
|
38
|
+
const r = new Uint8Array(n);
|
|
39
39
|
let e = "";
|
|
40
|
-
for (let t = 0; t <
|
|
41
|
-
e += String.fromCharCode(
|
|
40
|
+
for (let t = 0; t < r.byteLength; t++)
|
|
41
|
+
e += String.fromCharCode(r[t]);
|
|
42
42
|
return btoa(e);
|
|
43
43
|
}
|
|
44
44
|
function O(n) {
|
|
45
|
-
const
|
|
46
|
-
for (let t = 0; t <
|
|
47
|
-
e[t] =
|
|
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
48
|
return e.buffer;
|
|
49
49
|
}
|
|
50
|
-
async function
|
|
50
|
+
async function I(n, r) {
|
|
51
51
|
const e = new TextEncoder(), t = await crypto.subtle.importKey(
|
|
52
52
|
"raw",
|
|
53
53
|
e.encode(n),
|
|
@@ -58,319 +58,221 @@ async function T(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
65
|
t,
|
|
66
|
-
{ name:
|
|
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 L = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*",
|
|
97
|
-
function
|
|
98
|
-
const
|
|
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
99
|
let t = "";
|
|
100
|
-
for (let
|
|
101
|
-
const c = e[
|
|
100
|
+
for (let a = 0; a < r; a++) {
|
|
101
|
+
const c = e[a] % L.length;
|
|
102
102
|
t += L[c];
|
|
103
103
|
}
|
|
104
104
|
return t;
|
|
105
105
|
}
|
|
106
|
-
|
|
107
|
-
const { password: e, keyData: t, onProgress: r } = a;
|
|
108
|
-
if (!e && !t)
|
|
109
|
-
throw new o("PASSWORD_REQUIRED");
|
|
110
|
-
try {
|
|
111
|
-
r == null || r({ phase: "deriving_key", progress: 0 });
|
|
112
|
-
const c = await w(n);
|
|
113
|
-
return r == null || r({ phase: "deriving_key", progress: 10 }), t ? await H(c, t, r) : await F(c, e, r);
|
|
114
|
-
} catch (c) {
|
|
115
|
-
throw c instanceof o ? c : new o("ENCRYPTION_FAILED");
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
async function F(n, a, e) {
|
|
119
|
-
const t = M(), r = N();
|
|
120
|
-
e == null || e({ phase: "deriving_key", progress: 20 });
|
|
121
|
-
const c = await T(a, t);
|
|
122
|
-
e == null || e({ phase: "encrypting", progress: 30 });
|
|
123
|
-
const i = await crypto.subtle.encrypt(
|
|
124
|
-
{ name: _, iv: h(r) },
|
|
125
|
-
c,
|
|
126
|
-
n
|
|
127
|
-
);
|
|
128
|
-
e == null || e({ phase: "encrypting", progress: 90 });
|
|
129
|
-
const s = new Uint8Array(
|
|
130
|
-
29 + i.byteLength
|
|
131
|
-
);
|
|
132
|
-
return s[0] = 1, s.set(t, 1), s.set(r, 17), s.set(new Uint8Array(i), 29), e == null || e({ phase: "complete", progress: 100 }), new Blob([s], { type: "application/octet-stream" });
|
|
133
|
-
}
|
|
134
|
-
async function H(n, a, e) {
|
|
135
|
-
const t = N();
|
|
136
|
-
e == null || e({ phase: "deriving_key", progress: 20 });
|
|
137
|
-
const r = await I(a);
|
|
138
|
-
e == null || e({ phase: "encrypting", progress: 30 });
|
|
139
|
-
const c = await crypto.subtle.encrypt(
|
|
140
|
-
{ name: _, iv: h(t) },
|
|
141
|
-
r,
|
|
142
|
-
n
|
|
143
|
-
);
|
|
144
|
-
e == null || e({ phase: "encrypting", progress: 90 });
|
|
145
|
-
const i = new Uint8Array(13 + c.byteLength);
|
|
146
|
-
return i[0] = 2, i.set(t, 1), i.set(new Uint8Array(c), 13), e == null || e({ phase: "complete", progress: 100 }), new Blob([i], { type: "application/octet-stream" });
|
|
147
|
-
}
|
|
148
|
-
async function V(n, a) {
|
|
149
|
-
const { password: e, keyData: t, onProgress: r } = a;
|
|
150
|
-
try {
|
|
151
|
-
r == null || r({ phase: "decrypting", progress: 0 });
|
|
152
|
-
const c = new Uint8Array(await w(n));
|
|
153
|
-
if (r == null || r({ phase: "decrypting", progress: 5 }), c.length < 1)
|
|
154
|
-
throw new o("INVALID_ENCRYPTED_DATA");
|
|
155
|
-
const i = c[0];
|
|
156
|
-
if (i === 1) {
|
|
157
|
-
if (!e)
|
|
158
|
-
throw new o("PASSWORD_REQUIRED");
|
|
159
|
-
return await v(c, e, r);
|
|
160
|
-
} else if (i === 2) {
|
|
161
|
-
if (!t)
|
|
162
|
-
throw new o("KEYFILE_REQUIRED");
|
|
163
|
-
return await G(c, t, r);
|
|
164
|
-
} else
|
|
165
|
-
throw new o("UNSUPPORTED_FORMAT");
|
|
166
|
-
} catch (c) {
|
|
167
|
-
throw c instanceof o ? c : new o("DECRYPTION_FAILED");
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
async function v(n, a, e) {
|
|
171
|
-
if (n.length < 45)
|
|
172
|
-
throw new o("INVALID_ENCRYPTED_DATA");
|
|
173
|
-
e == null || e({ phase: "deriving_key", progress: 10 });
|
|
174
|
-
const t = n.slice(1, 17), r = n.slice(17, 29), c = n.slice(29), i = await T(a, t);
|
|
175
|
-
e == null || e({ phase: "decrypting", progress: 30 });
|
|
176
|
-
try {
|
|
177
|
-
const s = await crypto.subtle.decrypt(
|
|
178
|
-
{ name: _, iv: h(r) },
|
|
179
|
-
i,
|
|
180
|
-
c
|
|
181
|
-
);
|
|
182
|
-
return e == null || e({ phase: "complete", progress: 100 }), new Blob([s]);
|
|
183
|
-
} catch {
|
|
184
|
-
throw new o("INVALID_PASSWORD");
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
async function G(n, a, e) {
|
|
188
|
-
if (n.length < 29)
|
|
189
|
-
throw new o("INVALID_ENCRYPTED_DATA");
|
|
190
|
-
e == null || e({ phase: "decrypting", progress: 10 });
|
|
191
|
-
const t = n.slice(1, 13), r = n.slice(13), c = await I(a);
|
|
192
|
-
e == null || e({ phase: "decrypting", progress: 30 });
|
|
193
|
-
try {
|
|
194
|
-
const i = await crypto.subtle.decrypt(
|
|
195
|
-
{ name: _, iv: h(t) },
|
|
196
|
-
c,
|
|
197
|
-
r
|
|
198
|
-
);
|
|
199
|
-
return e == null || e({ phase: "complete", progress: 100 }), new Blob([i]);
|
|
200
|
-
} catch {
|
|
201
|
-
throw new o("INVALID_KEYFILE");
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
function K(n, a) {
|
|
106
|
+
function M(n, r) {
|
|
205
107
|
const e = new Uint8Array(12);
|
|
206
108
|
e.set(n);
|
|
207
|
-
const t = new DataView(e.buffer),
|
|
208
|
-
return t.setUint32(8,
|
|
109
|
+
const t = new DataView(e.buffer), a = t.getUint32(8, !0);
|
|
110
|
+
return t.setUint32(8, a ^ r, !0), e;
|
|
209
111
|
}
|
|
210
|
-
function
|
|
211
|
-
const e = new Uint8Array(n.length +
|
|
212
|
-
return e.set(n, 0), e.set(
|
|
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;
|
|
213
115
|
}
|
|
214
|
-
async function m(n,
|
|
215
|
-
const
|
|
216
|
-
{ name:
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
),
|
|
220
|
-
return new DataView(
|
|
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;
|
|
221
123
|
}
|
|
222
|
-
async function
|
|
223
|
-
const
|
|
124
|
+
async function V(n, r, e, t, a) {
|
|
125
|
+
const c = M(e, t);
|
|
224
126
|
try {
|
|
225
|
-
const
|
|
226
|
-
{ name:
|
|
227
|
-
|
|
228
|
-
|
|
127
|
+
const s = await crypto.subtle.decrypt(
|
|
128
|
+
{ name: w, iv: R(c) },
|
|
129
|
+
r,
|
|
130
|
+
R(n)
|
|
229
131
|
);
|
|
230
|
-
return new Uint8Array(
|
|
132
|
+
return new Uint8Array(s);
|
|
231
133
|
} catch {
|
|
232
|
-
throw new
|
|
134
|
+
throw t === 0 ? new E(a ? "INVALID_PASSWORD" : "INVALID_KEYFILE") : new E("DECRYPTION_FAILED");
|
|
233
135
|
}
|
|
234
136
|
}
|
|
235
|
-
function
|
|
137
|
+
function v(n, r, e, t) {
|
|
236
138
|
if (n && e) {
|
|
237
|
-
const
|
|
238
|
-
return
|
|
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;
|
|
239
141
|
} else {
|
|
240
|
-
const
|
|
241
|
-
return
|
|
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;
|
|
242
144
|
}
|
|
243
145
|
}
|
|
244
|
-
function
|
|
245
|
-
const
|
|
246
|
-
if (
|
|
247
|
-
throw new
|
|
146
|
+
function B(n) {
|
|
147
|
+
const r = n[0], e = r === 17;
|
|
148
|
+
if (r !== 17 && r !== 18)
|
|
149
|
+
throw new E("UNSUPPORTED_FORMAT");
|
|
248
150
|
const t = n[1];
|
|
249
151
|
if (t !== 1)
|
|
250
|
-
throw new
|
|
251
|
-
const
|
|
152
|
+
throw new E("UNSUPPORTED_FORMAT");
|
|
153
|
+
const a = new DataView(n.buffer, n.byteOffset).getUint32(
|
|
252
154
|
2,
|
|
253
155
|
!0
|
|
254
156
|
);
|
|
255
157
|
if (e) {
|
|
256
|
-
const c = n.slice(6, 22),
|
|
257
|
-
return { isPassword: e, version: t, chunkSize:
|
|
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 };
|
|
258
160
|
} else {
|
|
259
161
|
const c = n.slice(6, 18);
|
|
260
|
-
return { isPassword: e, version: t, chunkSize:
|
|
162
|
+
return { isPassword: e, version: t, chunkSize: a, salt: null, baseIV: c, headerSize: 18 };
|
|
261
163
|
}
|
|
262
164
|
}
|
|
263
|
-
async function
|
|
264
|
-
const { password:
|
|
265
|
-
if (!
|
|
266
|
-
throw new
|
|
267
|
-
const c = !!
|
|
268
|
-
|
|
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({
|
|
269
171
|
phase: "deriving_key",
|
|
270
172
|
processedBytes: 0,
|
|
271
173
|
processedChunks: 0
|
|
272
174
|
});
|
|
273
|
-
const
|
|
274
|
-
let
|
|
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;
|
|
275
177
|
return { stream: new TransformStream({
|
|
276
|
-
async transform(d,
|
|
277
|
-
for (
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
phase: "
|
|
283
|
-
processedBytes:
|
|
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,
|
|
284
186
|
processedChunks: y
|
|
285
187
|
});
|
|
286
188
|
}
|
|
287
189
|
},
|
|
288
190
|
async flush(d) {
|
|
289
|
-
if (
|
|
290
|
-
const
|
|
291
|
-
d.enqueue(
|
|
191
|
+
if (o.length > 0) {
|
|
192
|
+
const f = await m(o, p, i, y);
|
|
193
|
+
d.enqueue(f), u += o.length, y++;
|
|
292
194
|
}
|
|
293
|
-
|
|
195
|
+
a == null || a({
|
|
294
196
|
phase: "complete",
|
|
295
|
-
processedBytes:
|
|
197
|
+
processedBytes: u,
|
|
296
198
|
processedChunks: y,
|
|
297
199
|
progress: 100
|
|
298
200
|
});
|
|
299
201
|
}
|
|
300
202
|
}), header: l };
|
|
301
203
|
}
|
|
302
|
-
function
|
|
303
|
-
const { password:
|
|
304
|
-
let
|
|
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;
|
|
305
207
|
return new TransformStream({
|
|
306
|
-
async transform(
|
|
307
|
-
if (
|
|
308
|
-
if (
|
|
309
|
-
const
|
|
310
|
-
if (
|
|
311
|
-
const
|
|
312
|
-
if (
|
|
313
|
-
throw new
|
|
314
|
-
if (!
|
|
315
|
-
throw new
|
|
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");
|
|
316
218
|
t == null || t({
|
|
317
219
|
phase: "deriving_key",
|
|
318
220
|
processedBytes: 0,
|
|
319
221
|
processedChunks: 0
|
|
320
|
-
}),
|
|
222
|
+
}), s = o ? await I(r, h.salt) : await T(e), a = a.slice(y), c = !0;
|
|
321
223
|
}
|
|
322
|
-
for (;
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
224
|
+
for (; a.length >= 4; ) {
|
|
225
|
+
const f = 4 + new DataView(
|
|
226
|
+
a.buffer,
|
|
227
|
+
a.byteOffset
|
|
326
228
|
).getUint32(0, !0);
|
|
327
|
-
if (
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
phase: "
|
|
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",
|
|
333
235
|
processedBytes: l,
|
|
334
|
-
processedChunks:
|
|
236
|
+
processedChunks: p
|
|
335
237
|
});
|
|
336
238
|
}
|
|
337
239
|
},
|
|
338
240
|
async flush() {
|
|
339
|
-
if (
|
|
340
|
-
throw new
|
|
241
|
+
if (a.length > 0)
|
|
242
|
+
throw new E("INVALID_ENCRYPTED_DATA");
|
|
341
243
|
t == null || t({
|
|
342
244
|
phase: "complete",
|
|
343
245
|
processedBytes: l,
|
|
344
|
-
processedChunks:
|
|
246
|
+
processedChunks: p,
|
|
345
247
|
progress: 100
|
|
346
248
|
});
|
|
347
249
|
}
|
|
348
250
|
});
|
|
349
251
|
}
|
|
350
|
-
async function
|
|
351
|
-
const e = n.size, t =
|
|
352
|
-
|
|
353
|
-
...
|
|
252
|
+
async function W(n, r) {
|
|
253
|
+
const e = n.size, t = r.onProgress ? (o) => {
|
|
254
|
+
r.onProgress({
|
|
255
|
+
...o,
|
|
354
256
|
totalBytes: e,
|
|
355
|
-
progress:
|
|
257
|
+
progress: o.phase === "complete" ? 100 : Math.round(o.processedBytes / e * 100)
|
|
356
258
|
});
|
|
357
|
-
} : void 0, { stream:
|
|
358
|
-
...
|
|
259
|
+
} : void 0, { stream: a, header: c } = await G({
|
|
260
|
+
...r,
|
|
359
261
|
onProgress: t
|
|
360
|
-
}),
|
|
361
|
-
let
|
|
362
|
-
const l =
|
|
262
|
+
}), i = n.stream().pipeThrough(a);
|
|
263
|
+
let p = !1;
|
|
264
|
+
const l = i.getReader();
|
|
363
265
|
return new ReadableStream({
|
|
364
|
-
async pull(
|
|
365
|
-
if (!
|
|
366
|
-
|
|
266
|
+
async pull(o) {
|
|
267
|
+
if (!p) {
|
|
268
|
+
o.enqueue(c), p = !0;
|
|
367
269
|
return;
|
|
368
270
|
}
|
|
369
271
|
try {
|
|
370
|
-
const { done: y, value:
|
|
371
|
-
y ?
|
|
272
|
+
const { done: y, value: u } = await l.read();
|
|
273
|
+
y ? o.close() : o.enqueue(u);
|
|
372
274
|
} catch (y) {
|
|
373
|
-
|
|
275
|
+
o.error(y);
|
|
374
276
|
}
|
|
375
277
|
},
|
|
376
278
|
cancel() {
|
|
@@ -378,152 +280,342 @@ async function fe(n, a) {
|
|
|
378
280
|
}
|
|
379
281
|
});
|
|
380
282
|
}
|
|
381
|
-
function
|
|
382
|
-
const e =
|
|
283
|
+
function K(n, r) {
|
|
284
|
+
const e = g(r);
|
|
383
285
|
return n instanceof ReadableStream ? n.pipeThrough(e) : n.stream().pipeThrough(e);
|
|
384
286
|
}
|
|
385
|
-
|
|
386
|
-
|
|
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);
|
|
296
|
+
} catch (c) {
|
|
297
|
+
throw c instanceof E ? c : new E("ENCRYPTION_FAILED");
|
|
298
|
+
}
|
|
299
|
+
}
|
|
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) },
|
|
307
|
+
c,
|
|
308
|
+
n
|
|
309
|
+
);
|
|
310
|
+
e == null || e({ phase: "encrypting", progress: 90 });
|
|
311
|
+
const i = new Uint8Array(
|
|
312
|
+
29 + s.byteLength
|
|
313
|
+
);
|
|
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" });
|
|
315
|
+
}
|
|
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 });
|
|
321
|
+
const c = await crypto.subtle.encrypt(
|
|
322
|
+
{ name: w, iv: R(t) },
|
|
323
|
+
a,
|
|
324
|
+
n
|
|
325
|
+
);
|
|
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" });
|
|
329
|
+
}
|
|
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;
|
|
359
|
+
try {
|
|
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) {
|
|
366
|
+
if (!e)
|
|
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
|
+
}
|
|
378
|
+
} catch (c) {
|
|
379
|
+
throw c instanceof E ? c : new E("DECRYPTION_FAILED");
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
async function q(n, r, e) {
|
|
383
|
+
if (n.length < 45)
|
|
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 });
|
|
388
|
+
try {
|
|
389
|
+
const i = await crypto.subtle.decrypt(
|
|
390
|
+
{ name: w, iv: R(a) },
|
|
391
|
+
s,
|
|
392
|
+
c
|
|
393
|
+
);
|
|
394
|
+
return e == null || e({ phase: "complete", progress: 100 }), new Blob([i]);
|
|
395
|
+
} catch {
|
|
396
|
+
throw new E("INVALID_PASSWORD");
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
async function j(n, r, e) {
|
|
400
|
+
if (n.length < 29)
|
|
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 });
|
|
405
|
+
try {
|
|
406
|
+
const s = await crypto.subtle.decrypt(
|
|
407
|
+
{ name: w, iv: R(t) },
|
|
408
|
+
c,
|
|
409
|
+
a
|
|
410
|
+
);
|
|
411
|
+
return e == null || e({ phase: "complete", progress: 100 }), new Blob([s]);
|
|
412
|
+
} catch {
|
|
413
|
+
throw new E("INVALID_KEYFILE");
|
|
414
|
+
}
|
|
415
|
+
}
|
|
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);
|
|
387
431
|
if (e.length < 1)
|
|
388
432
|
return "unknown";
|
|
389
433
|
const t = e[0];
|
|
390
434
|
return t === 1 ? "password" : t === 2 ? "keyfile" : t === 17 ? "password-stream" : t === 18 ? "keyfile-stream" : "unknown";
|
|
391
435
|
}
|
|
392
|
-
const
|
|
393
|
-
async function
|
|
394
|
-
const
|
|
436
|
+
const J = 34, X = 18;
|
|
437
|
+
async function Ae(n) {
|
|
438
|
+
const r = await S(n), e = new Uint8Array(r);
|
|
395
439
|
if (e.length < 1)
|
|
396
440
|
return !1;
|
|
397
441
|
const t = e[0];
|
|
398
|
-
return t === 1 && e.length >= 45 || t === 2 && e.length >= 29 || t === 17 && e.length >=
|
|
442
|
+
return t === 1 && e.length >= 45 || t === 2 && e.length >= 29 || t === 17 && e.length >= J || t === 18 && e.length >= X;
|
|
399
443
|
}
|
|
400
|
-
function
|
|
444
|
+
function Se(n) {
|
|
401
445
|
return n === "password-stream" || n === "keyfile-stream";
|
|
402
446
|
}
|
|
403
|
-
function
|
|
404
|
-
const n =
|
|
447
|
+
function Ie() {
|
|
448
|
+
const n = N(32);
|
|
405
449
|
return {
|
|
406
450
|
version: 1,
|
|
407
451
|
algorithm: "AES-256-GCM",
|
|
408
|
-
key:
|
|
452
|
+
key: U(n.buffer),
|
|
409
453
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
410
454
|
};
|
|
411
455
|
}
|
|
412
|
-
function
|
|
456
|
+
function Te(n) {
|
|
413
457
|
try {
|
|
414
|
-
const
|
|
415
|
-
return
|
|
458
|
+
const r = JSON.parse(n);
|
|
459
|
+
return ee(r) ? r : null;
|
|
416
460
|
} catch {
|
|
417
461
|
return null;
|
|
418
462
|
}
|
|
419
463
|
}
|
|
420
|
-
function
|
|
464
|
+
function ee(n) {
|
|
421
465
|
if (typeof n != "object" || n === null)
|
|
422
466
|
return !1;
|
|
423
|
-
const
|
|
424
|
-
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";
|
|
425
469
|
}
|
|
426
|
-
function
|
|
470
|
+
function Ne(n, r, e = "key") {
|
|
427
471
|
const t = {
|
|
428
472
|
version: 1,
|
|
429
473
|
algorithm: "AES-256-GCM",
|
|
430
474
|
key: n,
|
|
431
475
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
432
|
-
},
|
|
433
|
-
|
|
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);
|
|
434
478
|
}
|
|
435
|
-
async function
|
|
436
|
-
const
|
|
437
|
-
return Array.from(t).map((
|
|
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("");
|
|
438
482
|
}
|
|
439
|
-
async function
|
|
440
|
-
const { fileName: e, onProgress: t, ...
|
|
483
|
+
async function Le(n, r) {
|
|
484
|
+
const { fileName: e, onProgress: t, ...a } = r;
|
|
441
485
|
try {
|
|
442
486
|
t == null || t({ phase: "downloading", progress: 0 });
|
|
443
487
|
const c = await fetch(n);
|
|
444
488
|
if (!c.ok)
|
|
445
|
-
throw new
|
|
489
|
+
throw new E(
|
|
446
490
|
"DOWNLOAD_FAILED",
|
|
447
491
|
`Download failed: ${c.status} ${c.statusText}`
|
|
448
492
|
);
|
|
449
|
-
const
|
|
450
|
-
let
|
|
451
|
-
|
|
493
|
+
const s = c.headers.get("content-length");
|
|
494
|
+
let i;
|
|
495
|
+
s && c.body ? i = await te(
|
|
452
496
|
c.body,
|
|
453
|
-
parseInt(
|
|
497
|
+
parseInt(s, 10),
|
|
454
498
|
(l) => {
|
|
455
499
|
t == null || t({ phase: "downloading", progress: Math.round(l * 50) });
|
|
456
500
|
}
|
|
457
|
-
) : (t == null || t({ phase: "downloading", progress: 25 }),
|
|
458
|
-
const
|
|
459
|
-
...
|
|
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,
|
|
460
504
|
onProgress: (l) => {
|
|
461
|
-
const
|
|
505
|
+
const o = 50 + Math.round(l.progress * 0.45);
|
|
462
506
|
t == null || t({
|
|
463
507
|
phase: l.phase === "complete" ? "complete" : l.phase,
|
|
464
|
-
progress: l.phase === "complete" ? 100 :
|
|
508
|
+
progress: l.phase === "complete" ? 100 : o
|
|
465
509
|
});
|
|
466
510
|
}
|
|
467
511
|
});
|
|
468
|
-
|
|
512
|
+
C(p, e), t == null || t({ phase: "complete", progress: 100 });
|
|
469
513
|
} catch (c) {
|
|
470
|
-
throw c instanceof
|
|
514
|
+
throw c instanceof E ? c : new E("DOWNLOAD_FAILED");
|
|
471
515
|
}
|
|
472
516
|
}
|
|
473
|
-
async function
|
|
474
|
-
const t = n.getReader(),
|
|
475
|
-
let c = 0,
|
|
476
|
-
for (; !
|
|
517
|
+
async function te(n, r, e) {
|
|
518
|
+
const t = n.getReader(), a = [];
|
|
519
|
+
let c = 0, s = !1;
|
|
520
|
+
for (; !s; ) {
|
|
477
521
|
const l = await t.read();
|
|
478
|
-
if (
|
|
479
|
-
|
|
480
|
-
const
|
|
481
|
-
e(Math.min(
|
|
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));
|
|
482
526
|
}
|
|
483
527
|
}
|
|
484
|
-
const
|
|
485
|
-
let
|
|
486
|
-
for (const l of
|
|
487
|
-
|
|
488
|
-
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;
|
|
489
533
|
}
|
|
490
|
-
function
|
|
534
|
+
function C(n, r) {
|
|
491
535
|
const e = URL.createObjectURL(n), t = document.createElement("a");
|
|
492
|
-
t.href = e, t.download =
|
|
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
|
+
}
|
|
493
583
|
}
|
|
494
584
|
export {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
_e as
|
|
526
|
-
|
|
527
|
-
|
|
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
|
|
528
620
|
};
|
|
529
621
|
//# sourceMappingURL=index.mjs.map
|