@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
@@ -600,7 +600,7 @@ for (let n = 0; n < 256; n++) {
600
600
  T[k][n] = (previous >>> 8) ^ T[0][previous & 0xFF];
601
601
  }
602
602
  }
603
- const [T0, T1, T2, T3, T4, T5, T6, T7] = T;
603
+ const [T0$1, T1$1, T2$1, T3$1, T4, T5, T6, T7] = T;
604
604
 
605
605
  class Crc32 {
606
606
 
@@ -622,12 +622,12 @@ class Crc32 {
622
622
  const a = crc ^ view.getInt32(offset, true);
623
623
  const b = view.getInt32(offset + 4, true);
624
624
  crc = T7[a & 0xFF] ^ T6[(a >>> 8) & 0xFF] ^ T5[(a >>> 16) & 0xFF] ^ T4[(a >>> 24) & 0xFF] ^
625
- T3[b & 0xFF] ^ T2[(b >>> 8) & 0xFF] ^ T1[(b >>> 16) & 0xFF] ^ T0[(b >>> 24) & 0xFF];
625
+ T3$1[b & 0xFF] ^ T2$1[(b >>> 8) & 0xFF] ^ T1$1[(b >>> 16) & 0xFF] ^ T0$1[(b >>> 24) & 0xFF];
626
626
  }
627
627
  }
628
628
  // Remaining tail (and non-typed inputs) byte-at-a-time with the base table.
629
629
  for (; offset < length; offset++) {
630
- crc = (crc >>> 8) ^ T0[(crc ^ data[offset]) & 0xFF];
630
+ crc = (crc >>> 8) ^ T0$1[(crc ^ data[offset]) & 0xFF];
631
631
  }
632
632
  this.crc = crc;
633
633
  }
@@ -731,794 +731,349 @@ function encodeText(value) {
731
731
  }
732
732
  }
733
733
 
734
- // Derived from https://github.com/xqdoo00o/jszip/blob/master/lib/sjcl.js and https://github.com/bitwiseshiftleft/sjcl
735
-
736
- // deno-lint-ignore-file no-this-alias
737
-
738
734
  /*
739
- * SJCL is open. You can use, modify and redistribute it under a BSD
740
- * license or under the GNU GPL, version 2.0.
741
- */
742
-
743
- /** @fileOverview Javascript cryptography implementation.
744
- *
745
- * Crush to remove comments, shorten variable names and
746
- * generally reduce transmission size.
747
- *
748
- * @author Emily Stark
749
- * @author Mike Hamburg
750
- * @author Dan Boneh
751
- */
752
-
753
- /*jslint indent: 2, bitwise: false, nomen: false, plusplus: false, white: false, regexp: false */
754
-
755
- /** @fileOverview Arrays of bits, encoded as arrays of Numbers.
756
- *
757
- * @author Emily Stark
758
- * @author Mike Hamburg
759
- * @author Dan Boneh
760
- */
761
-
762
- /**
763
- * Arrays of bits, encoded as arrays of Numbers.
764
- * @namespace
765
- * @description
766
- * <p>
767
- * These objects are the currency accepted by SJCL's crypto functions.
768
- * </p>
769
- *
770
- * <p>
771
- * Most of our crypto primitives operate on arrays of 4-byte words internally,
772
- * but many of them can take arguments that are not a multiple of 4 bytes.
773
- * This library encodes arrays of bits (whose size need not be a multiple of 8
774
- * bits) as arrays of 32-bit words. The bits are packed, big-endian, into an
775
- * array of words, 32 bits at a time. Since the words are double-precision
776
- * floating point numbers, they fit some extra data. We use this (in a private,
777
- * possibly-changing manner) to encode the number of bits actually present
778
- * in the last word of the array.
779
- * </p>
780
- *
781
- * <p>
782
- * Because bitwise ops clear this out-of-band data, these arrays can be passed
783
- * to ciphers like AES which want arrays of words.
784
- * </p>
785
- */
786
- const bitArray = {
787
- /**
788
- * Concatenate two bit arrays.
789
- * @param {bitArray} a1 The first array.
790
- * @param {bitArray} a2 The second array.
791
- * @return {bitArray} The concatenation of a1 and a2.
792
- */
793
- concat(a1, a2) {
794
- if (a1.length === 0 || a2.length === 0) {
795
- return a1.concat(a2);
796
- }
797
-
798
- const last = a1[a1.length - 1], shift = bitArray.getPartial(last);
799
- if (shift === 32) {
800
- return a1.concat(a2);
801
- } else {
802
- return bitArray._shiftRight(a2, shift, last | 0, a1.slice(0, a1.length - 1));
803
- }
804
- },
805
-
806
- /**
807
- * Find the length of an array of bits.
808
- * @param {bitArray} a The array.
809
- * @return {Number} The length of a, in bits.
810
- */
811
- bitLength(a) {
812
- const l = a.length;
813
- if (l === 0) {
814
- return 0;
815
- }
816
- const x = a[l - 1];
817
- return (l - 1) * 32 + bitArray.getPartial(x);
818
- },
819
-
820
- /**
821
- * Truncate an array.
822
- * @param {bitArray} a The array.
823
- * @param {Number} len The length to truncate to, in bits.
824
- * @return {bitArray} A new array, truncated to len bits.
825
- */
826
- clamp(a, len) {
827
- if (a.length * 32 < len) {
828
- return a;
829
- }
830
- a = a.slice(0, Math.ceil(len / 32));
831
- const l = a.length;
832
- len = len & 31;
833
- if (l > 0 && len) {
834
- a[l - 1] = bitArray.partial(len, a[l - 1] & 0x80000000 >> (len - 1), 1);
835
- }
836
- return a;
837
- },
838
-
839
- /**
840
- * Make a partial word for a bit array.
841
- * @param {Number} len The number of bits in the word.
842
- * @param {Number} x The bits.
843
- * @param {Number} [_end=0] Pass 1 if x has already been shifted to the high side.
844
- * @return {Number} The partial word.
845
- */
846
- partial(len, x, _end) {
847
- if (len === 32) {
848
- return x;
849
- }
850
- return (_end ? x | 0 : x << (32 - len)) + len * 0x10000000000;
851
- },
735
+ Copyright (c) 2026 Gildas Lormeau. All rights reserved.
852
736
 
853
- /**
854
- * Get the number of bits used by a partial word.
855
- * @param {Number} x The partial word.
856
- * @return {Number} The number of bits used by the partial word.
857
- */
858
- getPartial(x) {
859
- return Math.round(x / 0x10000000000) || 32;
860
- },
737
+ Redistribution and use in source and binary forms, with or without
738
+ modification, are permitted provided that the following conditions are met:
861
739
 
862
- /** Shift an array right.
863
- * @param {bitArray} a The array to shift.
864
- * @param {Number} shift The number of bits to shift.
865
- * @param {Number} [carry=0] A byte to carry in
866
- * @param {bitArray} [out=[]] An array to prepend to the output.
867
- * @private
868
- */
869
- _shiftRight(a, shift, carry, out) {
870
- if (out === undefined) {
871
- out = [];
872
- }
740
+ 1. Redistributions of source code must retain the above copyright notice,
741
+ this list of conditions and the following disclaimer.
873
742
 
874
- for (; shift >= 32; shift -= 32) {
875
- out.push(carry);
876
- carry = 0;
877
- }
878
- if (shift === 0) {
879
- return out.concat(a);
880
- }
743
+ 2. Redistributions in binary form must reproduce the above copyright
744
+ notice, this list of conditions and the following disclaimer in
745
+ the documentation and/or other materials provided with the distribution.
881
746
 
882
- for (let i = 0; i < a.length; i++) {
883
- out.push(carry | a[i] >>> shift);
884
- carry = a[i] << (32 - shift);
885
- }
886
- const last2 = a.length ? a[a.length - 1] : 0;
887
- const shift2 = bitArray.getPartial(last2);
888
- out.push(bitArray.partial(shift + shift2 & 31, (shift + shift2 > 32) ? carry : out.pop(), 1));
889
- return out;
890
- }
891
- };
747
+ 3. The names of the authors may not be used to endorse or promote products
748
+ derived from this software without specific prior written permission.
892
749
 
893
- /** @fileOverview Bit array codec implementations.
894
- *
895
- * @author Emily Stark
896
- * @author Mike Hamburg
897
- * @author Dan Boneh
750
+ THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
751
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
752
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
753
+ INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
754
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
755
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
756
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
757
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
758
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
759
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
898
760
  */
899
761
 
900
- /**
901
- * Arrays of bytes
902
- * @namespace
903
- */
904
- const codec = {
905
- bytes: {
906
- /** Convert from a bitArray to an array of bytes. */
907
- fromBits(arr) {
908
- const bl = bitArray.bitLength(arr);
909
- const byteLength = bl / 8;
910
- const out = new Uint8Array(byteLength);
911
- let tmp;
912
- for (let i = 0; i < byteLength; i++) {
913
- if ((i & 3) === 0) {
914
- tmp = arr[i / 4];
915
- }
916
- out[i] = tmp >>> 24;
917
- tmp <<= 8;
918
- }
919
- return out;
920
- },
921
- /** Convert from an array of bytes to a bitArray. */
922
- toBits(bytes) {
923
- const out = [];
924
- let i;
925
- let tmp = 0;
926
- for (i = 0; i < bytes.length; i++) {
927
- tmp = tmp << 8 | bytes[i];
928
- if ((i & 3) === 3) {
929
- out.push(tmp);
930
- tmp = 0;
931
- }
762
+ const BLOCK_LENGTH$1 = 16;
763
+ const ROUND_KEYS_LENGTH = 60;
764
+ const SHA1_BLOCK_LENGTH = 64;
765
+ const SHA1_DIGEST_LENGTH = 20;
766
+ const SHA1_SCHEDULE_LENGTH = 80;
767
+ const SHA1_LENGTH_OFFSET = 56;
768
+ const SHA1_PADDING = new Uint8Array([0x80]);
769
+ const SHA1_ZERO = new Uint8Array(1);
770
+ const SHA1_INITIAL_STATE = new Int32Array([0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]);
771
+ const HMAC_INNER_PADDING = 0x36;
772
+ const HMAC_OUTER_PADDING = 0x5c;
773
+ const S_BOX = new Uint8Array(256);
774
+ const T0 = new Int32Array(256);
775
+ const T1 = new Int32Array(256);
776
+ const T2 = new Int32Array(256);
777
+ const T3 = new Int32Array(256);
778
+
779
+ let tablesInitialized = false;
780
+
781
+ function createEngine$2(key, authenticationKey) {
782
+ initTables();
783
+ const roundKeys = new Int32Array(ROUND_KEYS_LENGTH);
784
+ const rounds = expandKey(key, roundKeys);
785
+ const counter = new Uint8Array(BLOCK_LENGTH$1);
786
+ const keystream = new Int32Array(BLOCK_LENGTH$1 / 4);
787
+ const hmac = createHmac(authenticationKey);
788
+ return {
789
+ process(data, decrypt) {
790
+ if (decrypt) {
791
+ hmac.update(data, 0, data.length);
932
792
  }
933
- if (i & 3) {
934
- out.push(bitArray.partial(8 * (i & 3), tmp));
793
+ encrypt(data);
794
+ if (!decrypt) {
795
+ hmac.update(data, 0, data.length);
935
796
  }
936
- return out;
937
- }
938
- }
939
- };
940
-
941
- const hash = {};
942
-
943
- /**
944
- * Context for a SHA-1 operation in progress.
945
- * @constructor
946
- */
947
- hash.sha1 = class {
948
- constructor(hash) {
949
- const sha1 = this;
950
- /**
951
- * The hash's block size, in bits.
952
- * @constant
953
- */
954
- sha1.blockSize = 512;
955
- /**
956
- * The SHA-1 initialization vector.
957
- * @private
958
- */
959
- sha1._init = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0];
960
- /**
961
- * The SHA-1 hash key.
962
- * @private
963
- */
964
- sha1._key = [0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6];
965
- if (hash) {
966
- sha1._h = hash._h.slice(0);
967
- sha1._buffer = hash._buffer.slice(0);
968
- sha1._length = hash._length;
969
- } else {
970
- sha1.reset();
971
- }
972
- }
973
-
974
- /**
975
- * Reset the hash state.
976
- * @return this
977
- */
978
- reset() {
979
- const sha1 = this;
980
- sha1._h = sha1._init.slice(0);
981
- sha1._buffer = [];
982
- sha1._length = 0;
983
- return sha1;
984
- }
985
-
986
- /**
987
- * Input several words to the hash.
988
- * @param {bitArray|String} data the data to hash.
989
- * @return this
990
- */
991
- update(data) {
992
- const sha1 = this;
993
- if (typeof data === "string") {
994
- data = codec.utf8String.toBits(data);
995
- }
996
- const b = sha1._buffer = bitArray.concat(sha1._buffer, data);
997
- const ol = sha1._length;
998
- const nl = sha1._length = ol + bitArray.bitLength(data);
999
- if (nl > 9007199254740991) {
1000
- throw new Error("Cannot hash more than 2^53 - 1 bits");
1001
- }
1002
- const c = new Uint32Array(b);
1003
- let j = 0;
1004
- for (let i = sha1.blockSize + ol - ((sha1.blockSize + ol) & (sha1.blockSize - 1)); i <= nl;
1005
- i += sha1.blockSize) {
1006
- sha1._block(c.subarray(16 * j, 16 * (j + 1)));
1007
- j += 1;
1008
- }
1009
- b.splice(0, 16 * j);
1010
- return sha1;
1011
- }
1012
-
1013
- /**
1014
- * Complete hashing and output the hash value.
1015
- * @return {bitArray} The hash value, an array of 5 big-endian words. TODO
1016
- */
1017
- finalize() {
1018
- const sha1 = this;
1019
- let b = sha1._buffer;
1020
- const h = sha1._h;
1021
-
1022
- // Round out and push the buffer
1023
- b = bitArray.concat(b, [bitArray.partial(1, 1)]);
1024
- // Round out the buffer to a multiple of 16 words, less the 2 length words.
1025
- for (let i = b.length + 2; i & 15; i++) {
1026
- b.push(0);
1027
- }
1028
-
1029
- // append the length
1030
- b.push(Math.floor(sha1._length / 0x100000000));
1031
- b.push(sha1._length | 0);
1032
-
1033
- while (b.length) {
1034
- sha1._block(b.splice(0, 16));
1035
- }
1036
-
1037
- sha1.reset();
1038
- return h;
1039
- }
1040
-
1041
- /**
1042
- * The SHA-1 logical functions f(0), f(1), ..., f(79).
1043
- * @private
1044
- */
1045
- _f(t, b, c, d) {
1046
- if (t <= 19) {
1047
- return (b & c) | (~b & d);
1048
- } else if (t <= 39) {
1049
- return b ^ c ^ d;
1050
- } else if (t <= 59) {
1051
- return (b & c) | (b & d) | (c & d);
1052
- } else if (t <= 79) {
1053
- return b ^ c ^ d;
1054
- }
1055
- }
1056
-
1057
- /**
1058
- * Circular left-shift operator.
1059
- * @private
1060
- */
1061
- _S(n, x) {
1062
- return (x << n) | (x >>> 32 - n);
1063
- }
1064
-
1065
- /**
1066
- * Perform one cycle of SHA-1.
1067
- * @param {Uint32Array|bitArray} words one block of words.
1068
- * @private
1069
- */
1070
- _block(words) {
1071
- const sha1 = this;
1072
- const h = sha1._h;
1073
- // When words is passed to _block, it has 16 elements. SHA1 _block
1074
- // function extends words with new elements (at the end there are 80 elements).
1075
- // The problem is that if we use Uint32Array instead of Array,
1076
- // the length of Uint32Array cannot be changed. Thus, we replace words with a
1077
- // normal Array here.
1078
- const w = Array(80); // do not use Uint32Array here as the instantiation is slower
1079
- for (let j = 0; j < 16; j++) {
1080
- w[j] = words[j];
1081
- }
1082
-
1083
- let a = h[0];
1084
- let b = h[1];
1085
- let c = h[2];
1086
- let d = h[3];
1087
- let e = h[4];
1088
-
1089
- for (let t = 0; t <= 79; t++) {
1090
- if (t >= 16) {
1091
- w[t] = sha1._S(1, w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]);
1092
- }
1093
- const tmp = (sha1._S(5, a) + sha1._f(t, b, c, d) + e + w[t] +
1094
- sha1._key[Math.floor(t / 20)]) | 0;
1095
- e = d;
1096
- d = c;
1097
- c = sha1._S(30, b);
1098
- b = a;
1099
- a = tmp;
797
+ },
798
+ digest() {
799
+ return hmac.digest();
1100
800
  }
801
+ };
1101
802
 
1102
- h[0] = (h[0] + a) | 0;
1103
- h[1] = (h[1] + b) | 0;
1104
- h[2] = (h[2] + c) | 0;
1105
- h[3] = (h[3] + d) | 0;
1106
- h[4] = (h[4] + e) | 0;
803
+ function encrypt(data) {
804
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
805
+ const length = data.length;
806
+ let offset = 0;
807
+ for (; offset + BLOCK_LENGTH$1 <= length; offset += BLOCK_LENGTH$1) {
808
+ nextKeystream();
809
+ view.setInt32(offset, view.getInt32(offset) ^ keystream[0]);
810
+ view.setInt32(offset + 4, view.getInt32(offset + 4) ^ keystream[1]);
811
+ view.setInt32(offset + 8, view.getInt32(offset + 8) ^ keystream[2]);
812
+ view.setInt32(offset + 12, view.getInt32(offset + 12) ^ keystream[3]);
813
+ }
814
+ if (offset < length) {
815
+ nextKeystream();
816
+ for (let indexByte = 0; offset < length; offset++, indexByte++) {
817
+ data[offset] ^= keystream[indexByte >> 2] >>> (24 - 8 * (indexByte & 3));
818
+ }
819
+ }
820
+ }
821
+
822
+ function nextKeystream() {
823
+ for (let indexByte = 0; indexByte < BLOCK_LENGTH$1; indexByte++) {
824
+ counter[indexByte]++;
825
+ if (counter[indexByte] !== 0) {
826
+ break;
827
+ }
828
+ }
829
+ let s0 = ((counter[0] << 24) | (counter[1] << 16) | (counter[2] << 8) | counter[3]) ^ roundKeys[0];
830
+ let s1 = ((counter[4] << 24) | (counter[5] << 16) | (counter[6] << 8) | counter[7]) ^ roundKeys[1];
831
+ let s2 = ((counter[8] << 24) | (counter[9] << 16) | (counter[10] << 8) | counter[11]) ^ roundKeys[2];
832
+ let s3 = ((counter[12] << 24) | (counter[13] << 16) | (counter[14] << 8) | counter[15]) ^ roundKeys[3];
833
+ let indexKey = 4;
834
+ for (let round = 1; round < rounds; round++, indexKey += 4) {
835
+ const t0 = T0[s0 >>> 24] ^ T1[(s1 >>> 16) & 255] ^ T2[(s2 >>> 8) & 255] ^ T3[s3 & 255] ^ roundKeys[indexKey];
836
+ const t1 = T0[s1 >>> 24] ^ T1[(s2 >>> 16) & 255] ^ T2[(s3 >>> 8) & 255] ^ T3[s0 & 255] ^ roundKeys[indexKey + 1];
837
+ const t2 = T0[s2 >>> 24] ^ T1[(s3 >>> 16) & 255] ^ T2[(s0 >>> 8) & 255] ^ T3[s1 & 255] ^ roundKeys[indexKey + 2];
838
+ const t3 = T0[s3 >>> 24] ^ T1[(s0 >>> 16) & 255] ^ T2[(s1 >>> 8) & 255] ^ T3[s2 & 255] ^ roundKeys[indexKey + 3];
839
+ s0 = t0;
840
+ s1 = t1;
841
+ s2 = t2;
842
+ s3 = t3;
843
+ }
844
+ 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];
845
+ 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];
846
+ 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];
847
+ 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];
848
+ }
849
+ }
850
+
851
+ function pbkdf2(password, salt, iterations, length) {
852
+ const hmac = createHmac(password);
853
+ const result = new Uint8Array(length);
854
+ const block = new Uint8Array(salt.length + 4);
855
+ const blockView = new DataView(block.buffer);
856
+ block.set(salt);
857
+ for (let indexBlock = 1, offset = 0; offset < length; indexBlock++, offset += SHA1_DIGEST_LENGTH) {
858
+ blockView.setUint32(salt.length, indexBlock);
859
+ hmac.update(block, 0, block.length);
860
+ let previous = hmac.digest();
861
+ const output = previous.slice();
862
+ for (let iteration = 1; iteration < iterations; iteration++) {
863
+ hmac.update(previous, 0, SHA1_DIGEST_LENGTH);
864
+ previous = hmac.digest();
865
+ for (let indexByte = 0; indexByte < SHA1_DIGEST_LENGTH; indexByte++) {
866
+ output[indexByte] ^= previous[indexByte];
867
+ }
868
+ }
869
+ result.set(output.subarray(0, Math.min(SHA1_DIGEST_LENGTH, length - offset)), offset);
1107
870
  }
1108
- };
1109
-
1110
- /** @fileOverview Low-level AES implementation.
1111
- *
1112
- * This file contains a low-level implementation of AES, optimized for
1113
- * size and for efficiency on several browsers. It is based on
1114
- * OpenSSL's aes_core.c, a public-domain implementation by Vincent
1115
- * Rijmen, Antoon Bosselaers and Paulo Barreto.
1116
- *
1117
- * An older version of this implementation is available in the public
1118
- * domain, but this one is (c) Emily Stark, Mike Hamburg, Dan Boneh,
1119
- * Stanford University 2008-2010 and BSD-licensed for liability
1120
- * reasons.
1121
- *
1122
- * @author Emily Stark
1123
- * @author Mike Hamburg
1124
- * @author Dan Boneh
1125
- */
1126
-
1127
- const cipher = {};
1128
-
1129
- /**
1130
- * Schedule out an AES key for both encryption and decryption. This
1131
- * is a low-level class. Use a cipher mode to do bulk encryption.
1132
- *
1133
- * @constructor
1134
- * @param {Array} key The key as an array of 4, 6 or 8 words.
1135
- */
1136
- cipher.aes = class {
1137
- constructor(key) {
1138
- /**
1139
- * The expanded S-box and inverse S-box tables. These will be computed
1140
- * on the client so that we don't have to send them down the wire.
1141
- *
1142
- * There are two tables, _tables[0] is for encryption and
1143
- * _tables[1] is for decryption.
1144
- *
1145
- * The first 4 sub-tables are the expanded S-box with MixColumns. The
1146
- * last (_tables[01][4]) is the S-box itself.
1147
- *
1148
- * @private
1149
- */
1150
- const aes = this;
1151
- aes._tables = [[[], [], [], [], []], [[], [], [], [], []]];
1152
-
1153
- if (!aes._tables[0][0][0]) {
1154
- aes._precompute();
1155
- }
1156
-
1157
- const sbox = aes._tables[0][4];
1158
- const decTable = aes._tables[1];
1159
- const keyLen = key.length;
1160
-
1161
- let i, encKey, decKey, rcon = 1;
1162
-
1163
- if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) {
1164
- throw new Error("invalid aes key size");
1165
- }
1166
-
1167
- aes._key = [encKey = key.slice(0), decKey = []];
1168
-
1169
- // schedule encryption keys
1170
- for (i = keyLen; i < 4 * keyLen + 28; i++) {
1171
- let tmp = encKey[i - 1];
1172
-
1173
- // apply sbox
1174
- if (i % keyLen === 0 || (keyLen === 8 && i % keyLen === 4)) {
1175
- tmp = sbox[tmp >>> 24] << 24 ^ sbox[tmp >> 16 & 255] << 16 ^ sbox[tmp >> 8 & 255] << 8 ^ sbox[tmp & 255];
1176
-
1177
- // shift rows and add rcon
1178
- if (i % keyLen === 0) {
1179
- tmp = tmp << 8 ^ tmp >>> 24 ^ rcon << 24;
1180
- rcon = rcon << 1 ^ (rcon >> 7) * 283;
1181
- }
1182
- }
1183
-
1184
- encKey[i] = encKey[i - keyLen] ^ tmp;
1185
- }
871
+ return result;
872
+ }
1186
873
 
1187
- // schedule decryption keys
1188
- for (let j = 0; i; j++, i--) {
1189
- const tmp = encKey[j & 3 ? i : i - 4];
1190
- if (i <= 4 || j < 4) {
1191
- decKey[j] = tmp;
1192
- } else {
1193
- decKey[j] = decTable[0][sbox[tmp >>> 24]] ^
1194
- decTable[1][sbox[tmp >> 16 & 255]] ^
1195
- decTable[2][sbox[tmp >> 8 & 255]] ^
1196
- decTable[3][sbox[tmp & 255]];
1197
- }
1198
- }
1199
- }
1200
- // public
1201
- /* Something like this might appear here eventually
1202
- name: "AES",
1203
- blockSize: 4,
1204
- keySizes: [4,6,8],
1205
- */
1206
-
1207
- /**
1208
- * Encrypt an array of 4 big-endian words.
1209
- * @param {Array} data The plaintext.
1210
- * @return {Array} The ciphertext.
1211
- */
1212
- encrypt(data) {
1213
- return this._crypt(data, 0);
1214
- }
1215
-
1216
- /**
1217
- * Decrypt an array of 4 big-endian words.
1218
- * @param {Array} data The ciphertext.
1219
- * @return {Array} The plaintext.
1220
- */
1221
- decrypt(data) {
1222
- return this._crypt(data, 1);
1223
- }
1224
-
1225
- /**
1226
- * Expand the S-box tables.
1227
- *
1228
- * @private
1229
- */
1230
- _precompute() {
1231
- const encTable = this._tables[0];
1232
- const decTable = this._tables[1];
1233
- const sbox = encTable[4];
1234
- const sboxInv = decTable[4];
1235
- const d = [];
1236
- const th = [];
1237
- let xInv, x2, x4, x8;
1238
-
1239
- // Compute double and third tables
1240
- for (let i = 0; i < 256; i++) {
1241
- th[(d[i] = i << 1 ^ (i >> 7) * 283) ^ i] = i;
1242
- }
1243
-
1244
- for (let x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) {
1245
- // Compute sbox
1246
- let s = xInv ^ xInv << 1 ^ xInv << 2 ^ xInv << 3 ^ xInv << 4;
1247
- s = s >> 8 ^ s & 255 ^ 99;
1248
- sbox[x] = s;
1249
- sboxInv[s] = x;
1250
-
1251
- // Compute MixColumns
1252
- x8 = d[x4 = d[x2 = d[x]]];
1253
- let tDec = x8 * 0x1010101 ^ x4 * 0x10001 ^ x2 * 0x101 ^ x * 0x1010100;
1254
- let tEnc = d[s] * 0x101 ^ s * 0x1010100;
1255
-
1256
- for (let i = 0; i < 4; i++) {
1257
- encTable[i][x] = tEnc = tEnc << 24 ^ tEnc >>> 8;
1258
- decTable[i][s] = tDec = tDec << 24 ^ tDec >>> 8;
1259
- }
1260
- }
1261
-
1262
- // Compactify. Considerable speedup on Firefox.
1263
- for (let i = 0; i < 5; i++) {
1264
- encTable[i] = encTable[i].slice(0);
1265
- decTable[i] = decTable[i].slice(0);
1266
- }
1267
- }
1268
-
1269
- /**
1270
- * Encryption and decryption core.
1271
- * @param {Array} input Four words to be encrypted or decrypted.
1272
- * @param dir The direction, 0 for encrypt and 1 for decrypt.
1273
- * @return {Array} The four encrypted or decrypted words.
1274
- * @private
1275
- */
1276
- _crypt(input, dir) {
1277
- if (input.length !== 4) {
1278
- throw new Error("invalid aes block size");
1279
- }
1280
-
1281
- const key = this._key[dir];
1282
-
1283
- const nInnerRounds = key.length / 4 - 2;
1284
- const out = [0, 0, 0, 0];
1285
- const table = this._tables[dir];
1286
-
1287
- // load up the tables
1288
- const t0 = table[0];
1289
- const t1 = table[1];
1290
- const t2 = table[2];
1291
- const t3 = table[3];
1292
- const sbox = table[4];
1293
-
1294
- // state variables a,b,c,d are loaded with pre-whitened data
1295
- let a = input[0] ^ key[0];
1296
- let b = input[dir ? 3 : 1] ^ key[1];
1297
- let c = input[2] ^ key[2];
1298
- let d = input[dir ? 1 : 3] ^ key[3];
1299
- let kIndex = 4;
1300
- let a2, b2, c2;
1301
-
1302
- // Inner rounds. Cribbed from OpenSSL.
1303
- for (let i = 0; i < nInnerRounds; i++) {
1304
- a2 = t0[a >>> 24] ^ t1[b >> 16 & 255] ^ t2[c >> 8 & 255] ^ t3[d & 255] ^ key[kIndex];
1305
- b2 = t0[b >>> 24] ^ t1[c >> 16 & 255] ^ t2[d >> 8 & 255] ^ t3[a & 255] ^ key[kIndex + 1];
1306
- c2 = t0[c >>> 24] ^ t1[d >> 16 & 255] ^ t2[a >> 8 & 255] ^ t3[b & 255] ^ key[kIndex + 2];
1307
- d = t0[d >>> 24] ^ t1[a >> 16 & 255] ^ t2[b >> 8 & 255] ^ t3[c & 255] ^ key[kIndex + 3];
1308
- kIndex += 4;
1309
- a = a2; b = b2; c = c2;
1310
- }
1311
-
1312
- // Last round.
1313
- for (let i = 0; i < 4; i++) {
1314
- out[dir ? 3 & -i : i] =
1315
- sbox[a >>> 24] << 24 ^
1316
- sbox[b >> 16 & 255] << 16 ^
1317
- sbox[c >> 8 & 255] << 8 ^
1318
- sbox[d & 255] ^
1319
- key[kIndex++];
1320
- a2 = a; a = b; b = c; c = d; d = a2;
1321
- }
1322
-
1323
- return out;
874
+ function createHmac(key) {
875
+ const sha1 = createSha1();
876
+ const innerKey = new Uint8Array(SHA1_BLOCK_LENGTH);
877
+ const outerKey = new Uint8Array(SHA1_BLOCK_LENGTH);
878
+ if (key.length > SHA1_BLOCK_LENGTH) {
879
+ sha1.update(key, 0, key.length);
880
+ key = sha1.digest();
1324
881
  }
1325
- };
1326
-
1327
- /** @fileOverview CTR mode implementation.
1328
- *
1329
- * Special thanks to Roy Nicholson for pointing out a bug in our
1330
- * implementation.
1331
- *
1332
- * @author Emily Stark
1333
- * @author Mike Hamburg
1334
- * @author Dan Boneh
1335
- */
1336
-
1337
- /** Brian Gladman's CTR Mode.
1338
- * @constructor
1339
- * @param {Object} _prf The aes instance to generate key.
1340
- * @param {bitArray} _iv The iv for ctr mode, it must be 128 bits.
1341
- */
1342
-
1343
- const mode = {};
1344
-
1345
- /**
1346
- * Brian Gladman's CTR Mode.
1347
- * @namespace
1348
- */
1349
- mode.ctrGladman = class {
1350
- constructor(prf, iv) {
1351
- this._prf = prf;
1352
- this._initIv = iv;
1353
- this._iv = iv;
882
+ for (let indexByte = 0; indexByte < SHA1_BLOCK_LENGTH; indexByte++) {
883
+ const keyByte = indexByte < key.length ? key[indexByte] : 0;
884
+ innerKey[indexByte] = keyByte ^ HMAC_INNER_PADDING;
885
+ outerKey[indexByte] = keyByte ^ HMAC_OUTER_PADDING;
1354
886
  }
887
+ sha1.update(innerKey, 0, SHA1_BLOCK_LENGTH);
888
+ return {
889
+ update(data, offset, length) {
890
+ sha1.update(data, offset, length);
891
+ },
892
+ digest() {
893
+ const innerDigest = sha1.digest();
894
+ sha1.update(outerKey, 0, SHA1_BLOCK_LENGTH);
895
+ sha1.update(innerDigest, 0, SHA1_DIGEST_LENGTH);
896
+ const result = sha1.digest();
897
+ sha1.update(innerKey, 0, SHA1_BLOCK_LENGTH);
898
+ return result;
899
+ }
900
+ };
901
+ }
1355
902
 
1356
- reset() {
1357
- this._iv = this._initIv;
1358
- }
903
+ function createSha1() {
904
+ const state = new Int32Array(SHA1_INITIAL_STATE);
905
+ const schedule = new Int32Array(SHA1_SCHEDULE_LENGTH);
906
+ const block = new Uint8Array(SHA1_BLOCK_LENGTH);
907
+ const blockView = new DataView(block.buffer);
908
+ const lengthBytes = new Uint8Array(8);
909
+ let blockLength = 0;
910
+ let totalLength = 0;
911
+ return {
912
+ update,
913
+ digest
914
+ };
1359
915
 
1360
- /** Input some data to calculate.
1361
- * @param {bitArray} data the data to process, it must be intergral multiple of 128 bits unless it's the last.
1362
- */
1363
- update(data) {
1364
- return this.calculate(this._prf, data, this._iv);
916
+ function update(data, offset, length) {
917
+ const end = offset + length;
918
+ totalLength += length;
919
+ if (blockLength) {
920
+ while (offset < end && blockLength < SHA1_BLOCK_LENGTH) {
921
+ block[blockLength++] = data[offset++];
922
+ }
923
+ if (blockLength == SHA1_BLOCK_LENGTH) {
924
+ compress(blockView, 0);
925
+ blockLength = 0;
926
+ }
927
+ }
928
+ if (offset + SHA1_BLOCK_LENGTH <= end) {
929
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
930
+ for (; offset + SHA1_BLOCK_LENGTH <= end; offset += SHA1_BLOCK_LENGTH) {
931
+ compress(view, offset);
932
+ }
933
+ }
934
+ while (offset < end) {
935
+ block[blockLength++] = data[offset++];
936
+ }
937
+ }
938
+
939
+ function digest() {
940
+ const bits = totalLength * 8;
941
+ const high = Math.floor(bits / 0x100000000);
942
+ const low = bits >>> 0;
943
+ update(SHA1_PADDING, 0, 1);
944
+ while (blockLength != SHA1_LENGTH_OFFSET) {
945
+ update(SHA1_ZERO, 0, 1);
946
+ }
947
+ lengthBytes[0] = high >>> 24;
948
+ lengthBytes[1] = high >>> 16;
949
+ lengthBytes[2] = high >>> 8;
950
+ lengthBytes[3] = high;
951
+ lengthBytes[4] = low >>> 24;
952
+ lengthBytes[5] = low >>> 16;
953
+ lengthBytes[6] = low >>> 8;
954
+ lengthBytes[7] = low;
955
+ update(lengthBytes, 0, 8);
956
+ const result = new Uint8Array(SHA1_DIGEST_LENGTH);
957
+ const resultView = new DataView(result.buffer);
958
+ for (let indexWord = 0; indexWord < state.length; indexWord++) {
959
+ resultView.setInt32(4 * indexWord, state[indexWord]);
960
+ }
961
+ state.set(SHA1_INITIAL_STATE);
962
+ blockLength = 0;
963
+ totalLength = 0;
964
+ return result;
1365
965
  }
1366
966
 
1367
- incWord(word) {
1368
- if (((word >> 24) & 0xff) === 0xff) { //overflow
1369
- let b1 = (word >> 16) & 0xff;
1370
- let b2 = (word >> 8) & 0xff;
1371
- let b3 = word & 0xff;
1372
-
1373
- if (b1 === 0xff) { // overflow b1
1374
- b1 = 0;
1375
- if (b2 === 0xff) {
1376
- b2 = 0;
1377
- if (b3 === 0xff) {
1378
- b3 = 0;
1379
- } else {
1380
- ++b3;
1381
- }
1382
- } else {
1383
- ++b2;
1384
- }
1385
- } else {
1386
- ++b1;
1387
- }
1388
-
1389
- word = 0;
1390
- word += (b1 << 16);
1391
- word += (b2 << 8);
1392
- word += b3;
1393
- } else {
1394
- word += (0x01 << 24);
967
+ function compress(view, offset) {
968
+ for (let index = 0; index < 16; index++) {
969
+ schedule[index] = view.getInt32(offset + 4 * index);
1395
970
  }
1396
- return word;
1397
- }
1398
-
1399
- incCounter(counter) {
1400
- if ((counter[0] = this.incWord(counter[0])) === 0) {
1401
- // encr_data in fileenc.c from Dr Brian Gladman's counts only with DWORD j < 8
1402
- counter[1] = this.incWord(counter[1]);
971
+ for (let index = 16; index < SHA1_SCHEDULE_LENGTH; index++) {
972
+ const word = schedule[index - 3] ^ schedule[index - 8] ^ schedule[index - 14] ^ schedule[index - 16];
973
+ schedule[index] = (word << 1) | (word >>> 31);
1403
974
  }
1404
- }
1405
-
1406
- calculate(prf, data, iv) {
1407
- let l;
1408
- if (!(l = data.length)) {
1409
- return [];
975
+ let a = state[0];
976
+ let b = state[1];
977
+ let c = state[2];
978
+ let d = state[3];
979
+ let e = state[4];
980
+ let t;
981
+ for (let index = 0; index < 20; index++) {
982
+ t = (((a << 5) | (a >>> 27)) + ((b & c) | (~b & d)) + e + 0x5A827999 + schedule[index]) | 0;
983
+ e = d;
984
+ d = c;
985
+ c = (b << 30) | (b >>> 2);
986
+ b = a;
987
+ a = t;
988
+ }
989
+ for (let index = 20; index < 40; index++) {
990
+ t = (((a << 5) | (a >>> 27)) + (b ^ c ^ d) + e + 0x6ED9EBA1 + schedule[index]) | 0;
991
+ e = d;
992
+ d = c;
993
+ c = (b << 30) | (b >>> 2);
994
+ b = a;
995
+ a = t;
1410
996
  }
1411
- const bl = bitArray.bitLength(data);
1412
- for (let i = 0; i < l; i += 4) {
1413
- this.incCounter(iv);
1414
- const e = prf.encrypt(iv);
1415
- data[i] ^= e[0];
1416
- data[i + 1] ^= e[1];
1417
- data[i + 2] ^= e[2];
1418
- data[i + 3] ^= e[3];
997
+ for (let index = 40; index < 60; index++) {
998
+ t = (((a << 5) | (a >>> 27)) + ((b & c) | (b & d) | (c & d)) + e + 0x8F1BBCDC + schedule[index]) | 0;
999
+ e = d;
1000
+ d = c;
1001
+ c = (b << 30) | (b >>> 2);
1002
+ b = a;
1003
+ a = t;
1419
1004
  }
1420
- return bitArray.clamp(data, bl);
1005
+ for (let index = 60; index < SHA1_SCHEDULE_LENGTH; index++) {
1006
+ t = (((a << 5) | (a >>> 27)) + (b ^ c ^ d) + e + 0xCA62C1D6 + schedule[index]) | 0;
1007
+ e = d;
1008
+ d = c;
1009
+ c = (b << 30) | (b >>> 2);
1010
+ b = a;
1011
+ a = t;
1012
+ }
1013
+ state[0] = (state[0] + a) | 0;
1014
+ state[1] = (state[1] + b) | 0;
1015
+ state[2] = (state[2] + c) | 0;
1016
+ state[3] = (state[3] + d) | 0;
1017
+ state[4] = (state[4] + e) | 0;
1421
1018
  }
1422
- };
1019
+ }
1423
1020
 
1424
- const misc = {
1425
- importKey(password) {
1426
- return new misc.hmacSha1(codec.bytes.toBits(password));
1427
- },
1428
- pbkdf2(prf, salt, count, length) {
1429
- count = count || 10000;
1430
- if (length < 0 || count < 0) {
1431
- throw new Error("invalid params to pbkdf2");
1432
- }
1433
- const byteLength = ((length >> 5) + 1) << 2;
1434
- let u, ui, i, j, k;
1435
- const arrayBuffer = new ArrayBuffer(byteLength);
1436
- const out = new DataView(arrayBuffer);
1437
- let outLength = 0;
1438
- const b = bitArray;
1439
- salt = codec.bytes.toBits(salt);
1440
- for (k = 1; outLength < (byteLength || 1); k++) {
1441
- u = ui = prf.encrypt(b.concat(salt, [k]));
1442
- for (i = 1; i < count; i++) {
1443
- ui = prf.encrypt(ui);
1444
- for (j = 0; j < ui.length; j++) {
1445
- u[j] ^= ui[j];
1446
- }
1447
- }
1448
- for (i = 0; outLength < (byteLength || 1) && i < u.length; i++) {
1449
- out.setInt32(outLength, u[i]);
1450
- outLength += 4;
1021
+ function initTables() {
1022
+ if (!tablesInitialized) {
1023
+ let p = 1;
1024
+ let q = 1;
1025
+ do {
1026
+ p = (p ^ (p << 1) ^ ((p & 0x80) ? 0x1b : 0)) & 255;
1027
+ q = (q ^ (q << 1)) & 255;
1028
+ q = (q ^ (q << 2)) & 255;
1029
+ q = (q ^ (q << 4)) & 255;
1030
+ if (q & 0x80) {
1031
+ q ^= 0x09;
1451
1032
  }
1033
+ S_BOX[p] = (q ^ ((q << 1) | (q >> 7)) ^ ((q << 2) | (q >> 6)) ^ ((q << 3) | (q >> 5)) ^ ((q << 4) | (q >> 4)) ^ 0x63) & 255;
1034
+ } while (p != 1);
1035
+ S_BOX[0] = 0x63;
1036
+ for (let index = 0; index < 256; index++) {
1037
+ const s = S_BOX[index];
1038
+ const s2 = multiplyByTwo(s);
1039
+ const t = (s2 << 24) | (s << 16) | (s << 8) | (s2 ^ s);
1040
+ T0[index] = t;
1041
+ T1[index] = (t >>> 8) | (t << 24);
1042
+ T2[index] = (t >>> 16) | (t << 16);
1043
+ T3[index] = (t >>> 24) | (t << 8);
1452
1044
  }
1453
- return arrayBuffer.slice(0, length / 8);
1045
+ tablesInitialized = true;
1454
1046
  }
1455
- };
1456
-
1457
- /** @fileOverview HMAC implementation.
1458
- *
1459
- * @author Emily Stark
1460
- * @author Mike Hamburg
1461
- * @author Dan Boneh
1462
- */
1463
-
1464
- /** HMAC with the specified hash function.
1465
- * @constructor
1466
- * @param {bitArray} key the key for HMAC.
1467
- * @param {Object} [Hash=hash.sha1] The hash function to use.
1468
- */
1469
- misc.hmacSha1 = class {
1470
-
1471
- constructor(key) {
1472
- const hmac = this;
1473
- const Hash = hmac._hash = hash.sha1;
1474
- const exKey = [[], []];
1475
- hmac._baseHash = [new Hash(), new Hash()];
1476
- const bs = hmac._baseHash[0].blockSize / 32;
1477
-
1478
- if (key.length > bs) {
1479
- key = new Hash().update(key).finalize();
1480
- }
1481
-
1482
- for (let i = 0; i < bs; i++) {
1483
- exKey[0][i] = key[i] ^ 0x36363636;
1484
- exKey[1][i] = key[i] ^ 0x5C5C5C5C;
1485
- }
1047
+ }
1486
1048
 
1487
- hmac._baseHash[0].update(exKey[0]);
1488
- hmac._baseHash[1].update(exKey[1]);
1489
- hmac._resultHash = new Hash(hmac._baseHash[0]);
1049
+ function expandKey(key, roundKeys) {
1050
+ const keyWords = key.length >> 2;
1051
+ const rounds = keyWords + 6;
1052
+ const total = 4 * (rounds + 1);
1053
+ let roundConstant = 1;
1054
+ for (let index = 0; index < keyWords; index++) {
1055
+ roundKeys[index] = (key[4 * index] << 24) | (key[4 * index + 1] << 16) | (key[4 * index + 2] << 8) | key[4 * index + 3];
1490
1056
  }
1491
- reset() {
1492
- const hmac = this;
1493
- hmac._resultHash = new hmac._hash(hmac._baseHash[0]);
1494
- hmac._updated = false;
1495
- }
1496
-
1497
- update(data) {
1498
- const hmac = this;
1499
- hmac._updated = true;
1500
- hmac._resultHash.update(data);
1057
+ for (let index = keyWords; index < total; index++) {
1058
+ let word = roundKeys[index - 1];
1059
+ if (index % keyWords == 0) {
1060
+ word = substituteWord((word << 8) | (word >>> 24)) ^ (roundConstant << 24);
1061
+ roundConstant = multiplyByTwo(roundConstant);
1062
+ } else if (keyWords > 6 && index % keyWords == 4) {
1063
+ word = substituteWord(word);
1064
+ }
1065
+ roundKeys[index] = roundKeys[index - keyWords] ^ word;
1501
1066
  }
1067
+ return rounds;
1068
+ }
1502
1069
 
1503
- digest() {
1504
- const hmac = this;
1505
- const w = hmac._resultHash.finalize();
1506
- const result = new (hmac._hash)(hmac._baseHash[1]).update(w).finalize();
1507
-
1508
- hmac.reset();
1509
-
1510
- return result;
1511
- }
1070
+ function substituteWord(word) {
1071
+ return (S_BOX[word >>> 24] << 24) | (S_BOX[(word >>> 16) & 255] << 16) | (S_BOX[(word >>> 8) & 255] << 8) | S_BOX[word & 255];
1072
+ }
1512
1073
 
1513
- encrypt(data) {
1514
- if (!this._updated) {
1515
- this.update(data);
1516
- return this.digest(data);
1517
- } else {
1518
- throw new Error("encrypt on already updated hmac called!");
1519
- }
1520
- }
1521
- };
1074
+ function multiplyByTwo(value) {
1075
+ return ((value << 1) ^ ((value >> 7) * 0x1b)) & 255;
1076
+ }
1522
1077
 
1523
1078
  /*
1524
1079
  Copyright (c) 2022 Gildas Lormeau. All rights reserved.
@@ -1573,8 +1128,8 @@ function getRandomValues(array) {
1573
1128
  1. Redistributions of source code must retain the above copyright notice,
1574
1129
  this list of conditions and the following disclaimer.
1575
1130
 
1576
- 2. Redistributions in binary form must reproduce the above copyright
1577
- notice, this list of conditions and the following disclaimer in
1131
+ 2. Redistributions in binary form must reproduce the above copyright
1132
+ notice, this list of conditions and the following disclaimer in
1578
1133
  the documentation and/or other materials provided with the distribution.
1579
1134
 
1580
1135
  3. The names of the authors may not be used to endorse or promote products
@@ -1598,24 +1153,21 @@ const RAW_FORMAT = "raw";
1598
1153
  const PBKDF2_ALGORITHM = { name: "PBKDF2" };
1599
1154
  const HASH_ALGORITHM = { name: "HMAC" };
1600
1155
  const HASH_FUNCTION = "SHA-1";
1156
+ const PBKDF2_ITERATIONS = 1000;
1601
1157
  const BASE_KEY_ALGORITHM = Object.assign({ hash: HASH_ALGORITHM }, PBKDF2_ALGORITHM);
1602
- const DERIVED_BITS_ALGORITHM = Object.assign({ iterations: 1000, hash: { name: HASH_FUNCTION } }, PBKDF2_ALGORITHM);
1158
+ const DERIVED_BITS_ALGORITHM = Object.assign({ iterations: PBKDF2_ITERATIONS, hash: { name: HASH_FUNCTION } }, PBKDF2_ALGORITHM);
1603
1159
  const DERIVED_BITS_USAGE = ["deriveBits"];
1604
1160
  const SALT_LENGTH = [8, 12, 16];
1605
1161
  const KEY_LENGTH = [16, 24, 32];
1606
1162
  const AUTHENTICATION_CODE_LENGTH = 10;
1607
- const COUNTER_DEFAULT_VALUE = [0, 0, 0, 0];
1163
+ const PASSWORD_VERIFICATION_LENGTH = 2;
1608
1164
  // deno-lint-ignore valid-typeof
1609
1165
  const CRYPTO_API_SUPPORTED = typeof crypto != UNDEFINED_TYPE;
1610
1166
  const subtle = CRYPTO_API_SUPPORTED && crypto.subtle;
1611
1167
  const SUBTLE_API_SUPPORTED = CRYPTO_API_SUPPORTED && typeof subtle != UNDEFINED_TYPE;
1612
- const codecBytes = codec.bytes;
1613
- const Aes = cipher.aes;
1614
- const CtrGladman = mode.ctrGladman;
1615
- const HmacSha1 = misc.hmacSha1;
1616
1168
 
1617
- let IMPORT_KEY_SUPPORTED = CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && typeof subtle.importKey == FUNCTION_TYPE;
1618
- let DERIVE_BITS_SUPPORTED = CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && typeof subtle.deriveBits == FUNCTION_TYPE;
1169
+ let DERIVE_BITS_SUPPORTED = SUBTLE_API_SUPPORTED && typeof subtle.importKey == FUNCTION_TYPE && typeof subtle.deriveBits == FUNCTION_TYPE;
1170
+ let createEngine$1 = createEngine$2;
1619
1171
 
1620
1172
  class AESDecryptionStream extends TransformStream {
1621
1173
 
@@ -1633,9 +1185,10 @@ class AESDecryptionStream extends TransformStream {
1633
1185
  ready
1634
1186
  } = aesCrypto;
1635
1187
  if (password) {
1636
- await createDecryptionKeys(aesCrypto, strength, password, subarray(chunk, 0, SALT_LENGTH[strength] + 2));
1637
- chunk = subarray(chunk, SALT_LENGTH[strength] + 2);
1188
+ await createDecryptionKeys(aesCrypto, strength, password, subarray(chunk, 0, SALT_LENGTH[strength] + PASSWORD_VERIFICATION_LENGTH));
1189
+ chunk = subarray(chunk, SALT_LENGTH[strength] + PASSWORD_VERIFICATION_LENGTH);
1638
1190
  if (checkPasswordOnly) {
1191
+ disposeEngine(aesCrypto);
1639
1192
  controller.error(new Error(ERR_ABORT_CHECK_PASSWORD));
1640
1193
  } else {
1641
1194
  resolveReady();
@@ -1648,23 +1201,16 @@ class AESDecryptionStream extends TransformStream {
1648
1201
  },
1649
1202
  async flush(controller) {
1650
1203
  const {
1651
- ctr,
1652
- hmac,
1204
+ engine,
1653
1205
  pendingInput,
1654
1206
  ready
1655
1207
  } = this;
1656
- if (hmac && ctr) {
1208
+ if (engine) {
1657
1209
  await ready;
1658
- const chunkToDecrypt = subarray(pendingInput, 0, pendingInput.length - AUTHENTICATION_CODE_LENGTH);
1659
1210
  const originalAuthenticationCode = subarray(pendingInput, pendingInput.length - AUTHENTICATION_CODE_LENGTH);
1660
- let decryptedChunkArray = EMPTY_UINT8_ARRAY;
1661
- if (chunkToDecrypt.length) {
1662
- const encryptedChunk = toBits(codecBytes, chunkToDecrypt);
1663
- hmac.update(encryptedChunk);
1664
- const decryptedChunk = ctr.update(encryptedChunk);
1665
- decryptedChunkArray = fromBits(codecBytes, decryptedChunk);
1666
- }
1667
- const authenticationCode = subarray(fromBits(codecBytes, hmac.digest()), 0, AUTHENTICATION_CODE_LENGTH);
1211
+ const decryptedChunkArray = new Uint8Array(subarray(pendingInput, 0, pendingInput.length - AUTHENTICATION_CODE_LENGTH));
1212
+ engine.process(decryptedChunkArray, true);
1213
+ const authenticationCode = engine.digest();
1668
1214
  let invalidAuthenticationCode = pendingInput.length < AUTHENTICATION_CODE_LENGTH ? 1 : 0;
1669
1215
  for (let indexByte = 0; indexByte < AUTHENTICATION_CODE_LENGTH; indexByte++) {
1670
1216
  invalidAuthenticationCode |= authenticationCode[indexByte] ^ originalAuthenticationCode[indexByte];
@@ -1674,6 +1220,9 @@ class AESDecryptionStream extends TransformStream {
1674
1220
  }
1675
1221
  controller.enqueue(decryptedChunkArray);
1676
1222
  }
1223
+ },
1224
+ cancel() {
1225
+ disposeEngine(this);
1677
1226
  }
1678
1227
  });
1679
1228
  }
@@ -1703,31 +1252,33 @@ class AESEncryptionStream extends TransformStream {
1703
1252
  }
1704
1253
  const output = new Uint8Array(preamble.length + chunk.length - (chunk.length % BLOCK_LENGTH));
1705
1254
  output.set(preamble, 0);
1706
- controller.enqueue(append(aesCrypto, chunk, output, preamble.length, 0));
1255
+ controller.enqueue(append(aesCrypto, chunk, output, preamble.length, 0, false));
1707
1256
  },
1708
1257
  async flush(controller) {
1709
1258
  const {
1710
- ctr,
1711
- hmac,
1259
+ engine,
1712
1260
  pendingInput,
1713
1261
  ready
1714
1262
  } = this;
1715
- if (hmac && ctr) {
1263
+ if (engine) {
1716
1264
  await ready;
1717
- let encryptedChunkArray = EMPTY_UINT8_ARRAY;
1718
- if (pendingInput.length) {
1719
- const encryptedChunk = ctr.update(toBits(codecBytes, pendingInput));
1720
- hmac.update(encryptedChunk);
1721
- encryptedChunkArray = fromBits(codecBytes, encryptedChunk);
1722
- }
1723
- const authenticationCode = fromBits(codecBytes, hmac.digest()).slice(0, AUTHENTICATION_CODE_LENGTH);
1265
+ const encryptedChunkArray = new Uint8Array(pendingInput);
1266
+ engine.process(encryptedChunkArray, false);
1267
+ const authenticationCode = subarray(engine.digest(), 0, AUTHENTICATION_CODE_LENGTH);
1724
1268
  controller.enqueue(concat(encryptedChunkArray, authenticationCode));
1725
1269
  }
1270
+ },
1271
+ cancel() {
1272
+ disposeEngine(this);
1726
1273
  }
1727
1274
  });
1728
1275
  }
1729
1276
  }
1730
1277
 
1278
+ function setAESEngine(createEngineFunction) {
1279
+ createEngine$1 = createEngineFunction || createEngine$2;
1280
+ }
1281
+
1731
1282
  function initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength) {
1732
1283
  Object.assign(aesCrypto, {
1733
1284
  ready: new Promise(resolve => aesCrypto.resolveReady = resolve),
@@ -1737,30 +1288,23 @@ function initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength) {
1737
1288
  });
1738
1289
  }
1739
1290
 
1740
- function append(aesCrypto, input, output, paddingStart, paddingEnd, verifyAuthenticationCode) {
1291
+ function append(aesCrypto, input, output, paddingStart, paddingEnd, decrypt) {
1741
1292
  const {
1742
- ctr,
1743
- hmac,
1293
+ engine,
1744
1294
  pendingInput
1745
1295
  } = aesCrypto;
1746
1296
  if (pendingInput.length) {
1747
1297
  input = concat(pendingInput, input);
1748
1298
  }
1749
1299
  const inputLength = input.length - paddingEnd;
1750
- output = expand(output, paddingStart + (inputLength - (inputLength % BLOCK_LENGTH)));
1751
- let offset;
1752
- for (offset = 0; offset <= inputLength - BLOCK_LENGTH; offset += BLOCK_LENGTH) {
1753
- const inputChunk = toBits(codecBytes, subarray(input, offset, offset + BLOCK_LENGTH));
1754
- if (verifyAuthenticationCode) {
1755
- hmac.update(inputChunk);
1756
- }
1757
- const outputChunk = ctr.update(inputChunk);
1758
- if (!verifyAuthenticationCode) {
1759
- hmac.update(outputChunk);
1760
- }
1761
- output.set(fromBits(codecBytes, outputChunk), offset + paddingStart);
1762
- }
1763
- aesCrypto.pendingInput = subarray(input, offset);
1300
+ const alignedLength = inputLength - (inputLength % BLOCK_LENGTH);
1301
+ output = expand(output, paddingStart + alignedLength);
1302
+ if (alignedLength) {
1303
+ const chunk = subarray(output, paddingStart, paddingStart + alignedLength);
1304
+ chunk.set(subarray(input, 0, alignedLength));
1305
+ engine.process(chunk, decrypt);
1306
+ }
1307
+ aesCrypto.pendingInput = subarray(input, alignedLength);
1764
1308
  return output;
1765
1309
  }
1766
1310
 
@@ -1768,10 +1312,17 @@ async function createDecryptionKeys(decrypt, strength, password, preamble) {
1768
1312
  const passwordVerificationKey = await createKeys$1(decrypt, strength, password, subarray(preamble, 0, SALT_LENGTH[strength]));
1769
1313
  const passwordVerification = subarray(preamble, SALT_LENGTH[strength]);
1770
1314
  if (passwordVerificationKey[0] != passwordVerification[0] || passwordVerificationKey[1] != passwordVerification[1]) {
1315
+ disposeEngine(decrypt);
1771
1316
  throw new Error(ERR_INVALID_PASSWORD);
1772
1317
  }
1773
1318
  }
1774
1319
 
1320
+ function disposeEngine({ engine }) {
1321
+ if (engine && engine.dispose) {
1322
+ engine.dispose();
1323
+ }
1324
+ }
1325
+
1775
1326
  async function createEncryptionKeys(encrypt, strength, password) {
1776
1327
  const salt = getRandomValues(new Uint8Array(SALT_LENGTH[strength]));
1777
1328
  const passwordVerification = await createKeys$1(encrypt, strength, password, salt);
@@ -1780,48 +1331,22 @@ async function createEncryptionKeys(encrypt, strength, password) {
1780
1331
 
1781
1332
  async function createKeys$1(aesCrypto, strength, password, salt) {
1782
1333
  aesCrypto.password = null;
1783
- const baseKey = await importKey(RAW_FORMAT, password, BASE_KEY_ALGORITHM, false, DERIVED_BITS_USAGE);
1784
- const derivedBits = await deriveBits(Object.assign({ salt }, DERIVED_BITS_ALGORITHM), baseKey, 8 * ((KEY_LENGTH[strength] * 2) + 2));
1785
- const compositeKey = new Uint8Array(derivedBits);
1786
- const key = toBits(codecBytes, subarray(compositeKey, 0, KEY_LENGTH[strength]));
1787
- const authentication = toBits(codecBytes, subarray(compositeKey, KEY_LENGTH[strength], KEY_LENGTH[strength] * 2));
1788
- const passwordVerification = subarray(compositeKey, KEY_LENGTH[strength] * 2);
1789
- Object.assign(aesCrypto, {
1790
- keys: {
1791
- key,
1792
- authentication,
1793
- passwordVerification
1794
- },
1795
- ctr: new CtrGladman(new Aes(key), Array.from(COUNTER_DEFAULT_VALUE)),
1796
- hmac: new HmacSha1(authentication)
1797
- });
1798
- return passwordVerification;
1334
+ const keyLength = KEY_LENGTH[strength];
1335
+ const compositeKey = await deriveKey(password, salt, keyLength * 2 + PASSWORD_VERIFICATION_LENGTH);
1336
+ aesCrypto.engine = createEngine$1(subarray(compositeKey, 0, keyLength), subarray(compositeKey, keyLength, keyLength * 2));
1337
+ return subarray(compositeKey, keyLength * 2);
1799
1338
  }
1800
1339
 
1801
- async function importKey(format, password, algorithm, extractable, keyUsages) {
1802
- if (IMPORT_KEY_SUPPORTED) {
1803
- try {
1804
- return await subtle.importKey(format, password, algorithm, extractable, keyUsages);
1805
- } catch {
1806
- IMPORT_KEY_SUPPORTED = false;
1807
- return misc.importKey(password);
1808
- }
1809
- } else {
1810
- return misc.importKey(password);
1811
- }
1812
- }
1813
-
1814
- async function deriveBits(algorithm, baseKey, length) {
1340
+ async function deriveKey(password, salt, length) {
1815
1341
  if (DERIVE_BITS_SUPPORTED) {
1816
1342
  try {
1817
- return await subtle.deriveBits(algorithm, baseKey, length);
1343
+ const baseKey = await subtle.importKey(RAW_FORMAT, password, BASE_KEY_ALGORITHM, false, DERIVED_BITS_USAGE);
1344
+ return new Uint8Array(await subtle.deriveBits(Object.assign({ salt }, DERIVED_BITS_ALGORITHM), baseKey, length * 8));
1818
1345
  } catch {
1819
1346
  DERIVE_BITS_SUPPORTED = false;
1820
- return misc.pbkdf2(baseKey, algorithm.salt, DERIVED_BITS_ALGORITHM.iterations, length);
1821
1347
  }
1822
- } else {
1823
- return misc.pbkdf2(baseKey, algorithm.salt, DERIVED_BITS_ALGORITHM.iterations, length);
1824
1348
  }
1349
+ return pbkdf2(password, salt, PBKDF2_ITERATIONS, length);
1825
1350
  }
1826
1351
 
1827
1352
  function encodePassword(password, rawPassword) {
@@ -1845,13 +1370,6 @@ function subarray(array, begin, end) {
1845
1370
  return array.subarray(begin, end);
1846
1371
  }
1847
1372
 
1848
- function fromBits(codecBytes, chunk) {
1849
- return codecBytes.fromBits(chunk);
1850
- }
1851
- function toBits(codecBytes, chunk) {
1852
- return codecBytes.toBits(chunk);
1853
- }
1854
-
1855
1373
  /*
1856
1374
  Copyright (c) 2022 Gildas Lormeau. All rights reserved.
1857
1375
 
@@ -2795,11 +2313,18 @@ async function supportsDeflate(config) {
2795
2313
  return true;
2796
2314
  }
2797
2315
  if (FallbackStream) {
2316
+ return await loadModule(config);
2317
+ }
2318
+ return false;
2319
+ }
2320
+
2321
+ async function loadModule(config) {
2322
+ if (initModule$1) {
2798
2323
  try {
2799
2324
  await initModule$1(config);
2800
2325
  return true;
2801
2326
  } catch {
2802
- return false;
2327
+ // ignored
2803
2328
  }
2804
2329
  }
2805
2330
  return false;
@@ -2842,26 +2367,27 @@ class CodecWorker {
2842
2367
  terminate() {
2843
2368
  return new Promise(resolve => {
2844
2369
  const { worker, busy } = workerData;
2845
- if (worker) {
2846
- if (busy) {
2847
- workerData.resolveTerminated = resolve;
2848
- } else {
2370
+ if (busy) {
2371
+ workerData.resolveTerminated = resolve;
2372
+ } else {
2373
+ if (worker) {
2849
2374
  worker.terminate();
2850
- resolve();
2375
+ workerData.worker = null;
2851
2376
  }
2852
- workerData.interface = null;
2853
- } else {
2854
2377
  resolve();
2855
2378
  }
2379
+ workerData.interface = null;
2856
2380
  });
2857
2381
  },
2858
2382
  onTaskFinished() {
2859
2383
  if (workerData.busy) {
2860
- const { resolveTerminated } = workerData;
2384
+ const { resolveTerminated, worker } = workerData;
2861
2385
  if (resolveTerminated) {
2862
2386
  workerData.resolveTerminated = null;
2863
- workerData.terminated = true;
2864
- workerData.worker.terminate();
2387
+ if (worker) {
2388
+ workerData.terminated = true;
2389
+ worker.terminate();
2390
+ }
2865
2391
  resolveTerminated();
2866
2392
  }
2867
2393
  workerData.busy = false;
@@ -2918,28 +2444,23 @@ function createWorkerInterface(workerData, config) {
2918
2444
  }
2919
2445
 
2920
2446
  async function runWorker$1({ options, readable, writable, onTaskFinished, workerOptions }, config) {
2921
- let codecStream, chunkStream;
2447
+ let codecStream, chunkStream, modulePromise;
2922
2448
  try {
2923
2449
  if (options.compressed && !options.format) {
2924
2450
  const deflate = options.codecType.startsWith(CODEC_DEFLATE);
2925
2451
  const FallbackStream = deflate ? config.CompressionStreamFallback : config.DecompressionStreamFallback;
2926
2452
  const NativeStream = deflate ? config.CompressionStream : config.DecompressionStream;
2927
2453
  if (!options.useCompressionStream) {
2928
- try {
2929
- await initModule$1(config);
2930
- } catch {
2931
- if (!FallbackStream || FallbackStream.requiresModule) {
2932
- options.useCompressionStream = true;
2933
- }
2454
+ if (!await moduleLoaded() && (!FallbackStream || FallbackStream.requiresModule)) {
2455
+ options.useCompressionStream = true;
2934
2456
  }
2935
2457
  } else if (FallbackStream && FallbackStream.requiresModule && !supportsDeflateRaw(NativeStream)) {
2936
- try {
2937
- await initModule$1(config);
2938
- } catch {
2939
- // ignored
2940
- }
2458
+ await moduleLoaded();
2941
2459
  }
2942
2460
  }
2461
+ if (options.encrypted && !options.zipCrypto) {
2462
+ await moduleLoaded();
2463
+ }
2943
2464
  codecStream = new CodecStream(options, config);
2944
2465
  chunkStream = new ChunkStream(getChunkSize(config));
2945
2466
  await readable
@@ -2972,6 +2493,13 @@ async function runWorker$1({ options, readable, writable, onTaskFinished, worker
2972
2493
  } finally {
2973
2494
  onTaskFinished();
2974
2495
  }
2496
+
2497
+ function moduleLoaded() {
2498
+ if (!modulePromise) {
2499
+ modulePromise = loadModule(config);
2500
+ }
2501
+ return modulePromise;
2502
+ }
2975
2503
  }
2976
2504
 
2977
2505
  /*
@@ -3078,7 +2606,7 @@ async function runWebWorker(workerData, config) {
3078
2606
  rejectResult = error => {
3079
2607
  const { outputSize, workerOptions } = workerData;
3080
2608
  workerOptions.outputSize = outputSize;
3081
- if (isErrorObject(error) && error.outputSize === UNDEFINED_VALUE) {
2609
+ if (isErrorObject(error)) {
3082
2610
  try {
3083
2611
  error.outputSize = outputSize;
3084
2612
  } catch {
@@ -3092,12 +2620,14 @@ async function runWebWorker(workerData, config) {
3092
2620
  reader: null,
3093
2621
  writer: null,
3094
2622
  outputSize: 0,
2623
+ destinationFailed: false,
2624
+ destinationError: null,
3095
2625
  resolveResult,
3096
2626
  rejectResult,
3097
2627
  result
3098
2628
  });
3099
2629
  const { readable, options } = workerData;
3100
- const { writable, closed, abortPipe } = watchClosedStream(workerData.writable);
2630
+ const { writable, closed, abortPipe } = watchClosedStream(workerData.writable, workerData);
3101
2631
  let streamsTransferred;
3102
2632
  try {
3103
2633
  streamsTransferred = sendMessage({
@@ -3140,7 +2670,18 @@ async function runWebWorker(workerData, config) {
3140
2670
  } catch {
3141
2671
  // ignored
3142
2672
  }
3143
- throw error;
2673
+ const { outputSize, workerOptions, destinationFailed, destinationError } = workerData;
2674
+ workerOptions.outputSize = outputSize;
2675
+ const workerFailed = isErrorObject(error) && (error.codecImportFailed || error.workerStartupFailed);
2676
+ const reportedError = destinationFailed && !workerFailed ? destinationError : error;
2677
+ if (isErrorObject(reportedError)) {
2678
+ try {
2679
+ reportedError.outputSize = outputSize;
2680
+ } catch {
2681
+ // ignored
2682
+ }
2683
+ }
2684
+ throw reportedError;
3144
2685
  }
3145
2686
 
3146
2687
  async function closeWritable() {
@@ -3154,12 +2695,27 @@ async function runWebWorker(workerData, config) {
3154
2695
  }
3155
2696
  }
3156
2697
 
3157
- function watchClosedStream(writableSource) {
2698
+ function watchClosedStream(writableSource, workerData) {
3158
2699
  const abortController = new AbortController();
3159
- const { writable, readable } = new TransformStream();
2700
+ let aborting;
2701
+ const { writable, readable } = new TransformStream({
2702
+ transform(chunk, controller) {
2703
+ workerData.outputSize += chunk.length;
2704
+ controller.enqueue(chunk);
2705
+ }
2706
+ });
3160
2707
  const closed = readable.pipeTo(writableSource, { preventClose: true, preventAbort: true, signal: abortController.signal });
3161
- closed.catch(() => { });
3162
- return { writable, closed, abortPipe: () => abortController.abort() };
2708
+ closed.catch(error => {
2709
+ if (!aborting) {
2710
+ Object.assign(workerData, { destinationFailed: true, destinationError: error });
2711
+ }
2712
+ });
2713
+ return {
2714
+ writable, closed, abortPipe: () => {
2715
+ aborting = true;
2716
+ abortController.abort();
2717
+ }
2718
+ };
3163
2719
  }
3164
2720
 
3165
2721
  function releaseWorkerStreams(workerData) {
@@ -3357,9 +2913,6 @@ async function onMessage({ data }, workerData) {
3357
2913
  const stale = () => workerData.generation != generation;
3358
2914
  try {
3359
2915
  if (error) {
3360
- if (error.outputSize !== UNDEFINED_VALUE) {
3361
- workerData.outputSize = error.outputSize;
3362
- }
3363
2916
  fail(getResponseError(error, errorValue));
3364
2917
  } else {
3365
2918
  if (type == MESSAGE_PULL) {
@@ -3372,7 +2925,6 @@ async function onMessage({ data }, workerData) {
3372
2925
  const chunk = new Uint8Array(value);
3373
2926
  await writer.ready;
3374
2927
  await writer.write(chunk);
3375
- workerData.outputSize += chunk.length;
3376
2928
  if (!stale()) {
3377
2929
  sendMessage({ type: MESSAGE_ACK_DATA, messageId }, workerData);
3378
2930
  }
@@ -4104,16 +3656,14 @@ async function initHttpReader(httpReader, sendRequest, getRequestData) {
4104
3656
  combineSizeEocd
4105
3657
  } = httpReader;
4106
3658
  if (isHttpFamily(url) && (useRangeHeader || forceRangeRequests) && (typeof preventHeadRequest == UNDEFINED_TYPE || preventHeadRequest)) {
4107
- const response = await sendRequest(HTTP_METHOD_GET, httpReader, getRangeHeaders(httpReader, combineSizeEocd ? -END_OF_CENTRAL_DIR_LENGTH : undefined));
3659
+ const response = await sendRequest(HTTP_METHOD_GET, httpReader, getRangeHeaders(httpReader, combineSizeEocd ? -65557 : undefined));
4108
3660
  const acceptRanges = response.headers.get(HTTP_HEADER_ACCEPT_RANGES);
4109
3661
  if (!forceRangeRequests && (!acceptRanges || acceptRanges.toLowerCase() != HTTP_RANGE_UNIT)) {
4110
3662
  throw new Error(ERR_HTTP_RANGE);
4111
3663
  } else {
4112
- if (combineSizeEocd) {
4113
- const eocdCache = new Uint8Array(await response.arrayBuffer());
4114
- if (response.status == 206 && eocdCache.length == END_OF_CENTRAL_DIR_LENGTH) {
4115
- httpReader.eocdCache = eocdCache;
4116
- }
3664
+ let eocdCache;
3665
+ if (combineSizeEocd && response.status == 206) {
3666
+ eocdCache = new Uint8Array(await response.arrayBuffer());
4117
3667
  }
4118
3668
  setResourceValidators(httpReader, response);
4119
3669
  const contentSize = getContentRangeSize(response);
@@ -4122,6 +3672,9 @@ async function initHttpReader(httpReader, sendRequest, getRequestData) {
4122
3672
  } else {
4123
3673
  httpReader.size = contentSize;
4124
3674
  }
3675
+ if (eocdCache && eocdCache.length && getContentRangeOffset(response) === httpReader.size - eocdCache.length) {
3676
+ httpReader.eocdCache = eocdCache;
3677
+ }
4125
3678
  }
4126
3679
  } else {
4127
3680
  await getContentLength(httpReader, sendRequest, getRequestData);
@@ -4137,25 +3690,23 @@ async function readUint8ArrayHttpReader(httpReader, index, length, sendRequest,
4137
3690
  options
4138
3691
  } = httpReader;
4139
3692
  if (useRangeHeader || forceRangeRequests) {
4140
- if (eocdCache && index == size - END_OF_CENTRAL_DIR_LENGTH && length == END_OF_CENTRAL_DIR_LENGTH) {
4141
- return eocdCache;
4142
- }
4143
3693
  if (index >= size || length === 0) {
4144
3694
  return EMPTY_UINT8_ARRAY;
4145
3695
  } else {
4146
3696
  if (index + length > size) {
4147
3697
  length = size - index;
4148
3698
  }
3699
+ if (eocdCache && index >= size - eocdCache.length) {
3700
+ const cacheIndex = index - (size - eocdCache.length);
3701
+ return eocdCache.slice(cacheIndex, cacheIndex + length);
3702
+ }
4149
3703
  const response = await sendRequest(HTTP_METHOD_GET, httpReader, getRangeHeaders(httpReader, index, length));
4150
3704
  if (response.status != 206) {
4151
3705
  throw new Error(ERR_HTTP_RANGE);
4152
3706
  }
4153
- const contentRangeHeader = response.headers.get(HTTP_HEADER_CONTENT_RANGE);
4154
- if (contentRangeHeader) {
4155
- const rangeStart = Number(contentRangeHeader.trim().split(/[\s-]+/)[1]);
4156
- if (!Number.isNaN(rangeStart) && rangeStart != index) {
4157
- throw new Error(ERR_HTTP_RANGE);
4158
- }
3707
+ const rangeStart = getContentRangeOffset(response);
3708
+ if (rangeStart !== UNDEFINED_VALUE && rangeStart != index) {
3709
+ throw new Error(ERR_HTTP_RANGE);
4159
3710
  }
4160
3711
  checkResourceValidators(httpReader, response);
4161
3712
  setResourceValidators(httpReader, response);
@@ -4215,12 +3766,9 @@ function createRangeReadable(httpReader, offset, size) {
4215
3766
  if (response.status != 206) {
4216
3767
  throw new Error(ERR_HTTP_RANGE);
4217
3768
  }
4218
- const contentRangeHeader = response.headers.get(HTTP_HEADER_CONTENT_RANGE);
4219
- if (contentRangeHeader) {
4220
- const rangeStart = Number(contentRangeHeader.trim().split(/[\s-]+/)[1]);
4221
- if (!Number.isNaN(rangeStart) && rangeStart != windowOffset) {
4222
- throw new Error(ERR_HTTP_RANGE);
4223
- }
3769
+ const rangeStart = getContentRangeOffset(response);
3770
+ if (rangeStart !== UNDEFINED_VALUE && rangeStart != windowOffset) {
3771
+ throw new Error(ERR_HTTP_RANGE);
4224
3772
  }
4225
3773
  checkResourceValidators(httpReader, response);
4226
3774
  setResourceValidators(httpReader, response);
@@ -4236,6 +3784,16 @@ function createRangeReadable(httpReader, offset, size) {
4236
3784
  }
4237
3785
  }
4238
3786
 
3787
+ function getContentRangeOffset(response) {
3788
+ const contentRangeHeader = response.headers.get(HTTP_HEADER_CONTENT_RANGE);
3789
+ if (contentRangeHeader) {
3790
+ const rangeStart = Number(contentRangeHeader.trim().split(/[\s-]+/)[1]);
3791
+ if (!Number.isNaN(rangeStart)) {
3792
+ return rangeStart;
3793
+ }
3794
+ }
3795
+ }
3796
+
4239
3797
  function getContentRangeSize(response) {
4240
3798
  const contentRangeHeader = response.headers.get(HTTP_HEADER_CONTENT_RANGE);
4241
3799
  if (contentRangeHeader) {
@@ -6755,7 +6313,6 @@ class ZipWriter {
6755
6313
  rawExtraFieldUnix: EMPTY_UINT8_ARRAY,
6756
6314
  rawExtraField,
6757
6315
  rawCentralExtraField: EMPTY_UINT8_ARRAY,
6758
- extendedTimestamp: false,
6759
6316
  headerArray,
6760
6317
  headerView
6761
6318
  });
@@ -7499,7 +7056,7 @@ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options
7499
7056
  }
7500
7057
  }
7501
7058
  const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !passThroughCompression)) && !isCompressed(compressionMethod, level);
7502
- if (emptyEntry && !zipCrypto && getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR) === UNDEFINED_VALUE) {
7059
+ if (emptyEntry && getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR) === UNDEFINED_VALUE) {
7503
7060
  dataDescriptor = false;
7504
7061
  }
7505
7062
  const zip64UncompressedSize = zip64Enabled || unknownSize || uncompressedSize >= MAX_32_BITS;
@@ -9109,7 +8666,7 @@ function formatSupported(StreamClass, format) {
9109
8666
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9110
8667
  */
9111
8668
 
9112
- const VERSION = "2.13.0";
8669
+ const VERSION = "2.14.0";
9113
8670
 
9114
8671
  /*
9115
8672
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
@@ -9593,13 +9150,13 @@ const FORMAT_DEFLATE_RAW = "deflate-raw";
9593
9150
  const FORMAT_DEFLATE64_RAW = "deflate64-raw";
9594
9151
  const FORMAT_GZIP = "gzip";
9595
9152
 
9596
- let wasm, malloc, free, memory, initError;
9153
+ let wasm$1, malloc, free, memory, initError;
9597
9154
 
9598
- function setWasmExports(wasmAPI) {
9599
- wasm = wasmAPI;
9600
- ({ malloc, free, memory } = wasm);
9155
+ function setWasmExports$1(wasmAPI) {
9156
+ wasm$1 = wasmAPI;
9157
+ ({ malloc, free, memory } = wasm$1);
9601
9158
  if (typeof malloc !== "function" || typeof free !== "function" || !memory) {
9602
- wasm = malloc = free = memory = null;
9159
+ wasm$1 = malloc = free = memory = null;
9603
9160
  throw new Error("Invalid WASM module");
9604
9161
  }
9605
9162
  }
@@ -9608,12 +9165,12 @@ function setInitError(error) {
9608
9165
  initError = error;
9609
9166
  }
9610
9167
 
9611
- function resetWasmExports() {
9612
- wasm = malloc = free = memory = initError = null;
9168
+ function resetWasmExports$1() {
9169
+ wasm$1 = malloc = free = memory = initError = null;
9613
9170
  }
9614
9171
 
9615
9172
  function _make(isCompress, type, options = {}) {
9616
- if (!wasm) {
9173
+ if (!wasm$1) {
9617
9174
  const error = new Error("WASM module not loaded");
9618
9175
  error.cause = initError;
9619
9176
  throw error;
@@ -9634,35 +9191,35 @@ function _make(isCompress, type, options = {}) {
9634
9191
  }
9635
9192
  this._scratch = new Uint8Array(outBufferSize);
9636
9193
  if (isCompress) {
9637
- this._process = wasm.deflate_process;
9638
- this._last_consumed = wasm.deflate_last_consumed;
9639
- this._end = wasm.deflate_end;
9640
- this.streamHandle = wasm.deflate_new();
9194
+ this._process = wasm$1.deflate_process;
9195
+ this._last_consumed = wasm$1.deflate_last_consumed;
9196
+ this._end = wasm$1.deflate_end;
9197
+ this.streamHandle = wasm$1.deflate_new();
9641
9198
  if (type === FORMAT_GZIP) {
9642
- result = wasm.deflate_init_gzip(this.streamHandle, level);
9199
+ result = wasm$1.deflate_init_gzip(this.streamHandle, level);
9643
9200
  } else if (type === FORMAT_DEFLATE_RAW) {
9644
- result = wasm.deflate_init_raw(this.streamHandle, level);
9201
+ result = wasm$1.deflate_init_raw(this.streamHandle, level);
9645
9202
  } else {
9646
- result = wasm.deflate_init(this.streamHandle, level);
9203
+ result = wasm$1.deflate_init(this.streamHandle, level);
9647
9204
  }
9648
9205
  } else {
9649
9206
  if (type === FORMAT_DEFLATE64_RAW) {
9650
- this._process = wasm.inflate9_process;
9651
- this._last_consumed = wasm.inflate9_last_consumed;
9652
- this._end = wasm.inflate9_end;
9653
- this.streamHandle = wasm.inflate9_new();
9654
- result = wasm.inflate9_init_raw(this.streamHandle);
9207
+ this._process = wasm$1.inflate9_process;
9208
+ this._last_consumed = wasm$1.inflate9_last_consumed;
9209
+ this._end = wasm$1.inflate9_end;
9210
+ this.streamHandle = wasm$1.inflate9_new();
9211
+ result = wasm$1.inflate9_init_raw(this.streamHandle);
9655
9212
  } else {
9656
- this._process = wasm.inflate_process;
9657
- this._last_consumed = wasm.inflate_last_consumed;
9658
- this._end = wasm.inflate_end;
9659
- this.streamHandle = wasm.inflate_new();
9213
+ this._process = wasm$1.inflate_process;
9214
+ this._last_consumed = wasm$1.inflate_last_consumed;
9215
+ this._end = wasm$1.inflate_end;
9216
+ this.streamHandle = wasm$1.inflate_new();
9660
9217
  if (type === FORMAT_DEFLATE_RAW) {
9661
- result = wasm.inflate_init_raw(this.streamHandle);
9218
+ result = wasm$1.inflate_init_raw(this.streamHandle);
9662
9219
  } else if (type === FORMAT_GZIP) {
9663
- result = wasm.inflate_init_gzip(this.streamHandle);
9220
+ result = wasm$1.inflate_init_gzip(this.streamHandle);
9664
9221
  } else {
9665
- result = wasm.inflate_init(this.streamHandle);
9222
+ result = wasm$1.inflate_init(this.streamHandle);
9666
9223
  }
9667
9224
  }
9668
9225
  }
@@ -9797,6 +9354,105 @@ DecompressionStreamZlib.requiresModule = true;
9797
9354
  CompressionStreamZlib.supportedFormats = [FORMAT_DEFLATE, FORMAT_DEFLATE_RAW, FORMAT_GZIP];
9798
9355
  DecompressionStreamZlib.supportedFormats = [FORMAT_DEFLATE, FORMAT_DEFLATE_RAW, FORMAT_GZIP, FORMAT_DEFLATE64_RAW];
9799
9356
 
9357
+ /*
9358
+ Copyright (c) 2026 Gildas Lormeau. All rights reserved.
9359
+
9360
+ Redistribution and use in source and binary forms, with or without
9361
+ modification, are permitted provided that the following conditions are met:
9362
+
9363
+ 1. Redistributions of source code must retain the above copyright notice,
9364
+ this list of conditions and the following disclaimer.
9365
+
9366
+ 2. Redistributions in binary form must reproduce the above copyright
9367
+ notice, this list of conditions and the following disclaimer in
9368
+ the documentation and/or other materials provided with the distribution.
9369
+
9370
+ 3. The names of the authors may not be used to endorse or promote products
9371
+ derived from this software without specific prior written permission.
9372
+
9373
+ THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
9374
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
9375
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
9376
+ INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
9377
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9378
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
9379
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
9380
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
9381
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
9382
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9383
+ */
9384
+
9385
+
9386
+ const BUFFER_LENGTH = 64 * 1024;
9387
+ const DIGEST_LENGTH = 20;
9388
+
9389
+ let wasm, buffer;
9390
+
9391
+ function setWasmExports(wasmAPI) {
9392
+ // deno-lint-ignore valid-typeof
9393
+ if (typeof wasmAPI.aes_hmac_new == FUNCTION_TYPE) {
9394
+ wasm = wasmAPI;
9395
+ buffer = 0;
9396
+ }
9397
+ }
9398
+
9399
+ function resetWasmExports() {
9400
+ wasm = null;
9401
+ buffer = 0;
9402
+ }
9403
+
9404
+ function createEngine(key, authenticationKey) {
9405
+ const exports = wasm;
9406
+ let context = exports ? createContext(exports, key, authenticationKey) : 0;
9407
+ if (!context) {
9408
+ return createEngine$2(key, authenticationKey);
9409
+ }
9410
+ const scratch = buffer;
9411
+ return {
9412
+ process(data, decrypt) {
9413
+ for (let offset = 0; offset < data.length; offset += BUFFER_LENGTH) {
9414
+ const chunk = data.subarray(offset, offset + BUFFER_LENGTH);
9415
+ const heap = getHeap(exports);
9416
+ heap.set(chunk, scratch);
9417
+ exports.aes_hmac_process(context, scratch, chunk.length, decrypt ? 1 : 0);
9418
+ chunk.set(heap.subarray(scratch, scratch + chunk.length));
9419
+ }
9420
+ },
9421
+ digest() {
9422
+ exports.aes_hmac_end(context, scratch);
9423
+ context = 0;
9424
+ return getHeap(exports).slice(scratch, scratch + DIGEST_LENGTH);
9425
+ },
9426
+ dispose() {
9427
+ if (context) {
9428
+ exports.aes_hmac_end(context, 0);
9429
+ context = 0;
9430
+ }
9431
+ }
9432
+ };
9433
+ }
9434
+
9435
+ function createContext(exports, key, authenticationKey) {
9436
+ if (!buffer) {
9437
+ buffer = exports.malloc(BUFFER_LENGTH);
9438
+ }
9439
+ const context = buffer ? exports.aes_hmac_new() : 0;
9440
+ if (context) {
9441
+ const heap = getHeap(exports);
9442
+ heap.set(key, buffer);
9443
+ heap.set(authenticationKey, buffer + key.length);
9444
+ if (exports.aes_hmac_init(context, buffer, key.length, buffer + key.length, authenticationKey.length)) {
9445
+ exports.aes_hmac_end(context, 0);
9446
+ return 0;
9447
+ }
9448
+ }
9449
+ return context;
9450
+ }
9451
+
9452
+ function getHeap(exports) {
9453
+ return new Uint8Array(exports.memory.buffer);
9454
+ }
9455
+
9800
9456
  /*
9801
9457
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
9802
9458
 
@@ -9858,11 +9514,13 @@ async function instantiateModule(wasmURI, baseURI) {
9858
9514
  }
9859
9515
  }
9860
9516
  const wasmInstance = await WebAssembly.instantiate(arrayBuffer);
9517
+ setWasmExports$1(wasmInstance.instance.exports);
9861
9518
  setWasmExports(wasmInstance.instance.exports);
9862
9519
  }
9863
9520
 
9864
9521
  function resetWasmModule() {
9865
9522
  initializedModule = false;
9523
+ resetWasmExports$1();
9866
9524
  resetWasmExports();
9867
9525
  }
9868
9526
 
@@ -9908,6 +9566,7 @@ function arrayBufferFromDataURI(dataURI) {
9908
9566
 
9909
9567
  let modulePromise;
9910
9568
 
9569
+ setAESEngine(createEngine);
9911
9570
  configureWorker({
9912
9571
  initModule: config => {
9913
9572
  if (!modulePromise) {
@@ -10411,12 +10070,16 @@ class ZipDirectoryEntry extends ZipEntry {
10411
10070
  let directoryEntry = parent;
10412
10071
  if (name) {
10413
10072
  directoryEntry = parent.getChildByName(name);
10414
- if (directoryEntry && !directoryEntry.directory) {
10073
+ if (directoryEntry && (!directoryEntry.directory || directoryEntry.data)) {
10415
10074
  if (duplicates == DUPLICATES_KEEP_FIRST) {
10416
10075
  continue;
10417
10076
  } else if (duplicates == DUPLICATES_KEEP_LAST) {
10418
- this.fs.remove(directoryEntry);
10419
- directoryEntry = UNDEFINED_VALUE;
10077
+ if (directoryEntry.directory) {
10078
+ directoryEntry.data = entry;
10079
+ } else {
10080
+ this.fs.remove(directoryEntry);
10081
+ directoryEntry = UNDEFINED_VALUE;
10082
+ }
10420
10083
  } else {
10421
10084
  throw new Error(ERR_DUPLICATE_IMPORTED_ENTRY);
10422
10085
  }