@zip.js/zip.js 2.13.0 → 2.14.0

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.
Files changed (50) hide show
  1. package/BENCHMARKS.md +46 -1
  2. package/deno.json +1 -1
  3. package/dist/zip-core-external.js +594 -935
  4. package/dist/zip-core-external.min.js +1 -1
  5. package/dist/zip-core.js +461 -908
  6. package/dist/zip-core.min.js +1 -1
  7. package/dist/zip-fs-core-external.js +601 -938
  8. package/dist/zip-fs-core-external.min.js +1 -1
  9. package/dist/zip-fs-core.js +468 -911
  10. package/dist/zip-fs-core.min.js +1 -1
  11. package/dist/zip-fs-external.js +601 -938
  12. package/dist/zip-fs-external.min.js +1 -1
  13. package/dist/zip-fs-native.js +470 -913
  14. package/dist/zip-fs-native.min.js +1 -1
  15. package/dist/zip-fs.js +604 -941
  16. package/dist/zip-fs.min.js +1 -1
  17. package/dist/zip-legacy.js +463 -910
  18. package/dist/zip-legacy.min.js +1 -1
  19. package/dist/zip-module.wasm +0 -0
  20. package/dist/zip-native.js +463 -910
  21. package/dist/zip-native.min.js +1 -1
  22. package/dist/zip-web-worker-native.js +1 -1
  23. package/dist/zip-web-worker.js +1 -1
  24. package/dist/zip.js +597 -938
  25. package/dist/zip.min.js +1 -1
  26. package/index-native.cjs +470 -913
  27. package/index-native.min.js +1 -1
  28. package/index.cjs +604 -941
  29. package/index.d.cts +58 -12
  30. package/index.d.ts +58 -12
  31. package/index.min.js +1 -1
  32. package/lib/core/codec-worker-web.js +35 -11
  33. package/lib/core/codec-worker.js +33 -23
  34. package/lib/core/io.js +29 -21
  35. package/lib/core/streams/aes-crypto-stream.js +58 -99
  36. package/lib/core/streams/codecs/aes-hmac-sha1.js +348 -0
  37. package/lib/core/streams/zlib-wasm/aes-hmac-sha1-wasm.js +106 -0
  38. package/lib/core/streams/zlib-wasm/zlib-streams-loader.js +4 -0
  39. package/lib/core/streams/zlib-wasm/zlib-streams.wasm +0 -0
  40. package/lib/core/version.js +1 -1
  41. package/lib/core/web-worker-base.js +15 -9
  42. package/lib/core/web-worker-inline-native.js +1 -1
  43. package/lib/core/web-worker-inline-wasm.js +1 -1
  44. package/lib/core/web-worker-wasm.js +2 -0
  45. package/lib/core/zip-fs.js +7 -3
  46. package/lib/core/zip-writer.js +1 -2
  47. package/lib/core/zlib-streams-inline.js +1 -1
  48. package/lib/zip-module-wasm-base.js +3 -1
  49. package/package.json +1 -1
  50. package/lib/core/streams/codecs/sjcl.js +0 -795
@@ -573,7 +573,7 @@
573
573
  T[k][n] = (previous >>> 8) ^ T[0][previous & 0xFF];
574
574
  }
575
575
  }
576
- const [T0, T1, T2, T3, T4, T5, T6, T7] = T;
576
+ const [T0$1, T1$1, T2$1, T3$1, T4, T5, T6, T7] = T;
577
577
 
578
578
  class Crc32 {
579
579
 
@@ -595,12 +595,12 @@
595
595
  const a = crc ^ view.getInt32(offset, true);
596
596
  const b = view.getInt32(offset + 4, true);
597
597
  crc = T7[a & 0xFF] ^ T6[(a >>> 8) & 0xFF] ^ T5[(a >>> 16) & 0xFF] ^ T4[(a >>> 24) & 0xFF] ^
598
- T3[b & 0xFF] ^ T2[(b >>> 8) & 0xFF] ^ T1[(b >>> 16) & 0xFF] ^ T0[(b >>> 24) & 0xFF];
598
+ T3$1[b & 0xFF] ^ T2$1[(b >>> 8) & 0xFF] ^ T1$1[(b >>> 16) & 0xFF] ^ T0$1[(b >>> 24) & 0xFF];
599
599
  }
600
600
  }
601
601
  // Remaining tail (and non-typed inputs) byte-at-a-time with the base table.
602
602
  for (; offset < length; offset++) {
603
- crc = (crc >>> 8) ^ T0[(crc ^ data[offset]) & 0xFF];
603
+ crc = (crc >>> 8) ^ T0$1[(crc ^ data[offset]) & 0xFF];
604
604
  }
605
605
  this.crc = crc;
606
606
  }
@@ -704,794 +704,349 @@
704
704
  }
705
705
  }
706
706
 
707
- // Derived from https://github.com/xqdoo00o/jszip/blob/master/lib/sjcl.js and https://github.com/bitwiseshiftleft/sjcl
708
-
709
- // deno-lint-ignore-file no-this-alias
710
-
711
707
  /*
712
- * SJCL is open. You can use, modify and redistribute it under a BSD
713
- * license or under the GNU GPL, version 2.0.
714
- */
715
-
716
- /** @fileOverview Javascript cryptography implementation.
717
- *
718
- * Crush to remove comments, shorten variable names and
719
- * generally reduce transmission size.
720
- *
721
- * @author Emily Stark
722
- * @author Mike Hamburg
723
- * @author Dan Boneh
724
- */
725
-
726
- /*jslint indent: 2, bitwise: false, nomen: false, plusplus: false, white: false, regexp: false */
727
-
728
- /** @fileOverview Arrays of bits, encoded as arrays of Numbers.
729
- *
730
- * @author Emily Stark
731
- * @author Mike Hamburg
732
- * @author Dan Boneh
733
- */
734
-
735
- /**
736
- * Arrays of bits, encoded as arrays of Numbers.
737
- * @namespace
738
- * @description
739
- * <p>
740
- * These objects are the currency accepted by SJCL's crypto functions.
741
- * </p>
742
- *
743
- * <p>
744
- * Most of our crypto primitives operate on arrays of 4-byte words internally,
745
- * but many of them can take arguments that are not a multiple of 4 bytes.
746
- * This library encodes arrays of bits (whose size need not be a multiple of 8
747
- * bits) as arrays of 32-bit words. The bits are packed, big-endian, into an
748
- * array of words, 32 bits at a time. Since the words are double-precision
749
- * floating point numbers, they fit some extra data. We use this (in a private,
750
- * possibly-changing manner) to encode the number of bits actually present
751
- * in the last word of the array.
752
- * </p>
753
- *
754
- * <p>
755
- * Because bitwise ops clear this out-of-band data, these arrays can be passed
756
- * to ciphers like AES which want arrays of words.
757
- * </p>
758
- */
759
- const bitArray = {
760
- /**
761
- * Concatenate two bit arrays.
762
- * @param {bitArray} a1 The first array.
763
- * @param {bitArray} a2 The second array.
764
- * @return {bitArray} The concatenation of a1 and a2.
765
- */
766
- concat(a1, a2) {
767
- if (a1.length === 0 || a2.length === 0) {
768
- return a1.concat(a2);
769
- }
770
-
771
- const last = a1[a1.length - 1], shift = bitArray.getPartial(last);
772
- if (shift === 32) {
773
- return a1.concat(a2);
774
- } else {
775
- return bitArray._shiftRight(a2, shift, last | 0, a1.slice(0, a1.length - 1));
776
- }
777
- },
778
-
779
- /**
780
- * Find the length of an array of bits.
781
- * @param {bitArray} a The array.
782
- * @return {Number} The length of a, in bits.
783
- */
784
- bitLength(a) {
785
- const l = a.length;
786
- if (l === 0) {
787
- return 0;
788
- }
789
- const x = a[l - 1];
790
- return (l - 1) * 32 + bitArray.getPartial(x);
791
- },
792
-
793
- /**
794
- * Truncate an array.
795
- * @param {bitArray} a The array.
796
- * @param {Number} len The length to truncate to, in bits.
797
- * @return {bitArray} A new array, truncated to len bits.
798
- */
799
- clamp(a, len) {
800
- if (a.length * 32 < len) {
801
- return a;
802
- }
803
- a = a.slice(0, Math.ceil(len / 32));
804
- const l = a.length;
805
- len = len & 31;
806
- if (l > 0 && len) {
807
- a[l - 1] = bitArray.partial(len, a[l - 1] & 0x80000000 >> (len - 1), 1);
808
- }
809
- return a;
810
- },
811
-
812
- /**
813
- * Make a partial word for a bit array.
814
- * @param {Number} len The number of bits in the word.
815
- * @param {Number} x The bits.
816
- * @param {Number} [_end=0] Pass 1 if x has already been shifted to the high side.
817
- * @return {Number} The partial word.
818
- */
819
- partial(len, x, _end) {
820
- if (len === 32) {
821
- return x;
822
- }
823
- return (_end ? x | 0 : x << (32 - len)) + len * 0x10000000000;
824
- },
708
+ Copyright (c) 2026 Gildas Lormeau. All rights reserved.
825
709
 
826
- /**
827
- * Get the number of bits used by a partial word.
828
- * @param {Number} x The partial word.
829
- * @return {Number} The number of bits used by the partial word.
830
- */
831
- getPartial(x) {
832
- return Math.round(x / 0x10000000000) || 32;
833
- },
710
+ Redistribution and use in source and binary forms, with or without
711
+ modification, are permitted provided that the following conditions are met:
834
712
 
835
- /** Shift an array right.
836
- * @param {bitArray} a The array to shift.
837
- * @param {Number} shift The number of bits to shift.
838
- * @param {Number} [carry=0] A byte to carry in
839
- * @param {bitArray} [out=[]] An array to prepend to the output.
840
- * @private
841
- */
842
- _shiftRight(a, shift, carry, out) {
843
- if (out === undefined) {
844
- out = [];
845
- }
713
+ 1. Redistributions of source code must retain the above copyright notice,
714
+ this list of conditions and the following disclaimer.
846
715
 
847
- for (; shift >= 32; shift -= 32) {
848
- out.push(carry);
849
- carry = 0;
850
- }
851
- if (shift === 0) {
852
- return out.concat(a);
853
- }
716
+ 2. Redistributions in binary form must reproduce the above copyright
717
+ notice, this list of conditions and the following disclaimer in
718
+ the documentation and/or other materials provided with the distribution.
854
719
 
855
- for (let i = 0; i < a.length; i++) {
856
- out.push(carry | a[i] >>> shift);
857
- carry = a[i] << (32 - shift);
858
- }
859
- const last2 = a.length ? a[a.length - 1] : 0;
860
- const shift2 = bitArray.getPartial(last2);
861
- out.push(bitArray.partial(shift + shift2 & 31, (shift + shift2 > 32) ? carry : out.pop(), 1));
862
- return out;
863
- }
864
- };
720
+ 3. The names of the authors may not be used to endorse or promote products
721
+ derived from this software without specific prior written permission.
865
722
 
866
- /** @fileOverview Bit array codec implementations.
867
- *
868
- * @author Emily Stark
869
- * @author Mike Hamburg
870
- * @author Dan Boneh
723
+ THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
724
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
725
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
726
+ INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
727
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
728
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
729
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
730
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
731
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
732
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
871
733
  */
872
734
 
873
- /**
874
- * Arrays of bytes
875
- * @namespace
876
- */
877
- const codec = {
878
- bytes: {
879
- /** Convert from a bitArray to an array of bytes. */
880
- fromBits(arr) {
881
- const bl = bitArray.bitLength(arr);
882
- const byteLength = bl / 8;
883
- const out = new Uint8Array(byteLength);
884
- let tmp;
885
- for (let i = 0; i < byteLength; i++) {
886
- if ((i & 3) === 0) {
887
- tmp = arr[i / 4];
888
- }
889
- out[i] = tmp >>> 24;
890
- tmp <<= 8;
891
- }
892
- return out;
893
- },
894
- /** Convert from an array of bytes to a bitArray. */
895
- toBits(bytes) {
896
- const out = [];
897
- let i;
898
- let tmp = 0;
899
- for (i = 0; i < bytes.length; i++) {
900
- tmp = tmp << 8 | bytes[i];
901
- if ((i & 3) === 3) {
902
- out.push(tmp);
903
- tmp = 0;
904
- }
735
+ const BLOCK_LENGTH$1 = 16;
736
+ const ROUND_KEYS_LENGTH = 60;
737
+ const SHA1_BLOCK_LENGTH = 64;
738
+ const SHA1_DIGEST_LENGTH = 20;
739
+ const SHA1_SCHEDULE_LENGTH = 80;
740
+ const SHA1_LENGTH_OFFSET = 56;
741
+ const SHA1_PADDING = new Uint8Array([0x80]);
742
+ const SHA1_ZERO = new Uint8Array(1);
743
+ const SHA1_INITIAL_STATE = new Int32Array([0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]);
744
+ const HMAC_INNER_PADDING = 0x36;
745
+ const HMAC_OUTER_PADDING = 0x5c;
746
+ const S_BOX = new Uint8Array(256);
747
+ const T0 = new Int32Array(256);
748
+ const T1 = new Int32Array(256);
749
+ const T2 = new Int32Array(256);
750
+ const T3 = new Int32Array(256);
751
+
752
+ let tablesInitialized = false;
753
+
754
+ function createEngine$1(key, authenticationKey) {
755
+ initTables();
756
+ const roundKeys = new Int32Array(ROUND_KEYS_LENGTH);
757
+ const rounds = expandKey(key, roundKeys);
758
+ const counter = new Uint8Array(BLOCK_LENGTH$1);
759
+ const keystream = new Int32Array(BLOCK_LENGTH$1 / 4);
760
+ const hmac = createHmac(authenticationKey);
761
+ return {
762
+ process(data, decrypt) {
763
+ if (decrypt) {
764
+ hmac.update(data, 0, data.length);
905
765
  }
906
- if (i & 3) {
907
- out.push(bitArray.partial(8 * (i & 3), tmp));
766
+ encrypt(data);
767
+ if (!decrypt) {
768
+ hmac.update(data, 0, data.length);
908
769
  }
909
- return out;
910
- }
911
- }
912
- };
913
-
914
- const hash = {};
915
-
916
- /**
917
- * Context for a SHA-1 operation in progress.
918
- * @constructor
919
- */
920
- hash.sha1 = class {
921
- constructor(hash) {
922
- const sha1 = this;
923
- /**
924
- * The hash's block size, in bits.
925
- * @constant
926
- */
927
- sha1.blockSize = 512;
928
- /**
929
- * The SHA-1 initialization vector.
930
- * @private
931
- */
932
- sha1._init = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0];
933
- /**
934
- * The SHA-1 hash key.
935
- * @private
936
- */
937
- sha1._key = [0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6];
938
- if (hash) {
939
- sha1._h = hash._h.slice(0);
940
- sha1._buffer = hash._buffer.slice(0);
941
- sha1._length = hash._length;
942
- } else {
943
- sha1.reset();
944
- }
945
- }
946
-
947
- /**
948
- * Reset the hash state.
949
- * @return this
950
- */
951
- reset() {
952
- const sha1 = this;
953
- sha1._h = sha1._init.slice(0);
954
- sha1._buffer = [];
955
- sha1._length = 0;
956
- return sha1;
957
- }
958
-
959
- /**
960
- * Input several words to the hash.
961
- * @param {bitArray|String} data the data to hash.
962
- * @return this
963
- */
964
- update(data) {
965
- const sha1 = this;
966
- if (typeof data === "string") {
967
- data = codec.utf8String.toBits(data);
968
- }
969
- const b = sha1._buffer = bitArray.concat(sha1._buffer, data);
970
- const ol = sha1._length;
971
- const nl = sha1._length = ol + bitArray.bitLength(data);
972
- if (nl > 9007199254740991) {
973
- throw new Error("Cannot hash more than 2^53 - 1 bits");
974
- }
975
- const c = new Uint32Array(b);
976
- let j = 0;
977
- for (let i = sha1.blockSize + ol - ((sha1.blockSize + ol) & (sha1.blockSize - 1)); i <= nl;
978
- i += sha1.blockSize) {
979
- sha1._block(c.subarray(16 * j, 16 * (j + 1)));
980
- j += 1;
981
- }
982
- b.splice(0, 16 * j);
983
- return sha1;
984
- }
985
-
986
- /**
987
- * Complete hashing and output the hash value.
988
- * @return {bitArray} The hash value, an array of 5 big-endian words. TODO
989
- */
990
- finalize() {
991
- const sha1 = this;
992
- let b = sha1._buffer;
993
- const h = sha1._h;
994
-
995
- // Round out and push the buffer
996
- b = bitArray.concat(b, [bitArray.partial(1, 1)]);
997
- // Round out the buffer to a multiple of 16 words, less the 2 length words.
998
- for (let i = b.length + 2; i & 15; i++) {
999
- b.push(0);
1000
- }
1001
-
1002
- // append the length
1003
- b.push(Math.floor(sha1._length / 0x100000000));
1004
- b.push(sha1._length | 0);
1005
-
1006
- while (b.length) {
1007
- sha1._block(b.splice(0, 16));
1008
- }
1009
-
1010
- sha1.reset();
1011
- return h;
1012
- }
1013
-
1014
- /**
1015
- * The SHA-1 logical functions f(0), f(1), ..., f(79).
1016
- * @private
1017
- */
1018
- _f(t, b, c, d) {
1019
- if (t <= 19) {
1020
- return (b & c) | (~b & d);
1021
- } else if (t <= 39) {
1022
- return b ^ c ^ d;
1023
- } else if (t <= 59) {
1024
- return (b & c) | (b & d) | (c & d);
1025
- } else if (t <= 79) {
1026
- return b ^ c ^ d;
1027
- }
1028
- }
1029
-
1030
- /**
1031
- * Circular left-shift operator.
1032
- * @private
1033
- */
1034
- _S(n, x) {
1035
- return (x << n) | (x >>> 32 - n);
1036
- }
1037
-
1038
- /**
1039
- * Perform one cycle of SHA-1.
1040
- * @param {Uint32Array|bitArray} words one block of words.
1041
- * @private
1042
- */
1043
- _block(words) {
1044
- const sha1 = this;
1045
- const h = sha1._h;
1046
- // When words is passed to _block, it has 16 elements. SHA1 _block
1047
- // function extends words with new elements (at the end there are 80 elements).
1048
- // The problem is that if we use Uint32Array instead of Array,
1049
- // the length of Uint32Array cannot be changed. Thus, we replace words with a
1050
- // normal Array here.
1051
- const w = Array(80); // do not use Uint32Array here as the instantiation is slower
1052
- for (let j = 0; j < 16; j++) {
1053
- w[j] = words[j];
1054
- }
1055
-
1056
- let a = h[0];
1057
- let b = h[1];
1058
- let c = h[2];
1059
- let d = h[3];
1060
- let e = h[4];
1061
-
1062
- for (let t = 0; t <= 79; t++) {
1063
- if (t >= 16) {
1064
- w[t] = sha1._S(1, w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]);
1065
- }
1066
- const tmp = (sha1._S(5, a) + sha1._f(t, b, c, d) + e + w[t] +
1067
- sha1._key[Math.floor(t / 20)]) | 0;
1068
- e = d;
1069
- d = c;
1070
- c = sha1._S(30, b);
1071
- b = a;
1072
- a = tmp;
770
+ },
771
+ digest() {
772
+ return hmac.digest();
1073
773
  }
774
+ };
1074
775
 
1075
- h[0] = (h[0] + a) | 0;
1076
- h[1] = (h[1] + b) | 0;
1077
- h[2] = (h[2] + c) | 0;
1078
- h[3] = (h[3] + d) | 0;
1079
- h[4] = (h[4] + e) | 0;
776
+ function encrypt(data) {
777
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
778
+ const length = data.length;
779
+ let offset = 0;
780
+ for (; offset + BLOCK_LENGTH$1 <= length; offset += BLOCK_LENGTH$1) {
781
+ nextKeystream();
782
+ view.setInt32(offset, view.getInt32(offset) ^ keystream[0]);
783
+ view.setInt32(offset + 4, view.getInt32(offset + 4) ^ keystream[1]);
784
+ view.setInt32(offset + 8, view.getInt32(offset + 8) ^ keystream[2]);
785
+ view.setInt32(offset + 12, view.getInt32(offset + 12) ^ keystream[3]);
786
+ }
787
+ if (offset < length) {
788
+ nextKeystream();
789
+ for (let indexByte = 0; offset < length; offset++, indexByte++) {
790
+ data[offset] ^= keystream[indexByte >> 2] >>> (24 - 8 * (indexByte & 3));
791
+ }
792
+ }
793
+ }
794
+
795
+ function nextKeystream() {
796
+ for (let indexByte = 0; indexByte < BLOCK_LENGTH$1; indexByte++) {
797
+ counter[indexByte]++;
798
+ if (counter[indexByte] !== 0) {
799
+ break;
800
+ }
801
+ }
802
+ let s0 = ((counter[0] << 24) | (counter[1] << 16) | (counter[2] << 8) | counter[3]) ^ roundKeys[0];
803
+ let s1 = ((counter[4] << 24) | (counter[5] << 16) | (counter[6] << 8) | counter[7]) ^ roundKeys[1];
804
+ let s2 = ((counter[8] << 24) | (counter[9] << 16) | (counter[10] << 8) | counter[11]) ^ roundKeys[2];
805
+ let s3 = ((counter[12] << 24) | (counter[13] << 16) | (counter[14] << 8) | counter[15]) ^ roundKeys[3];
806
+ let indexKey = 4;
807
+ for (let round = 1; round < rounds; round++, indexKey += 4) {
808
+ const t0 = T0[s0 >>> 24] ^ T1[(s1 >>> 16) & 255] ^ T2[(s2 >>> 8) & 255] ^ T3[s3 & 255] ^ roundKeys[indexKey];
809
+ const t1 = T0[s1 >>> 24] ^ T1[(s2 >>> 16) & 255] ^ T2[(s3 >>> 8) & 255] ^ T3[s0 & 255] ^ roundKeys[indexKey + 1];
810
+ const t2 = T0[s2 >>> 24] ^ T1[(s3 >>> 16) & 255] ^ T2[(s0 >>> 8) & 255] ^ T3[s1 & 255] ^ roundKeys[indexKey + 2];
811
+ const t3 = T0[s3 >>> 24] ^ T1[(s0 >>> 16) & 255] ^ T2[(s1 >>> 8) & 255] ^ T3[s2 & 255] ^ roundKeys[indexKey + 3];
812
+ s0 = t0;
813
+ s1 = t1;
814
+ s2 = t2;
815
+ s3 = t3;
816
+ }
817
+ keystream[0] = ((S_BOX[s0 >>> 24] << 24) | (S_BOX[(s1 >>> 16) & 255] << 16) | (S_BOX[(s2 >>> 8) & 255] << 8) | S_BOX[s3 & 255]) ^ roundKeys[indexKey];
818
+ keystream[1] = ((S_BOX[s1 >>> 24] << 24) | (S_BOX[(s2 >>> 16) & 255] << 16) | (S_BOX[(s3 >>> 8) & 255] << 8) | S_BOX[s0 & 255]) ^ roundKeys[indexKey + 1];
819
+ keystream[2] = ((S_BOX[s2 >>> 24] << 24) | (S_BOX[(s3 >>> 16) & 255] << 16) | (S_BOX[(s0 >>> 8) & 255] << 8) | S_BOX[s1 & 255]) ^ roundKeys[indexKey + 2];
820
+ keystream[3] = ((S_BOX[s3 >>> 24] << 24) | (S_BOX[(s0 >>> 16) & 255] << 16) | (S_BOX[(s1 >>> 8) & 255] << 8) | S_BOX[s2 & 255]) ^ roundKeys[indexKey + 3];
821
+ }
822
+ }
823
+
824
+ function pbkdf2(password, salt, iterations, length) {
825
+ const hmac = createHmac(password);
826
+ const result = new Uint8Array(length);
827
+ const block = new Uint8Array(salt.length + 4);
828
+ const blockView = new DataView(block.buffer);
829
+ block.set(salt);
830
+ for (let indexBlock = 1, offset = 0; offset < length; indexBlock++, offset += SHA1_DIGEST_LENGTH) {
831
+ blockView.setUint32(salt.length, indexBlock);
832
+ hmac.update(block, 0, block.length);
833
+ let previous = hmac.digest();
834
+ const output = previous.slice();
835
+ for (let iteration = 1; iteration < iterations; iteration++) {
836
+ hmac.update(previous, 0, SHA1_DIGEST_LENGTH);
837
+ previous = hmac.digest();
838
+ for (let indexByte = 0; indexByte < SHA1_DIGEST_LENGTH; indexByte++) {
839
+ output[indexByte] ^= previous[indexByte];
840
+ }
841
+ }
842
+ result.set(output.subarray(0, Math.min(SHA1_DIGEST_LENGTH, length - offset)), offset);
1080
843
  }
1081
- };
1082
-
1083
- /** @fileOverview Low-level AES implementation.
1084
- *
1085
- * This file contains a low-level implementation of AES, optimized for
1086
- * size and for efficiency on several browsers. It is based on
1087
- * OpenSSL's aes_core.c, a public-domain implementation by Vincent
1088
- * Rijmen, Antoon Bosselaers and Paulo Barreto.
1089
- *
1090
- * An older version of this implementation is available in the public
1091
- * domain, but this one is (c) Emily Stark, Mike Hamburg, Dan Boneh,
1092
- * Stanford University 2008-2010 and BSD-licensed for liability
1093
- * reasons.
1094
- *
1095
- * @author Emily Stark
1096
- * @author Mike Hamburg
1097
- * @author Dan Boneh
1098
- */
1099
-
1100
- const cipher = {};
1101
-
1102
- /**
1103
- * Schedule out an AES key for both encryption and decryption. This
1104
- * is a low-level class. Use a cipher mode to do bulk encryption.
1105
- *
1106
- * @constructor
1107
- * @param {Array} key The key as an array of 4, 6 or 8 words.
1108
- */
1109
- cipher.aes = class {
1110
- constructor(key) {
1111
- /**
1112
- * The expanded S-box and inverse S-box tables. These will be computed
1113
- * on the client so that we don't have to send them down the wire.
1114
- *
1115
- * There are two tables, _tables[0] is for encryption and
1116
- * _tables[1] is for decryption.
1117
- *
1118
- * The first 4 sub-tables are the expanded S-box with MixColumns. The
1119
- * last (_tables[01][4]) is the S-box itself.
1120
- *
1121
- * @private
1122
- */
1123
- const aes = this;
1124
- aes._tables = [[[], [], [], [], []], [[], [], [], [], []]];
1125
-
1126
- if (!aes._tables[0][0][0]) {
1127
- aes._precompute();
1128
- }
1129
-
1130
- const sbox = aes._tables[0][4];
1131
- const decTable = aes._tables[1];
1132
- const keyLen = key.length;
1133
-
1134
- let i, encKey, decKey, rcon = 1;
1135
-
1136
- if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) {
1137
- throw new Error("invalid aes key size");
1138
- }
1139
-
1140
- aes._key = [encKey = key.slice(0), decKey = []];
1141
-
1142
- // schedule encryption keys
1143
- for (i = keyLen; i < 4 * keyLen + 28; i++) {
1144
- let tmp = encKey[i - 1];
1145
-
1146
- // apply sbox
1147
- if (i % keyLen === 0 || (keyLen === 8 && i % keyLen === 4)) {
1148
- tmp = sbox[tmp >>> 24] << 24 ^ sbox[tmp >> 16 & 255] << 16 ^ sbox[tmp >> 8 & 255] << 8 ^ sbox[tmp & 255];
1149
-
1150
- // shift rows and add rcon
1151
- if (i % keyLen === 0) {
1152
- tmp = tmp << 8 ^ tmp >>> 24 ^ rcon << 24;
1153
- rcon = rcon << 1 ^ (rcon >> 7) * 283;
1154
- }
1155
- }
1156
-
1157
- encKey[i] = encKey[i - keyLen] ^ tmp;
1158
- }
844
+ return result;
845
+ }
1159
846
 
1160
- // schedule decryption keys
1161
- for (let j = 0; i; j++, i--) {
1162
- const tmp = encKey[j & 3 ? i : i - 4];
1163
- if (i <= 4 || j < 4) {
1164
- decKey[j] = tmp;
1165
- } else {
1166
- decKey[j] = decTable[0][sbox[tmp >>> 24]] ^
1167
- decTable[1][sbox[tmp >> 16 & 255]] ^
1168
- decTable[2][sbox[tmp >> 8 & 255]] ^
1169
- decTable[3][sbox[tmp & 255]];
1170
- }
1171
- }
1172
- }
1173
- // public
1174
- /* Something like this might appear here eventually
1175
- name: "AES",
1176
- blockSize: 4,
1177
- keySizes: [4,6,8],
1178
- */
1179
-
1180
- /**
1181
- * Encrypt an array of 4 big-endian words.
1182
- * @param {Array} data The plaintext.
1183
- * @return {Array} The ciphertext.
1184
- */
1185
- encrypt(data) {
1186
- return this._crypt(data, 0);
1187
- }
1188
-
1189
- /**
1190
- * Decrypt an array of 4 big-endian words.
1191
- * @param {Array} data The ciphertext.
1192
- * @return {Array} The plaintext.
1193
- */
1194
- decrypt(data) {
1195
- return this._crypt(data, 1);
1196
- }
1197
-
1198
- /**
1199
- * Expand the S-box tables.
1200
- *
1201
- * @private
1202
- */
1203
- _precompute() {
1204
- const encTable = this._tables[0];
1205
- const decTable = this._tables[1];
1206
- const sbox = encTable[4];
1207
- const sboxInv = decTable[4];
1208
- const d = [];
1209
- const th = [];
1210
- let xInv, x2, x4, x8;
1211
-
1212
- // Compute double and third tables
1213
- for (let i = 0; i < 256; i++) {
1214
- th[(d[i] = i << 1 ^ (i >> 7) * 283) ^ i] = i;
1215
- }
1216
-
1217
- for (let x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) {
1218
- // Compute sbox
1219
- let s = xInv ^ xInv << 1 ^ xInv << 2 ^ xInv << 3 ^ xInv << 4;
1220
- s = s >> 8 ^ s & 255 ^ 99;
1221
- sbox[x] = s;
1222
- sboxInv[s] = x;
1223
-
1224
- // Compute MixColumns
1225
- x8 = d[x4 = d[x2 = d[x]]];
1226
- let tDec = x8 * 0x1010101 ^ x4 * 0x10001 ^ x2 * 0x101 ^ x * 0x1010100;
1227
- let tEnc = d[s] * 0x101 ^ s * 0x1010100;
1228
-
1229
- for (let i = 0; i < 4; i++) {
1230
- encTable[i][x] = tEnc = tEnc << 24 ^ tEnc >>> 8;
1231
- decTable[i][s] = tDec = tDec << 24 ^ tDec >>> 8;
1232
- }
1233
- }
1234
-
1235
- // Compactify. Considerable speedup on Firefox.
1236
- for (let i = 0; i < 5; i++) {
1237
- encTable[i] = encTable[i].slice(0);
1238
- decTable[i] = decTable[i].slice(0);
1239
- }
1240
- }
1241
-
1242
- /**
1243
- * Encryption and decryption core.
1244
- * @param {Array} input Four words to be encrypted or decrypted.
1245
- * @param dir The direction, 0 for encrypt and 1 for decrypt.
1246
- * @return {Array} The four encrypted or decrypted words.
1247
- * @private
1248
- */
1249
- _crypt(input, dir) {
1250
- if (input.length !== 4) {
1251
- throw new Error("invalid aes block size");
1252
- }
1253
-
1254
- const key = this._key[dir];
1255
-
1256
- const nInnerRounds = key.length / 4 - 2;
1257
- const out = [0, 0, 0, 0];
1258
- const table = this._tables[dir];
1259
-
1260
- // load up the tables
1261
- const t0 = table[0];
1262
- const t1 = table[1];
1263
- const t2 = table[2];
1264
- const t3 = table[3];
1265
- const sbox = table[4];
1266
-
1267
- // state variables a,b,c,d are loaded with pre-whitened data
1268
- let a = input[0] ^ key[0];
1269
- let b = input[dir ? 3 : 1] ^ key[1];
1270
- let c = input[2] ^ key[2];
1271
- let d = input[dir ? 1 : 3] ^ key[3];
1272
- let kIndex = 4;
1273
- let a2, b2, c2;
1274
-
1275
- // Inner rounds. Cribbed from OpenSSL.
1276
- for (let i = 0; i < nInnerRounds; i++) {
1277
- a2 = t0[a >>> 24] ^ t1[b >> 16 & 255] ^ t2[c >> 8 & 255] ^ t3[d & 255] ^ key[kIndex];
1278
- b2 = t0[b >>> 24] ^ t1[c >> 16 & 255] ^ t2[d >> 8 & 255] ^ t3[a & 255] ^ key[kIndex + 1];
1279
- c2 = t0[c >>> 24] ^ t1[d >> 16 & 255] ^ t2[a >> 8 & 255] ^ t3[b & 255] ^ key[kIndex + 2];
1280
- d = t0[d >>> 24] ^ t1[a >> 16 & 255] ^ t2[b >> 8 & 255] ^ t3[c & 255] ^ key[kIndex + 3];
1281
- kIndex += 4;
1282
- a = a2; b = b2; c = c2;
1283
- }
1284
-
1285
- // Last round.
1286
- for (let i = 0; i < 4; i++) {
1287
- out[dir ? 3 & -i : i] =
1288
- sbox[a >>> 24] << 24 ^
1289
- sbox[b >> 16 & 255] << 16 ^
1290
- sbox[c >> 8 & 255] << 8 ^
1291
- sbox[d & 255] ^
1292
- key[kIndex++];
1293
- a2 = a; a = b; b = c; c = d; d = a2;
1294
- }
1295
-
1296
- return out;
847
+ function createHmac(key) {
848
+ const sha1 = createSha1();
849
+ const innerKey = new Uint8Array(SHA1_BLOCK_LENGTH);
850
+ const outerKey = new Uint8Array(SHA1_BLOCK_LENGTH);
851
+ if (key.length > SHA1_BLOCK_LENGTH) {
852
+ sha1.update(key, 0, key.length);
853
+ key = sha1.digest();
1297
854
  }
1298
- };
1299
-
1300
- /** @fileOverview CTR mode implementation.
1301
- *
1302
- * Special thanks to Roy Nicholson for pointing out a bug in our
1303
- * implementation.
1304
- *
1305
- * @author Emily Stark
1306
- * @author Mike Hamburg
1307
- * @author Dan Boneh
1308
- */
1309
-
1310
- /** Brian Gladman's CTR Mode.
1311
- * @constructor
1312
- * @param {Object} _prf The aes instance to generate key.
1313
- * @param {bitArray} _iv The iv for ctr mode, it must be 128 bits.
1314
- */
1315
-
1316
- const mode = {};
1317
-
1318
- /**
1319
- * Brian Gladman's CTR Mode.
1320
- * @namespace
1321
- */
1322
- mode.ctrGladman = class {
1323
- constructor(prf, iv) {
1324
- this._prf = prf;
1325
- this._initIv = iv;
1326
- this._iv = iv;
855
+ for (let indexByte = 0; indexByte < SHA1_BLOCK_LENGTH; indexByte++) {
856
+ const keyByte = indexByte < key.length ? key[indexByte] : 0;
857
+ innerKey[indexByte] = keyByte ^ HMAC_INNER_PADDING;
858
+ outerKey[indexByte] = keyByte ^ HMAC_OUTER_PADDING;
1327
859
  }
860
+ sha1.update(innerKey, 0, SHA1_BLOCK_LENGTH);
861
+ return {
862
+ update(data, offset, length) {
863
+ sha1.update(data, offset, length);
864
+ },
865
+ digest() {
866
+ const innerDigest = sha1.digest();
867
+ sha1.update(outerKey, 0, SHA1_BLOCK_LENGTH);
868
+ sha1.update(innerDigest, 0, SHA1_DIGEST_LENGTH);
869
+ const result = sha1.digest();
870
+ sha1.update(innerKey, 0, SHA1_BLOCK_LENGTH);
871
+ return result;
872
+ }
873
+ };
874
+ }
1328
875
 
1329
- reset() {
1330
- this._iv = this._initIv;
1331
- }
876
+ function createSha1() {
877
+ const state = new Int32Array(SHA1_INITIAL_STATE);
878
+ const schedule = new Int32Array(SHA1_SCHEDULE_LENGTH);
879
+ const block = new Uint8Array(SHA1_BLOCK_LENGTH);
880
+ const blockView = new DataView(block.buffer);
881
+ const lengthBytes = new Uint8Array(8);
882
+ let blockLength = 0;
883
+ let totalLength = 0;
884
+ return {
885
+ update,
886
+ digest
887
+ };
1332
888
 
1333
- /** Input some data to calculate.
1334
- * @param {bitArray} data the data to process, it must be intergral multiple of 128 bits unless it's the last.
1335
- */
1336
- update(data) {
1337
- return this.calculate(this._prf, data, this._iv);
889
+ function update(data, offset, length) {
890
+ const end = offset + length;
891
+ totalLength += length;
892
+ if (blockLength) {
893
+ while (offset < end && blockLength < SHA1_BLOCK_LENGTH) {
894
+ block[blockLength++] = data[offset++];
895
+ }
896
+ if (blockLength == SHA1_BLOCK_LENGTH) {
897
+ compress(blockView, 0);
898
+ blockLength = 0;
899
+ }
900
+ }
901
+ if (offset + SHA1_BLOCK_LENGTH <= end) {
902
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
903
+ for (; offset + SHA1_BLOCK_LENGTH <= end; offset += SHA1_BLOCK_LENGTH) {
904
+ compress(view, offset);
905
+ }
906
+ }
907
+ while (offset < end) {
908
+ block[blockLength++] = data[offset++];
909
+ }
910
+ }
911
+
912
+ function digest() {
913
+ const bits = totalLength * 8;
914
+ const high = Math.floor(bits / 0x100000000);
915
+ const low = bits >>> 0;
916
+ update(SHA1_PADDING, 0, 1);
917
+ while (blockLength != SHA1_LENGTH_OFFSET) {
918
+ update(SHA1_ZERO, 0, 1);
919
+ }
920
+ lengthBytes[0] = high >>> 24;
921
+ lengthBytes[1] = high >>> 16;
922
+ lengthBytes[2] = high >>> 8;
923
+ lengthBytes[3] = high;
924
+ lengthBytes[4] = low >>> 24;
925
+ lengthBytes[5] = low >>> 16;
926
+ lengthBytes[6] = low >>> 8;
927
+ lengthBytes[7] = low;
928
+ update(lengthBytes, 0, 8);
929
+ const result = new Uint8Array(SHA1_DIGEST_LENGTH);
930
+ const resultView = new DataView(result.buffer);
931
+ for (let indexWord = 0; indexWord < state.length; indexWord++) {
932
+ resultView.setInt32(4 * indexWord, state[indexWord]);
933
+ }
934
+ state.set(SHA1_INITIAL_STATE);
935
+ blockLength = 0;
936
+ totalLength = 0;
937
+ return result;
1338
938
  }
1339
939
 
1340
- incWord(word) {
1341
- if (((word >> 24) & 0xff) === 0xff) { //overflow
1342
- let b1 = (word >> 16) & 0xff;
1343
- let b2 = (word >> 8) & 0xff;
1344
- let b3 = word & 0xff;
1345
-
1346
- if (b1 === 0xff) { // overflow b1
1347
- b1 = 0;
1348
- if (b2 === 0xff) {
1349
- b2 = 0;
1350
- if (b3 === 0xff) {
1351
- b3 = 0;
1352
- } else {
1353
- ++b3;
1354
- }
1355
- } else {
1356
- ++b2;
1357
- }
1358
- } else {
1359
- ++b1;
1360
- }
1361
-
1362
- word = 0;
1363
- word += (b1 << 16);
1364
- word += (b2 << 8);
1365
- word += b3;
1366
- } else {
1367
- word += (0x01 << 24);
940
+ function compress(view, offset) {
941
+ for (let index = 0; index < 16; index++) {
942
+ schedule[index] = view.getInt32(offset + 4 * index);
1368
943
  }
1369
- return word;
1370
- }
1371
-
1372
- incCounter(counter) {
1373
- if ((counter[0] = this.incWord(counter[0])) === 0) {
1374
- // encr_data in fileenc.c from Dr Brian Gladman's counts only with DWORD j < 8
1375
- counter[1] = this.incWord(counter[1]);
944
+ for (let index = 16; index < SHA1_SCHEDULE_LENGTH; index++) {
945
+ const word = schedule[index - 3] ^ schedule[index - 8] ^ schedule[index - 14] ^ schedule[index - 16];
946
+ schedule[index] = (word << 1) | (word >>> 31);
1376
947
  }
1377
- }
1378
-
1379
- calculate(prf, data, iv) {
1380
- let l;
1381
- if (!(l = data.length)) {
1382
- return [];
948
+ let a = state[0];
949
+ let b = state[1];
950
+ let c = state[2];
951
+ let d = state[3];
952
+ let e = state[4];
953
+ let t;
954
+ for (let index = 0; index < 20; index++) {
955
+ t = (((a << 5) | (a >>> 27)) + ((b & c) | (~b & d)) + e + 0x5A827999 + schedule[index]) | 0;
956
+ e = d;
957
+ d = c;
958
+ c = (b << 30) | (b >>> 2);
959
+ b = a;
960
+ a = t;
1383
961
  }
1384
- const bl = bitArray.bitLength(data);
1385
- for (let i = 0; i < l; i += 4) {
1386
- this.incCounter(iv);
1387
- const e = prf.encrypt(iv);
1388
- data[i] ^= e[0];
1389
- data[i + 1] ^= e[1];
1390
- data[i + 2] ^= e[2];
1391
- data[i + 3] ^= e[3];
962
+ for (let index = 20; index < 40; index++) {
963
+ t = (((a << 5) | (a >>> 27)) + (b ^ c ^ d) + e + 0x6ED9EBA1 + schedule[index]) | 0;
964
+ e = d;
965
+ d = c;
966
+ c = (b << 30) | (b >>> 2);
967
+ b = a;
968
+ a = t;
1392
969
  }
1393
- return bitArray.clamp(data, bl);
970
+ for (let index = 40; index < 60; index++) {
971
+ t = (((a << 5) | (a >>> 27)) + ((b & c) | (b & d) | (c & d)) + e + 0x8F1BBCDC + schedule[index]) | 0;
972
+ e = d;
973
+ d = c;
974
+ c = (b << 30) | (b >>> 2);
975
+ b = a;
976
+ a = t;
977
+ }
978
+ for (let index = 60; index < SHA1_SCHEDULE_LENGTH; index++) {
979
+ t = (((a << 5) | (a >>> 27)) + (b ^ c ^ d) + e + 0xCA62C1D6 + schedule[index]) | 0;
980
+ e = d;
981
+ d = c;
982
+ c = (b << 30) | (b >>> 2);
983
+ b = a;
984
+ a = t;
985
+ }
986
+ state[0] = (state[0] + a) | 0;
987
+ state[1] = (state[1] + b) | 0;
988
+ state[2] = (state[2] + c) | 0;
989
+ state[3] = (state[3] + d) | 0;
990
+ state[4] = (state[4] + e) | 0;
1394
991
  }
1395
- };
992
+ }
1396
993
 
1397
- const misc = {
1398
- importKey(password) {
1399
- return new misc.hmacSha1(codec.bytes.toBits(password));
1400
- },
1401
- pbkdf2(prf, salt, count, length) {
1402
- count = count || 10000;
1403
- if (length < 0 || count < 0) {
1404
- throw new Error("invalid params to pbkdf2");
1405
- }
1406
- const byteLength = ((length >> 5) + 1) << 2;
1407
- let u, ui, i, j, k;
1408
- const arrayBuffer = new ArrayBuffer(byteLength);
1409
- const out = new DataView(arrayBuffer);
1410
- let outLength = 0;
1411
- const b = bitArray;
1412
- salt = codec.bytes.toBits(salt);
1413
- for (k = 1; outLength < (byteLength || 1); k++) {
1414
- u = ui = prf.encrypt(b.concat(salt, [k]));
1415
- for (i = 1; i < count; i++) {
1416
- ui = prf.encrypt(ui);
1417
- for (j = 0; j < ui.length; j++) {
1418
- u[j] ^= ui[j];
1419
- }
1420
- }
1421
- for (i = 0; outLength < (byteLength || 1) && i < u.length; i++) {
1422
- out.setInt32(outLength, u[i]);
1423
- outLength += 4;
994
+ function initTables() {
995
+ if (!tablesInitialized) {
996
+ let p = 1;
997
+ let q = 1;
998
+ do {
999
+ p = (p ^ (p << 1) ^ ((p & 0x80) ? 0x1b : 0)) & 255;
1000
+ q = (q ^ (q << 1)) & 255;
1001
+ q = (q ^ (q << 2)) & 255;
1002
+ q = (q ^ (q << 4)) & 255;
1003
+ if (q & 0x80) {
1004
+ q ^= 0x09;
1424
1005
  }
1006
+ S_BOX[p] = (q ^ ((q << 1) | (q >> 7)) ^ ((q << 2) | (q >> 6)) ^ ((q << 3) | (q >> 5)) ^ ((q << 4) | (q >> 4)) ^ 0x63) & 255;
1007
+ } while (p != 1);
1008
+ S_BOX[0] = 0x63;
1009
+ for (let index = 0; index < 256; index++) {
1010
+ const s = S_BOX[index];
1011
+ const s2 = multiplyByTwo(s);
1012
+ const t = (s2 << 24) | (s << 16) | (s << 8) | (s2 ^ s);
1013
+ T0[index] = t;
1014
+ T1[index] = (t >>> 8) | (t << 24);
1015
+ T2[index] = (t >>> 16) | (t << 16);
1016
+ T3[index] = (t >>> 24) | (t << 8);
1425
1017
  }
1426
- return arrayBuffer.slice(0, length / 8);
1018
+ tablesInitialized = true;
1427
1019
  }
1428
- };
1429
-
1430
- /** @fileOverview HMAC implementation.
1431
- *
1432
- * @author Emily Stark
1433
- * @author Mike Hamburg
1434
- * @author Dan Boneh
1435
- */
1436
-
1437
- /** HMAC with the specified hash function.
1438
- * @constructor
1439
- * @param {bitArray} key the key for HMAC.
1440
- * @param {Object} [Hash=hash.sha1] The hash function to use.
1441
- */
1442
- misc.hmacSha1 = class {
1443
-
1444
- constructor(key) {
1445
- const hmac = this;
1446
- const Hash = hmac._hash = hash.sha1;
1447
- const exKey = [[], []];
1448
- hmac._baseHash = [new Hash(), new Hash()];
1449
- const bs = hmac._baseHash[0].blockSize / 32;
1450
-
1451
- if (key.length > bs) {
1452
- key = new Hash().update(key).finalize();
1453
- }
1454
-
1455
- for (let i = 0; i < bs; i++) {
1456
- exKey[0][i] = key[i] ^ 0x36363636;
1457
- exKey[1][i] = key[i] ^ 0x5C5C5C5C;
1458
- }
1020
+ }
1459
1021
 
1460
- hmac._baseHash[0].update(exKey[0]);
1461
- hmac._baseHash[1].update(exKey[1]);
1462
- hmac._resultHash = new Hash(hmac._baseHash[0]);
1463
- }
1464
- reset() {
1465
- const hmac = this;
1466
- hmac._resultHash = new hmac._hash(hmac._baseHash[0]);
1467
- hmac._updated = false;
1022
+ function expandKey(key, roundKeys) {
1023
+ const keyWords = key.length >> 2;
1024
+ const rounds = keyWords + 6;
1025
+ const total = 4 * (rounds + 1);
1026
+ let roundConstant = 1;
1027
+ for (let index = 0; index < keyWords; index++) {
1028
+ roundKeys[index] = (key[4 * index] << 24) | (key[4 * index + 1] << 16) | (key[4 * index + 2] << 8) | key[4 * index + 3];
1468
1029
  }
1469
-
1470
- update(data) {
1471
- const hmac = this;
1472
- hmac._updated = true;
1473
- hmac._resultHash.update(data);
1030
+ for (let index = keyWords; index < total; index++) {
1031
+ let word = roundKeys[index - 1];
1032
+ if (index % keyWords == 0) {
1033
+ word = substituteWord((word << 8) | (word >>> 24)) ^ (roundConstant << 24);
1034
+ roundConstant = multiplyByTwo(roundConstant);
1035
+ } else if (keyWords > 6 && index % keyWords == 4) {
1036
+ word = substituteWord(word);
1037
+ }
1038
+ roundKeys[index] = roundKeys[index - keyWords] ^ word;
1474
1039
  }
1040
+ return rounds;
1041
+ }
1475
1042
 
1476
- digest() {
1477
- const hmac = this;
1478
- const w = hmac._resultHash.finalize();
1479
- const result = new (hmac._hash)(hmac._baseHash[1]).update(w).finalize();
1480
-
1481
- hmac.reset();
1482
-
1483
- return result;
1484
- }
1043
+ function substituteWord(word) {
1044
+ return (S_BOX[word >>> 24] << 24) | (S_BOX[(word >>> 16) & 255] << 16) | (S_BOX[(word >>> 8) & 255] << 8) | S_BOX[word & 255];
1045
+ }
1485
1046
 
1486
- encrypt(data) {
1487
- if (!this._updated) {
1488
- this.update(data);
1489
- return this.digest(data);
1490
- } else {
1491
- throw new Error("encrypt on already updated hmac called!");
1492
- }
1493
- }
1494
- };
1047
+ function multiplyByTwo(value) {
1048
+ return ((value << 1) ^ ((value >> 7) * 0x1b)) & 255;
1049
+ }
1495
1050
 
1496
1051
  /*
1497
1052
  Copyright (c) 2022 Gildas Lormeau. All rights reserved.
@@ -1546,8 +1101,8 @@
1546
1101
  1. Redistributions of source code must retain the above copyright notice,
1547
1102
  this list of conditions and the following disclaimer.
1548
1103
 
1549
- 2. Redistributions in binary form must reproduce the above copyright
1550
- notice, this list of conditions and the following disclaimer in
1104
+ 2. Redistributions in binary form must reproduce the above copyright
1105
+ notice, this list of conditions and the following disclaimer in
1551
1106
  the documentation and/or other materials provided with the distribution.
1552
1107
 
1553
1108
  3. The names of the authors may not be used to endorse or promote products
@@ -1571,24 +1126,21 @@
1571
1126
  const PBKDF2_ALGORITHM = { name: "PBKDF2" };
1572
1127
  const HASH_ALGORITHM = { name: "HMAC" };
1573
1128
  const HASH_FUNCTION = "SHA-1";
1129
+ const PBKDF2_ITERATIONS = 1000;
1574
1130
  const BASE_KEY_ALGORITHM = Object.assign({ hash: HASH_ALGORITHM }, PBKDF2_ALGORITHM);
1575
- const DERIVED_BITS_ALGORITHM = Object.assign({ iterations: 1000, hash: { name: HASH_FUNCTION } }, PBKDF2_ALGORITHM);
1131
+ const DERIVED_BITS_ALGORITHM = Object.assign({ iterations: PBKDF2_ITERATIONS, hash: { name: HASH_FUNCTION } }, PBKDF2_ALGORITHM);
1576
1132
  const DERIVED_BITS_USAGE = ["deriveBits"];
1577
1133
  const SALT_LENGTH = [8, 12, 16];
1578
1134
  const KEY_LENGTH = [16, 24, 32];
1579
1135
  const AUTHENTICATION_CODE_LENGTH = 10;
1580
- const COUNTER_DEFAULT_VALUE = [0, 0, 0, 0];
1136
+ const PASSWORD_VERIFICATION_LENGTH = 2;
1581
1137
  // deno-lint-ignore valid-typeof
1582
1138
  const CRYPTO_API_SUPPORTED = typeof crypto != UNDEFINED_TYPE;
1583
1139
  const subtle = CRYPTO_API_SUPPORTED && crypto.subtle;
1584
1140
  const SUBTLE_API_SUPPORTED = CRYPTO_API_SUPPORTED && typeof subtle != UNDEFINED_TYPE;
1585
- const codecBytes = codec.bytes;
1586
- const Aes = cipher.aes;
1587
- const CtrGladman = mode.ctrGladman;
1588
- const HmacSha1 = misc.hmacSha1;
1589
1141
 
1590
- let IMPORT_KEY_SUPPORTED = CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && typeof subtle.importKey == FUNCTION_TYPE;
1591
- let DERIVE_BITS_SUPPORTED = CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && typeof subtle.deriveBits == FUNCTION_TYPE;
1142
+ let DERIVE_BITS_SUPPORTED = SUBTLE_API_SUPPORTED && typeof subtle.importKey == FUNCTION_TYPE && typeof subtle.deriveBits == FUNCTION_TYPE;
1143
+ let createEngine = createEngine$1;
1592
1144
 
1593
1145
  class AESDecryptionStream extends TransformStream {
1594
1146
 
@@ -1606,9 +1158,10 @@
1606
1158
  ready
1607
1159
  } = aesCrypto;
1608
1160
  if (password) {
1609
- await createDecryptionKeys(aesCrypto, strength, password, subarray(chunk, 0, SALT_LENGTH[strength] + 2));
1610
- chunk = subarray(chunk, SALT_LENGTH[strength] + 2);
1161
+ await createDecryptionKeys(aesCrypto, strength, password, subarray(chunk, 0, SALT_LENGTH[strength] + PASSWORD_VERIFICATION_LENGTH));
1162
+ chunk = subarray(chunk, SALT_LENGTH[strength] + PASSWORD_VERIFICATION_LENGTH);
1611
1163
  if (checkPasswordOnly) {
1164
+ disposeEngine(aesCrypto);
1612
1165
  controller.error(new Error(ERR_ABORT_CHECK_PASSWORD));
1613
1166
  } else {
1614
1167
  resolveReady();
@@ -1621,23 +1174,16 @@
1621
1174
  },
1622
1175
  async flush(controller) {
1623
1176
  const {
1624
- ctr,
1625
- hmac,
1177
+ engine,
1626
1178
  pendingInput,
1627
1179
  ready
1628
1180
  } = this;
1629
- if (hmac && ctr) {
1181
+ if (engine) {
1630
1182
  await ready;
1631
- const chunkToDecrypt = subarray(pendingInput, 0, pendingInput.length - AUTHENTICATION_CODE_LENGTH);
1632
1183
  const originalAuthenticationCode = subarray(pendingInput, pendingInput.length - AUTHENTICATION_CODE_LENGTH);
1633
- let decryptedChunkArray = EMPTY_UINT8_ARRAY;
1634
- if (chunkToDecrypt.length) {
1635
- const encryptedChunk = toBits(codecBytes, chunkToDecrypt);
1636
- hmac.update(encryptedChunk);
1637
- const decryptedChunk = ctr.update(encryptedChunk);
1638
- decryptedChunkArray = fromBits(codecBytes, decryptedChunk);
1639
- }
1640
- const authenticationCode = subarray(fromBits(codecBytes, hmac.digest()), 0, AUTHENTICATION_CODE_LENGTH);
1184
+ const decryptedChunkArray = new Uint8Array(subarray(pendingInput, 0, pendingInput.length - AUTHENTICATION_CODE_LENGTH));
1185
+ engine.process(decryptedChunkArray, true);
1186
+ const authenticationCode = engine.digest();
1641
1187
  let invalidAuthenticationCode = pendingInput.length < AUTHENTICATION_CODE_LENGTH ? 1 : 0;
1642
1188
  for (let indexByte = 0; indexByte < AUTHENTICATION_CODE_LENGTH; indexByte++) {
1643
1189
  invalidAuthenticationCode |= authenticationCode[indexByte] ^ originalAuthenticationCode[indexByte];
@@ -1647,6 +1193,9 @@
1647
1193
  }
1648
1194
  controller.enqueue(decryptedChunkArray);
1649
1195
  }
1196
+ },
1197
+ cancel() {
1198
+ disposeEngine(this);
1650
1199
  }
1651
1200
  });
1652
1201
  }
@@ -1676,26 +1225,24 @@
1676
1225
  }
1677
1226
  const output = new Uint8Array(preamble.length + chunk.length - (chunk.length % BLOCK_LENGTH));
1678
1227
  output.set(preamble, 0);
1679
- controller.enqueue(append(aesCrypto, chunk, output, preamble.length, 0));
1228
+ controller.enqueue(append(aesCrypto, chunk, output, preamble.length, 0, false));
1680
1229
  },
1681
1230
  async flush(controller) {
1682
1231
  const {
1683
- ctr,
1684
- hmac,
1232
+ engine,
1685
1233
  pendingInput,
1686
1234
  ready
1687
1235
  } = this;
1688
- if (hmac && ctr) {
1236
+ if (engine) {
1689
1237
  await ready;
1690
- let encryptedChunkArray = EMPTY_UINT8_ARRAY;
1691
- if (pendingInput.length) {
1692
- const encryptedChunk = ctr.update(toBits(codecBytes, pendingInput));
1693
- hmac.update(encryptedChunk);
1694
- encryptedChunkArray = fromBits(codecBytes, encryptedChunk);
1695
- }
1696
- const authenticationCode = fromBits(codecBytes, hmac.digest()).slice(0, AUTHENTICATION_CODE_LENGTH);
1238
+ const encryptedChunkArray = new Uint8Array(pendingInput);
1239
+ engine.process(encryptedChunkArray, false);
1240
+ const authenticationCode = subarray(engine.digest(), 0, AUTHENTICATION_CODE_LENGTH);
1697
1241
  controller.enqueue(concat(encryptedChunkArray, authenticationCode));
1698
1242
  }
1243
+ },
1244
+ cancel() {
1245
+ disposeEngine(this);
1699
1246
  }
1700
1247
  });
1701
1248
  }
@@ -1710,30 +1257,23 @@
1710
1257
  });
1711
1258
  }
1712
1259
 
1713
- function append(aesCrypto, input, output, paddingStart, paddingEnd, verifyAuthenticationCode) {
1260
+ function append(aesCrypto, input, output, paddingStart, paddingEnd, decrypt) {
1714
1261
  const {
1715
- ctr,
1716
- hmac,
1262
+ engine,
1717
1263
  pendingInput
1718
1264
  } = aesCrypto;
1719
1265
  if (pendingInput.length) {
1720
1266
  input = concat(pendingInput, input);
1721
1267
  }
1722
1268
  const inputLength = input.length - paddingEnd;
1723
- output = expand(output, paddingStart + (inputLength - (inputLength % BLOCK_LENGTH)));
1724
- let offset;
1725
- for (offset = 0; offset <= inputLength - BLOCK_LENGTH; offset += BLOCK_LENGTH) {
1726
- const inputChunk = toBits(codecBytes, subarray(input, offset, offset + BLOCK_LENGTH));
1727
- if (verifyAuthenticationCode) {
1728
- hmac.update(inputChunk);
1729
- }
1730
- const outputChunk = ctr.update(inputChunk);
1731
- if (!verifyAuthenticationCode) {
1732
- hmac.update(outputChunk);
1733
- }
1734
- output.set(fromBits(codecBytes, outputChunk), offset + paddingStart);
1735
- }
1736
- aesCrypto.pendingInput = subarray(input, offset);
1269
+ const alignedLength = inputLength - (inputLength % BLOCK_LENGTH);
1270
+ output = expand(output, paddingStart + alignedLength);
1271
+ if (alignedLength) {
1272
+ const chunk = subarray(output, paddingStart, paddingStart + alignedLength);
1273
+ chunk.set(subarray(input, 0, alignedLength));
1274
+ engine.process(chunk, decrypt);
1275
+ }
1276
+ aesCrypto.pendingInput = subarray(input, alignedLength);
1737
1277
  return output;
1738
1278
  }
1739
1279
 
@@ -1741,10 +1281,17 @@
1741
1281
  const passwordVerificationKey = await createKeys$1(decrypt, strength, password, subarray(preamble, 0, SALT_LENGTH[strength]));
1742
1282
  const passwordVerification = subarray(preamble, SALT_LENGTH[strength]);
1743
1283
  if (passwordVerificationKey[0] != passwordVerification[0] || passwordVerificationKey[1] != passwordVerification[1]) {
1284
+ disposeEngine(decrypt);
1744
1285
  throw new Error(ERR_INVALID_PASSWORD);
1745
1286
  }
1746
1287
  }
1747
1288
 
1289
+ function disposeEngine({ engine }) {
1290
+ if (engine && engine.dispose) {
1291
+ engine.dispose();
1292
+ }
1293
+ }
1294
+
1748
1295
  async function createEncryptionKeys(encrypt, strength, password) {
1749
1296
  const salt = getRandomValues(new Uint8Array(SALT_LENGTH[strength]));
1750
1297
  const passwordVerification = await createKeys$1(encrypt, strength, password, salt);
@@ -1753,48 +1300,22 @@
1753
1300
 
1754
1301
  async function createKeys$1(aesCrypto, strength, password, salt) {
1755
1302
  aesCrypto.password = null;
1756
- const baseKey = await importKey(RAW_FORMAT, password, BASE_KEY_ALGORITHM, false, DERIVED_BITS_USAGE);
1757
- const derivedBits = await deriveBits(Object.assign({ salt }, DERIVED_BITS_ALGORITHM), baseKey, 8 * ((KEY_LENGTH[strength] * 2) + 2));
1758
- const compositeKey = new Uint8Array(derivedBits);
1759
- const key = toBits(codecBytes, subarray(compositeKey, 0, KEY_LENGTH[strength]));
1760
- const authentication = toBits(codecBytes, subarray(compositeKey, KEY_LENGTH[strength], KEY_LENGTH[strength] * 2));
1761
- const passwordVerification = subarray(compositeKey, KEY_LENGTH[strength] * 2);
1762
- Object.assign(aesCrypto, {
1763
- keys: {
1764
- key,
1765
- authentication,
1766
- passwordVerification
1767
- },
1768
- ctr: new CtrGladman(new Aes(key), Array.from(COUNTER_DEFAULT_VALUE)),
1769
- hmac: new HmacSha1(authentication)
1770
- });
1771
- return passwordVerification;
1772
- }
1773
-
1774
- async function importKey(format, password, algorithm, extractable, keyUsages) {
1775
- if (IMPORT_KEY_SUPPORTED) {
1776
- try {
1777
- return await subtle.importKey(format, password, algorithm, extractable, keyUsages);
1778
- } catch {
1779
- IMPORT_KEY_SUPPORTED = false;
1780
- return misc.importKey(password);
1781
- }
1782
- } else {
1783
- return misc.importKey(password);
1784
- }
1303
+ const keyLength = KEY_LENGTH[strength];
1304
+ const compositeKey = await deriveKey(password, salt, keyLength * 2 + PASSWORD_VERIFICATION_LENGTH);
1305
+ aesCrypto.engine = createEngine(subarray(compositeKey, 0, keyLength), subarray(compositeKey, keyLength, keyLength * 2));
1306
+ return subarray(compositeKey, keyLength * 2);
1785
1307
  }
1786
1308
 
1787
- async function deriveBits(algorithm, baseKey, length) {
1309
+ async function deriveKey(password, salt, length) {
1788
1310
  if (DERIVE_BITS_SUPPORTED) {
1789
1311
  try {
1790
- return await subtle.deriveBits(algorithm, baseKey, length);
1312
+ const baseKey = await subtle.importKey(RAW_FORMAT, password, BASE_KEY_ALGORITHM, false, DERIVED_BITS_USAGE);
1313
+ return new Uint8Array(await subtle.deriveBits(Object.assign({ salt }, DERIVED_BITS_ALGORITHM), baseKey, length * 8));
1791
1314
  } catch {
1792
1315
  DERIVE_BITS_SUPPORTED = false;
1793
- return misc.pbkdf2(baseKey, algorithm.salt, DERIVED_BITS_ALGORITHM.iterations, length);
1794
1316
  }
1795
- } else {
1796
- return misc.pbkdf2(baseKey, algorithm.salt, DERIVED_BITS_ALGORITHM.iterations, length);
1797
1317
  }
1318
+ return pbkdf2(password, salt, PBKDF2_ITERATIONS, length);
1798
1319
  }
1799
1320
 
1800
1321
  function encodePassword(password, rawPassword) {
@@ -1818,13 +1339,6 @@
1818
1339
  return array.subarray(begin, end);
1819
1340
  }
1820
1341
 
1821
- function fromBits(codecBytes, chunk) {
1822
- return codecBytes.fromBits(chunk);
1823
- }
1824
- function toBits(codecBytes, chunk) {
1825
- return codecBytes.toBits(chunk);
1826
- }
1827
-
1828
1342
  /*
1829
1343
  Copyright (c) 2022 Gildas Lormeau. All rights reserved.
1830
1344
 
@@ -2764,11 +2278,18 @@
2764
2278
  return true;
2765
2279
  }
2766
2280
  if (FallbackStream) {
2281
+ return await loadModule(config);
2282
+ }
2283
+ return false;
2284
+ }
2285
+
2286
+ async function loadModule(config) {
2287
+ if (initModule) {
2767
2288
  try {
2768
2289
  await initModule(config);
2769
2290
  return true;
2770
2291
  } catch {
2771
- return false;
2292
+ // ignored
2772
2293
  }
2773
2294
  }
2774
2295
  return false;
@@ -2811,26 +2332,27 @@
2811
2332
  terminate() {
2812
2333
  return new Promise(resolve => {
2813
2334
  const { worker, busy } = workerData;
2814
- if (worker) {
2815
- if (busy) {
2816
- workerData.resolveTerminated = resolve;
2817
- } else {
2335
+ if (busy) {
2336
+ workerData.resolveTerminated = resolve;
2337
+ } else {
2338
+ if (worker) {
2818
2339
  worker.terminate();
2819
- resolve();
2340
+ workerData.worker = null;
2820
2341
  }
2821
- workerData.interface = null;
2822
- } else {
2823
2342
  resolve();
2824
2343
  }
2344
+ workerData.interface = null;
2825
2345
  });
2826
2346
  },
2827
2347
  onTaskFinished() {
2828
2348
  if (workerData.busy) {
2829
- const { resolveTerminated } = workerData;
2349
+ const { resolveTerminated, worker } = workerData;
2830
2350
  if (resolveTerminated) {
2831
2351
  workerData.resolveTerminated = null;
2832
- workerData.terminated = true;
2833
- workerData.worker.terminate();
2352
+ if (worker) {
2353
+ workerData.terminated = true;
2354
+ worker.terminate();
2355
+ }
2834
2356
  resolveTerminated();
2835
2357
  }
2836
2358
  workerData.busy = false;
@@ -2887,28 +2409,23 @@
2887
2409
  }
2888
2410
 
2889
2411
  async function runWorker$1({ options, readable, writable, onTaskFinished, workerOptions }, config) {
2890
- let codecStream, chunkStream;
2412
+ let codecStream, chunkStream, modulePromise;
2891
2413
  try {
2892
2414
  if (options.compressed && !options.format) {
2893
2415
  const deflate = options.codecType.startsWith(CODEC_DEFLATE);
2894
2416
  const FallbackStream = deflate ? config.CompressionStreamFallback : config.DecompressionStreamFallback;
2895
2417
  const NativeStream = deflate ? config.CompressionStream : config.DecompressionStream;
2896
2418
  if (!options.useCompressionStream) {
2897
- try {
2898
- await initModule(config);
2899
- } catch {
2900
- if (!FallbackStream || FallbackStream.requiresModule) {
2901
- options.useCompressionStream = true;
2902
- }
2419
+ if (!await moduleLoaded() && (!FallbackStream || FallbackStream.requiresModule)) {
2420
+ options.useCompressionStream = true;
2903
2421
  }
2904
2422
  } else if (FallbackStream && FallbackStream.requiresModule && !supportsDeflateRaw(NativeStream)) {
2905
- try {
2906
- await initModule(config);
2907
- } catch {
2908
- // ignored
2909
- }
2423
+ await moduleLoaded();
2910
2424
  }
2911
2425
  }
2426
+ if (options.encrypted && !options.zipCrypto) {
2427
+ await moduleLoaded();
2428
+ }
2912
2429
  codecStream = new CodecStream(options, config);
2913
2430
  chunkStream = new ChunkStream(getChunkSize(config));
2914
2431
  await readable
@@ -2941,6 +2458,13 @@
2941
2458
  } finally {
2942
2459
  onTaskFinished();
2943
2460
  }
2461
+
2462
+ function moduleLoaded() {
2463
+ if (!modulePromise) {
2464
+ modulePromise = loadModule(config);
2465
+ }
2466
+ return modulePromise;
2467
+ }
2944
2468
  }
2945
2469
 
2946
2470
  /*
@@ -3047,7 +2571,7 @@
3047
2571
  rejectResult = error => {
3048
2572
  const { outputSize, workerOptions } = workerData;
3049
2573
  workerOptions.outputSize = outputSize;
3050
- if (isErrorObject(error) && error.outputSize === UNDEFINED_VALUE) {
2574
+ if (isErrorObject(error)) {
3051
2575
  try {
3052
2576
  error.outputSize = outputSize;
3053
2577
  } catch {
@@ -3061,12 +2585,14 @@
3061
2585
  reader: null,
3062
2586
  writer: null,
3063
2587
  outputSize: 0,
2588
+ destinationFailed: false,
2589
+ destinationError: null,
3064
2590
  resolveResult,
3065
2591
  rejectResult,
3066
2592
  result
3067
2593
  });
3068
2594
  const { readable, options } = workerData;
3069
- const { writable, closed, abortPipe } = watchClosedStream(workerData.writable);
2595
+ const { writable, closed, abortPipe } = watchClosedStream(workerData.writable, workerData);
3070
2596
  let streamsTransferred;
3071
2597
  try {
3072
2598
  streamsTransferred = sendMessage({
@@ -3109,7 +2635,18 @@
3109
2635
  } catch {
3110
2636
  // ignored
3111
2637
  }
3112
- throw error;
2638
+ const { outputSize, workerOptions, destinationFailed, destinationError } = workerData;
2639
+ workerOptions.outputSize = outputSize;
2640
+ const workerFailed = isErrorObject(error) && (error.codecImportFailed || error.workerStartupFailed);
2641
+ const reportedError = destinationFailed && !workerFailed ? destinationError : error;
2642
+ if (isErrorObject(reportedError)) {
2643
+ try {
2644
+ reportedError.outputSize = outputSize;
2645
+ } catch {
2646
+ // ignored
2647
+ }
2648
+ }
2649
+ throw reportedError;
3113
2650
  }
3114
2651
 
3115
2652
  async function closeWritable() {
@@ -3123,12 +2660,27 @@
3123
2660
  }
3124
2661
  }
3125
2662
 
3126
- function watchClosedStream(writableSource) {
2663
+ function watchClosedStream(writableSource, workerData) {
3127
2664
  const abortController = new AbortController();
3128
- const { writable, readable } = new TransformStream();
2665
+ let aborting;
2666
+ const { writable, readable } = new TransformStream({
2667
+ transform(chunk, controller) {
2668
+ workerData.outputSize += chunk.length;
2669
+ controller.enqueue(chunk);
2670
+ }
2671
+ });
3129
2672
  const closed = readable.pipeTo(writableSource, { preventClose: true, preventAbort: true, signal: abortController.signal });
3130
- closed.catch(() => { });
3131
- return { writable, closed, abortPipe: () => abortController.abort() };
2673
+ closed.catch(error => {
2674
+ if (!aborting) {
2675
+ Object.assign(workerData, { destinationFailed: true, destinationError: error });
2676
+ }
2677
+ });
2678
+ return {
2679
+ writable, closed, abortPipe: () => {
2680
+ aborting = true;
2681
+ abortController.abort();
2682
+ }
2683
+ };
3132
2684
  }
3133
2685
 
3134
2686
  function releaseWorkerStreams(workerData) {
@@ -3326,9 +2878,6 @@
3326
2878
  const stale = () => workerData.generation != generation;
3327
2879
  try {
3328
2880
  if (error) {
3329
- if (error.outputSize !== UNDEFINED_VALUE) {
3330
- workerData.outputSize = error.outputSize;
3331
- }
3332
2881
  fail(getResponseError(error, errorValue));
3333
2882
  } else {
3334
2883
  if (type == MESSAGE_PULL) {
@@ -3341,7 +2890,6 @@
3341
2890
  const chunk = new Uint8Array(value);
3342
2891
  await writer.ready;
3343
2892
  await writer.write(chunk);
3344
- workerData.outputSize += chunk.length;
3345
2893
  if (!stale()) {
3346
2894
  sendMessage({ type: MESSAGE_ACK_DATA, messageId }, workerData);
3347
2895
  }
@@ -4073,16 +3621,14 @@
4073
3621
  combineSizeEocd
4074
3622
  } = httpReader;
4075
3623
  if (isHttpFamily(url) && (useRangeHeader || forceRangeRequests) && (typeof preventHeadRequest == UNDEFINED_TYPE || preventHeadRequest)) {
4076
- const response = await sendRequest(HTTP_METHOD_GET, httpReader, getRangeHeaders(httpReader, combineSizeEocd ? -END_OF_CENTRAL_DIR_LENGTH : undefined));
3624
+ const response = await sendRequest(HTTP_METHOD_GET, httpReader, getRangeHeaders(httpReader, combineSizeEocd ? -65557 : undefined));
4077
3625
  const acceptRanges = response.headers.get(HTTP_HEADER_ACCEPT_RANGES);
4078
3626
  if (!forceRangeRequests && (!acceptRanges || acceptRanges.toLowerCase() != HTTP_RANGE_UNIT)) {
4079
3627
  throw new Error(ERR_HTTP_RANGE);
4080
3628
  } else {
4081
- if (combineSizeEocd) {
4082
- const eocdCache = new Uint8Array(await response.arrayBuffer());
4083
- if (response.status == 206 && eocdCache.length == END_OF_CENTRAL_DIR_LENGTH) {
4084
- httpReader.eocdCache = eocdCache;
4085
- }
3629
+ let eocdCache;
3630
+ if (combineSizeEocd && response.status == 206) {
3631
+ eocdCache = new Uint8Array(await response.arrayBuffer());
4086
3632
  }
4087
3633
  setResourceValidators(httpReader, response);
4088
3634
  const contentSize = getContentRangeSize(response);
@@ -4091,6 +3637,9 @@
4091
3637
  } else {
4092
3638
  httpReader.size = contentSize;
4093
3639
  }
3640
+ if (eocdCache && eocdCache.length && getContentRangeOffset(response) === httpReader.size - eocdCache.length) {
3641
+ httpReader.eocdCache = eocdCache;
3642
+ }
4094
3643
  }
4095
3644
  } else {
4096
3645
  await getContentLength(httpReader, sendRequest, getRequestData);
@@ -4106,25 +3655,23 @@
4106
3655
  options
4107
3656
  } = httpReader;
4108
3657
  if (useRangeHeader || forceRangeRequests) {
4109
- if (eocdCache && index == size - END_OF_CENTRAL_DIR_LENGTH && length == END_OF_CENTRAL_DIR_LENGTH) {
4110
- return eocdCache;
4111
- }
4112
3658
  if (index >= size || length === 0) {
4113
3659
  return EMPTY_UINT8_ARRAY;
4114
3660
  } else {
4115
3661
  if (index + length > size) {
4116
3662
  length = size - index;
4117
3663
  }
3664
+ if (eocdCache && index >= size - eocdCache.length) {
3665
+ const cacheIndex = index - (size - eocdCache.length);
3666
+ return eocdCache.slice(cacheIndex, cacheIndex + length);
3667
+ }
4118
3668
  const response = await sendRequest(HTTP_METHOD_GET, httpReader, getRangeHeaders(httpReader, index, length));
4119
3669
  if (response.status != 206) {
4120
3670
  throw new Error(ERR_HTTP_RANGE);
4121
3671
  }
4122
- const contentRangeHeader = response.headers.get(HTTP_HEADER_CONTENT_RANGE);
4123
- if (contentRangeHeader) {
4124
- const rangeStart = Number(contentRangeHeader.trim().split(/[\s-]+/)[1]);
4125
- if (!Number.isNaN(rangeStart) && rangeStart != index) {
4126
- throw new Error(ERR_HTTP_RANGE);
4127
- }
3672
+ const rangeStart = getContentRangeOffset(response);
3673
+ if (rangeStart !== UNDEFINED_VALUE && rangeStart != index) {
3674
+ throw new Error(ERR_HTTP_RANGE);
4128
3675
  }
4129
3676
  checkResourceValidators(httpReader, response);
4130
3677
  setResourceValidators(httpReader, response);
@@ -4184,12 +3731,9 @@
4184
3731
  if (response.status != 206) {
4185
3732
  throw new Error(ERR_HTTP_RANGE);
4186
3733
  }
4187
- const contentRangeHeader = response.headers.get(HTTP_HEADER_CONTENT_RANGE);
4188
- if (contentRangeHeader) {
4189
- const rangeStart = Number(contentRangeHeader.trim().split(/[\s-]+/)[1]);
4190
- if (!Number.isNaN(rangeStart) && rangeStart != windowOffset) {
4191
- throw new Error(ERR_HTTP_RANGE);
4192
- }
3734
+ const rangeStart = getContentRangeOffset(response);
3735
+ if (rangeStart !== UNDEFINED_VALUE && rangeStart != windowOffset) {
3736
+ throw new Error(ERR_HTTP_RANGE);
4193
3737
  }
4194
3738
  checkResourceValidators(httpReader, response);
4195
3739
  setResourceValidators(httpReader, response);
@@ -4205,6 +3749,16 @@
4205
3749
  }
4206
3750
  }
4207
3751
 
3752
+ function getContentRangeOffset(response) {
3753
+ const contentRangeHeader = response.headers.get(HTTP_HEADER_CONTENT_RANGE);
3754
+ if (contentRangeHeader) {
3755
+ const rangeStart = Number(contentRangeHeader.trim().split(/[\s-]+/)[1]);
3756
+ if (!Number.isNaN(rangeStart)) {
3757
+ return rangeStart;
3758
+ }
3759
+ }
3760
+ }
3761
+
4208
3762
  function getContentRangeSize(response) {
4209
3763
  const contentRangeHeader = response.headers.get(HTTP_HEADER_CONTENT_RANGE);
4210
3764
  if (contentRangeHeader) {
@@ -6724,7 +6278,6 @@
6724
6278
  rawExtraFieldUnix: EMPTY_UINT8_ARRAY,
6725
6279
  rawExtraField,
6726
6280
  rawCentralExtraField: EMPTY_UINT8_ARRAY,
6727
- extendedTimestamp: false,
6728
6281
  headerArray,
6729
6282
  headerView
6730
6283
  });
@@ -7468,7 +7021,7 @@
7468
7021
  }
7469
7022
  }
7470
7023
  const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !passThroughCompression)) && !isCompressed(compressionMethod, level);
7471
- if (emptyEntry && !zipCrypto && getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR) === UNDEFINED_VALUE) {
7024
+ if (emptyEntry && getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR) === UNDEFINED_VALUE) {
7472
7025
  dataDescriptor = false;
7473
7026
  }
7474
7027
  const zip64UncompressedSize = zip64Enabled || unknownSize || uncompressedSize >= MAX_32_BITS;
@@ -9078,7 +8631,7 @@
9078
8631
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9079
8632
  */
9080
8633
 
9081
- const VERSION = "2.13.0";
8634
+ const VERSION = "2.14.0";
9082
8635
 
9083
8636
  /*
9084
8637
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
@@ -9998,12 +9551,16 @@
9998
9551
  let directoryEntry = parent;
9999
9552
  if (name) {
10000
9553
  directoryEntry = parent.getChildByName(name);
10001
- if (directoryEntry && !directoryEntry.directory) {
9554
+ if (directoryEntry && (!directoryEntry.directory || directoryEntry.data)) {
10002
9555
  if (duplicates == DUPLICATES_KEEP_FIRST) {
10003
9556
  continue;
10004
9557
  } else if (duplicates == DUPLICATES_KEEP_LAST) {
10005
- this.fs.remove(directoryEntry);
10006
- directoryEntry = UNDEFINED_VALUE;
9558
+ if (directoryEntry.directory) {
9559
+ directoryEntry.data = entry;
9560
+ } else {
9561
+ this.fs.remove(directoryEntry);
9562
+ directoryEntry = UNDEFINED_VALUE;
9563
+ }
10007
9564
  } else {
10008
9565
  throw new Error(ERR_DUPLICATE_IMPORTED_ENTRY);
10009
9566
  }