@zip.js/zip.js 2.5.3 → 2.5.4

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.
@@ -45,14 +45,19 @@ const SALT_LENGTH = [8, 12, 16];
45
45
  const KEY_LENGTH = [16, 24, 32];
46
46
  const SIGNATURE_LENGTH = 10;
47
47
  const COUNTER_DEFAULT_VALUE = [0, 0, 0, 0];
48
- const CRYPTO_API_SUPPORTED = typeof crypto != "undefined";
49
- const SUBTLE_API_SUPPORTED = CRYPTO_API_SUPPORTED && typeof crypto.subtle != "undefined";
48
+ const UNDEFINED_TYPE = "undefined";
49
+ const FUNCTION_TYPE = "function";
50
+ const CRYPTO_API_SUPPORTED = typeof crypto != UNDEFINED_TYPE;
51
+ const SUBTLE_API_SUPPORTED = CRYPTO_API_SUPPORTED && typeof crypto.subtle != UNDEFINED_TYPE;
52
+ const GET_RANDOM_VALUES_SUPPORTED = CRYPTO_API_SUPPORTED && typeof crypto.getRandomValues == FUNCTION_TYPE;
53
+ const IMPORT_KEY_SUPPORTED = CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && typeof crypto.subtle.importKey == FUNCTION_TYPE;
54
+ const DERIVE_BITS_SUPPORTED = CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && typeof crypto.subtle.deriveBits == FUNCTION_TYPE;
50
55
  const codecBytes = codec.bytes;
51
56
  const Aes = cipher.aes;
52
57
  const CtrGladman = mode.ctrGladman;
53
58
  const HmacSha1 = misc.hmacSha1;
54
59
 
55
- class AESDecryptStream extends TransformStream {
60
+ class AESDecryptionStream extends TransformStream {
56
61
 
57
62
  constructor(password, signed, strength) {
58
63
  let stream;
@@ -74,7 +79,7 @@ class AESDecryptStream extends TransformStream {
74
79
  aesCrypto.password = null;
75
80
  const preamble = subarray(chunk, 0, SALT_LENGTH[aesCrypto.strength] + 2);
76
81
  await createDecryptionKeys(aesCrypto, preamble, password);
77
- aesCrypto.aesCtrGladman = new CtrGladman(new Aes(aesCrypto.keys.key), Array.from(COUNTER_DEFAULT_VALUE));
82
+ aesCrypto.ctr = new CtrGladman(new Aes(aesCrypto.keys.key), Array.from(COUNTER_DEFAULT_VALUE));
78
83
  aesCrypto.hmac = new HmacSha1(aesCrypto.keys.authentication);
79
84
  chunk = subarray(chunk, SALT_LENGTH[aesCrypto.strength] + 2);
80
85
  aesCrypto.resolveReady();
@@ -93,14 +98,14 @@ class AESDecryptStream extends TransformStream {
93
98
  const originalSignature = subarray(pending, pending.length - SIGNATURE_LENGTH);
94
99
  let decryptedChunkArray = new Uint8Array(0);
95
100
  if (chunkToDecrypt.length) {
96
- const encryptedChunk = codecBytes.toBits(chunkToDecrypt);
101
+ const encryptedChunk = toBits(codecBytes, chunkToDecrypt);
97
102
  aesCrypto.hmac.update(encryptedChunk);
98
- const decryptedChunk = aesCrypto.aesCtrGladman.update(encryptedChunk);
99
- decryptedChunkArray = codecBytes.fromBits(decryptedChunk);
103
+ const decryptedChunk = aesCrypto.ctr.update(encryptedChunk);
104
+ decryptedChunkArray = fromBits(codecBytes, decryptedChunk);
100
105
  }
101
106
  stream.valid = true;
102
107
  if (aesCrypto.signed) {
103
- const signature = subarray(codecBytes.fromBits(aesCrypto.hmac.digest()), 0, SIGNATURE_LENGTH);
108
+ const signature = subarray(fromBits(codecBytes, aesCrypto.hmac.digest()), 0, SIGNATURE_LENGTH);
104
109
  for (let indexSignature = 0; indexSignature < SIGNATURE_LENGTH; indexSignature++) {
105
110
  if (signature[indexSignature] != originalSignature[indexSignature]) {
106
111
  stream.valid = false;
@@ -114,7 +119,7 @@ class AESDecryptStream extends TransformStream {
114
119
  }
115
120
  }
116
121
 
117
- class AESEncryptStream extends TransformStream {
122
+ class AESEncryptionStream extends TransformStream {
118
123
 
119
124
  constructor(password, strength) {
120
125
  let stream;
@@ -135,7 +140,7 @@ class AESEncryptStream extends TransformStream {
135
140
  const password = aesCrypto.password;
136
141
  aesCrypto.password = null;
137
142
  preamble = await createEncryptionKeys(aesCrypto, password);
138
- aesCrypto.aesCtrGladman = new CtrGladman(new Aes(aesCrypto.keys.key), Array.from(COUNTER_DEFAULT_VALUE));
143
+ aesCrypto.ctr = new CtrGladman(new Aes(aesCrypto.keys.key), Array.from(COUNTER_DEFAULT_VALUE));
139
144
  aesCrypto.hmac = new HmacSha1(aesCrypto.keys.authentication);
140
145
  aesCrypto.resolveReady();
141
146
  } else {
@@ -151,11 +156,11 @@ class AESEncryptStream extends TransformStream {
151
156
  await aesCrypto.ready;
152
157
  let encryptedChunkArray = new Uint8Array(0);
153
158
  if (aesCrypto.pending.length) {
154
- const encryptedChunk = aesCrypto.aesCtrGladman.update(codecBytes.toBits(aesCrypto.pending));
159
+ const encryptedChunk = aesCrypto.ctr.update(toBits(codecBytes, aesCrypto.pending));
155
160
  aesCrypto.hmac.update(encryptedChunk);
156
- encryptedChunkArray = codecBytes.fromBits(encryptedChunk);
161
+ encryptedChunkArray = fromBits(codecBytes, encryptedChunk);
157
162
  }
158
- stream.signature = codecBytes.fromBits(aesCrypto.hmac.digest()).slice(0, SIGNATURE_LENGTH);
163
+ stream.signature = fromBits(codecBytes, aesCrypto.hmac.digest()).slice(0, SIGNATURE_LENGTH);
159
164
  controller.enqueue(concat(encryptedChunkArray, stream.signature));
160
165
  }
161
166
  });
@@ -164,8 +169,8 @@ class AESEncryptStream extends TransformStream {
164
169
  }
165
170
 
166
171
  export {
167
- AESDecryptStream,
168
- AESEncryptStream,
172
+ AESDecryptionStream,
173
+ AESEncryptionStream,
169
174
  ERR_INVALID_PASSWORD
170
175
  };
171
176
 
@@ -177,15 +182,15 @@ function append(aesCrypto, input, output, paddingStart, paddingEnd, verifySignat
177
182
  }
178
183
  let offset;
179
184
  for (offset = 0; offset <= inputLength - BLOCK_LENGTH; offset += BLOCK_LENGTH) {
180
- const inputChunk = codecBytes.toBits(subarray(input, offset, offset + BLOCK_LENGTH));
185
+ const inputChunk = toBits(codecBytes, subarray(input, offset, offset + BLOCK_LENGTH));
181
186
  if (verifySignature) {
182
187
  aesCrypto.hmac.update(inputChunk);
183
188
  }
184
- const outputChunk = aesCrypto.aesCtrGladman.update(inputChunk);
189
+ const outputChunk = aesCrypto.ctr.update(inputChunk);
185
190
  if (!verifySignature) {
186
191
  aesCrypto.hmac.update(outputChunk);
187
192
  }
188
- output.set(codecBytes.fromBits(outputChunk), offset + paddingStart);
193
+ output.set(fromBits(codecBytes, outputChunk), offset + paddingStart);
189
194
  }
190
195
  aesCrypto.pending = subarray(input, offset);
191
196
  return output;
@@ -212,14 +217,14 @@ async function createKeys(target, password, salt) {
212
217
  const derivedBits = await deriveBits(Object.assign({ salt }, DERIVED_BITS_ALGORITHM), basekey, 8 * ((KEY_LENGTH[target.strength] * 2) + 2));
213
218
  const compositeKey = new Uint8Array(derivedBits);
214
219
  target.keys = {
215
- key: codecBytes.toBits(subarray(compositeKey, 0, KEY_LENGTH[target.strength])),
216
- authentication: codecBytes.toBits(subarray(compositeKey, KEY_LENGTH[target.strength], KEY_LENGTH[target.strength] * 2)),
220
+ key: toBits(codecBytes, subarray(compositeKey, 0, KEY_LENGTH[target.strength])),
221
+ authentication: toBits(codecBytes, subarray(compositeKey, KEY_LENGTH[target.strength], KEY_LENGTH[target.strength] * 2)),
217
222
  passwordVerification: subarray(compositeKey, KEY_LENGTH[target.strength] * 2)
218
223
  };
219
224
  }
220
225
 
221
226
  function getRandomValues(array) {
222
- if (CRYPTO_API_SUPPORTED && typeof crypto.getRandomValues == "function") {
227
+ if (GET_RANDOM_VALUES_SUPPORTED) {
223
228
  return crypto.getRandomValues(array);
224
229
  } else {
225
230
  return random.getRandomValues(array);
@@ -227,7 +232,7 @@ function getRandomValues(array) {
227
232
  }
228
233
 
229
234
  function importKey(format, password, algorithm, extractable, keyUsages) {
230
- if (CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && typeof crypto.subtle.importKey == "function") {
235
+ if (IMPORT_KEY_SUPPORTED) {
231
236
  return crypto.subtle.importKey(format, password, algorithm, extractable, keyUsages);
232
237
  } else {
233
238
  return misc.importKey(password);
@@ -235,7 +240,7 @@ function importKey(format, password, algorithm, extractable, keyUsages) {
235
240
  }
236
241
 
237
242
  async function deriveBits(algorithm, baseKey, length) {
238
- if (CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && typeof crypto.subtle.deriveBits == "function") {
243
+ if (DERIVE_BITS_SUPPORTED) {
239
244
  return await crypto.subtle.deriveBits(algorithm, baseKey, length);
240
245
  } else {
241
246
  return misc.pbkdf2(baseKey, algorithm.salt, DERIVED_BITS_ALGORITHM.iterations, length);
@@ -263,4 +268,11 @@ function expand(inputArray, length) {
263
268
 
264
269
  function subarray(array, begin, end) {
265
270
  return array.subarray(begin, end);
271
+ }
272
+
273
+ function fromBits(codecBytes, chunk) {
274
+ return codecBytes.fromBits(chunk);
275
+ }
276
+ function toBits(codecBytes, chunk) {
277
+ return codecBytes.toBits(chunk);
266
278
  }
@@ -43,13 +43,13 @@ class CodecStream extends TransformStream {
43
43
  },
44
44
  transform(chunk, controller) {
45
45
  chunk = this.codec.append(chunk);
46
- if (chunk) {
46
+ if (chunk && chunk.length) {
47
47
  controller.enqueue(chunk);
48
48
  }
49
49
  },
50
50
  flush(controller) {
51
51
  const chunk = this.codec.flush();
52
- if (chunk) {
52
+ if (chunk && chunk.length) {
53
53
  controller.enqueue(chunk);
54
54
  }
55
55
  }
@@ -30,8 +30,8 @@
30
30
  // deno-lint-ignore-file no-this-alias
31
31
 
32
32
  import Crc32Stream from "./crc32-stream.js";
33
- import { AESEncryptStream, AESDecryptStream, ERR_INVALID_PASSWORD } from "./aes-crypto-stream.js";
34
- import { ZipCryptoDecryptStream, ZipCryptoEncryptStream } from "./zip-crypto-stream.js";
33
+ import { AESEncryptionStream, AESDecryptionStream, ERR_INVALID_PASSWORD } from "./aes-crypto-stream.js";
34
+ import { ZipCryptoDecryptionStream, ZipCryptoEncryptionStream } from "./zip-crypto-stream.js";
35
35
  import CodecStream from "./codec-stream.js";
36
36
 
37
37
  const CODEC_DEFLATE = "deflate";
@@ -42,6 +42,8 @@ const MESSAGE_START = "start";
42
42
  const MESSAGE_PULL = "pull";
43
43
  const MESSAGE_DATA = "data";
44
44
  const MESSAGE_ABORT = "abort";
45
+ const COMPRESSION_FORMAT = "deflate-raw";
46
+ const UNDEFINED_TYPE = "undefined";
45
47
 
46
48
  class Inflate {
47
49
 
@@ -64,30 +66,22 @@ class Inflate {
64
66
  signed,
65
67
  compressed,
66
68
  zipCrypto,
67
- stream: new ReadableStream({
68
- async pull(controller) {
69
- const { value, done } = await codec.pull();
70
- controller.enqueue(value);
71
- if (done || codec.aborted) {
72
- controller.close();
73
- }
74
- }
75
- })
69
+ stream: createReadableStream(codec)
76
70
  });
77
71
  if (encrypted) {
78
72
  if (zipCrypto) {
79
- codec.stream = codec.stream.pipeThrough(new ZipCryptoDecryptStream(password, passwordVerification));
73
+ codec.stream = codec.stream.pipeThrough(new ZipCryptoDecryptionStream(password, passwordVerification));
80
74
  } else {
81
- codec.decryptStream = new AESDecryptStream(password, signed, encryptionStrength);
75
+ codec.decryptStream = new AESDecryptionStream(password, signed, encryptionStrength);
82
76
  codec.stream = codec.stream.pipeThrough(codec.decryptStream);
83
77
  }
84
78
  }
85
79
  if (compressed) {
86
- if ((useCompressionStream !== undefined && !useCompressionStream) || typeof DecompressionStream == "undefined") {
80
+ if ((useCompressionStream !== undefined && !useCompressionStream) || typeof DecompressionStream == UNDEFINED_TYPE) {
87
81
  pipeCodecStream();
88
82
  } else {
89
83
  try {
90
- codec.stream = codec.stream.pipeThrough(new DecompressionStream("deflate-raw"));
84
+ codec.stream = codec.stream.pipeThrough(new DecompressionStream(COMPRESSION_FORMAT));
91
85
  } catch (_error) {
92
86
  pipeCodecStream();
93
87
  }
@@ -155,15 +149,7 @@ class Deflate {
155
149
  signed,
156
150
  compressed,
157
151
  zipCrypto,
158
- stream: new ReadableStream({
159
- async pull(controller) {
160
- const { value, done } = await codec.pull();
161
- controller.enqueue(value);
162
- if (done || codec.aborted) {
163
- controller.close();
164
- }
165
- }
166
- })
152
+ stream: createReadableStream(codec)
167
153
  });
168
154
  if ((!encrypted || zipCrypto) && signed) {
169
155
  const tee = codec.stream.tee();
@@ -171,11 +157,11 @@ class Deflate {
171
157
  codec.crc32Stream = tee[1].pipeThrough(new Crc32Stream({ chunkSize }));
172
158
  }
173
159
  if (compressed) {
174
- if ((useCompressionStream !== undefined && !useCompressionStream) || typeof CompressionStream == "undefined") {
160
+ if ((useCompressionStream !== undefined && !useCompressionStream) || typeof CompressionStream == UNDEFINED_TYPE) {
175
161
  pipeCodecStream();
176
162
  } else {
177
163
  try {
178
- codec.stream = codec.stream.pipeThrough(new CompressionStream("deflate-raw"));
164
+ codec.stream = codec.stream.pipeThrough(new CompressionStream(COMPRESSION_FORMAT));
179
165
  } catch (_error) {
180
166
  pipeCodecStream();
181
167
  }
@@ -183,9 +169,9 @@ class Deflate {
183
169
  }
184
170
  if (encrypted) {
185
171
  if (zipCrypto) {
186
- codec.stream = codec.stream.pipeThrough(new ZipCryptoEncryptStream(password, passwordVerification));
172
+ codec.stream = codec.stream.pipeThrough(new ZipCryptoEncryptionStream(password, passwordVerification));
187
173
  } else {
188
- codec.encryptStream = new AESEncryptStream(password, encryptionStrength);
174
+ codec.encryptStream = new AESEncryptionStream(password, encryptionStrength);
189
175
  codec.stream = codec.stream.pipeThrough(codec.encryptStream);
190
176
  }
191
177
  }
@@ -243,4 +229,18 @@ function createCodec(codecConstructor, options, config) {
243
229
  } else if (options.codecType.startsWith(CODEC_INFLATE)) {
244
230
  return new Inflate(codecConstructor, options, config);
245
231
  }
232
+ }
233
+
234
+ function createReadableStream(codec) {
235
+ return new ReadableStream({
236
+ async pull(controller) {
237
+ const { value, done } = await codec.pull();
238
+ if (value) {
239
+ controller.enqueue(value);
240
+ }
241
+ if (done || codec.aborted) {
242
+ controller.close();
243
+ }
244
+ }
245
+ });
246
246
  }
@@ -37,7 +37,7 @@ class Crc32Stream extends TransformStream {
37
37
  this.crc32 = new Crc32();
38
38
  },
39
39
  transform(chunk) {
40
- if (chunk) {
40
+ if (chunk && chunk.length) {
41
41
  this.crc32.append(chunk);
42
42
  }
43
43
  },
@@ -34,7 +34,7 @@ import { ERR_INVALID_PASSWORD } from "./aes-crypto-stream.js";
34
34
 
35
35
  const HEADER_LENGTH = 12;
36
36
 
37
- class ZipCryptoDecryptStream extends TransformStream {
37
+ class ZipCryptoDecryptionStream extends TransformStream {
38
38
 
39
39
  constructor(password, passwordVerification) {
40
40
  let stream;
@@ -68,7 +68,7 @@ class ZipCryptoDecryptStream extends TransformStream {
68
68
  }
69
69
  }
70
70
 
71
- class ZipCryptoEncryptStream extends TransformStream {
71
+ class ZipCryptoEncryptionStream extends TransformStream {
72
72
 
73
73
  constructor(password, passwordVerification) {
74
74
  super({
@@ -106,8 +106,8 @@ class ZipCryptoEncryptStream extends TransformStream {
106
106
  }
107
107
 
108
108
  export {
109
- ZipCryptoDecryptStream,
110
- ZipCryptoEncryptStream,
109
+ ZipCryptoDecryptionStream,
110
+ ZipCryptoEncryptionStream,
111
111
  ERR_INVALID_PASSWORD
112
112
  };
113
113
 
@@ -28,6 +28,7 @@
28
28
 
29
29
  /* global navigator */
30
30
 
31
+ const MINIMUM_CHUNK_SIZE = 64;
31
32
  const DEFAULT_CONFIGURATION = {
32
33
  chunkSize: 512 * 1024,
33
34
  maxWorkers: (typeof navigator != "undefined" && navigator.hardwareConcurrency) || 2,
@@ -40,13 +41,18 @@ const config = Object.assign({}, DEFAULT_CONFIGURATION);
40
41
 
41
42
  export {
42
43
  configure,
43
- getConfiguration
44
+ getConfiguration,
45
+ getChunkSize
44
46
  };
45
47
 
46
48
  function getConfiguration() {
47
49
  return config;
48
50
  }
49
51
 
52
+ function getChunkSize(config) {
53
+ return Math.max(config.chunkSize, MINIMUM_CHUNK_SIZE);
54
+ }
55
+
50
56
  function configure(configuration) {
51
57
  if (configuration.baseURL !== undefined) {
52
58
  config.baseURL = configuration.baseURL;
@@ -26,7 +26,7 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- const MINIMUM_CHUNK_SIZE = 64;
29
+ // const MINIMUM_CHUNK_SIZE = 64;
30
30
  const ERR_ABORT = "Abort error";
31
31
 
32
32
  export {
@@ -34,39 +34,35 @@ export {
34
34
  processData
35
35
  };
36
36
 
37
- async function processData(codec, reader, writer, offset, inputLengthGetter, config, options) {
38
- const chunkSize = Math.max(config.chunkSize, MINIMUM_CHUNK_SIZE);
39
- const signal = options.signal;
37
+ async function processData(codec, reader, writer, size, { signal, onprogress }) {
40
38
  let length = 0;
41
39
  let chunkOffset = 0;
42
40
 
43
41
  const result = new Promise((resolve, reject) => {
44
42
  codec.pull = async () => {
45
43
  testAborted(signal, codec);
46
- const inputLength = inputLengthGetter();
47
- let currentChunkOffset = chunkOffset;
48
- chunkOffset += chunkSize;
49
- const value = await reader.readUint8Array(currentChunkOffset + offset, Math.min(chunkSize, inputLength - currentChunkOffset));
50
- const done = chunkOffset > inputLength;
51
- return { value, done };
44
+ const result = await reader.read();
45
+ chunkOffset += result.length;
46
+ return result;
52
47
  };
53
48
  codec.ondata = async ({ value, done }) => {
54
49
  try {
55
50
  testAborted(signal, codec);
56
- const inputLength = inputLengthGetter();
57
51
  const { data, signature } = value;
58
52
  if (data && data.length) {
59
53
  length += data.length;
60
- await writer.writeUint8Array(data);
54
+ await writer.ready;
55
+ await writer.write(data);
61
56
  }
62
- if (options.onprogress) {
57
+ if (onprogress) {
63
58
  try {
64
- options.onprogress(chunkOffset, inputLength);
59
+ onprogress(chunkOffset, size());
65
60
  } catch (error) {
66
61
  // ignored
67
62
  }
68
63
  }
69
64
  if (done) {
65
+ await writer.ready;
70
66
  resolve({ signature, length });
71
67
  }
72
68
  } catch (error) {