archive-codec 1.7.1 → 1.8.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.
package/README.md CHANGED
@@ -16,6 +16,8 @@ Created for [documents.js#564](https://github.com/ExaDev/documents.js/issues/564
16
16
 
17
17
  [documents.js#1108](https://github.com/ExaDev/documents.js/issues/1108) added the RC4/MD5 primitives `xls-codec` needs to decrypt a legacy-encrypted `.xls` workbook: the [MS-OFFCRYPTO] 2.3.6.1 "RC4 encryption header" scheme every BIFF8 `FilePass` record protected this way shares with the same header shape in `.doc` and `.ppt`. RC4 and MD5 are trivial and completely unavailable from any platform crypto API this package can portably reach (WebCrypto has never offered either; `node:crypto` dropped RC4 from its default provider with OpenSSL 3), so hand-writing them here — once, shared — is the only option that keeps `xls-codec`, `doc-codec`, and `ppt-codec` (already this package's only consumers) from each carrying their own copy. The newer "RC4 CryptoAPI encryption header" scheme (2.3.5.1, a different header shape and derivation) and the older XOR obfuscation scheme are explicitly out of scope for now — tracked separately in [documents.js#922](https://github.com/ExaDev/documents.js/issues/922).
18
18
 
19
+ [documents.js#1113](https://github.com/ExaDev/documents.js/issues/1113) is the first of those two named future consumers to actually land: `doc-codec` decrypts an RC4-encrypted `.doc` given a password, wired against the same primitives `xls-codec` uses. The two codecs' own re-keying intervals genuinely differ (`OFFICE_RC4_BLOCK_SIZE` for `xls-codec`, `OFFICE_RC4_DOC_BLOCK_SIZE` for `doc-codec`), so `decryptOfficeRc4` gained a `blockSize` parameter rather than this package assuming one shared constant — see [Legacy Office encryption](#legacy-office-encryption).
20
+
19
21
  Scope: **ZIP containers** (read and write over [`fflate`](https://github.com/101arrowz/fflate), recursive walking of ZIP-in-ZIP entries), **classic OLE compound files** (bounded [MS-CFB] reading and conformant [MS-CFB] writing, plus OLE Package stream reading and writing), **[MS-OLEPS] Property Set Streams** (generic read/write of a single-property-set stream, plus SummaryInformation's own title/subject/author/keywords/comments/created/last-saved/last-printed fields), and the **RC4/MD5 primitives** the legacy OLE-based binary formats share for password-to-open encryption. **tar and gzip, DocumentSummaryInformation's extended and user-defined property sets, writing VT_LPSTR (ANSI-codepage) string properties, RC4 CryptoAPI encryption, and XOR obfuscation are explicitly out of scope.**
20
22
 
21
23
  ## Getting started
@@ -61,7 +63,7 @@ The smoke suite (`test/smoke.test.mjs`) is the guard on that advertisement: it l
61
63
  | `oleps/layout-metadata` | `summaryInformationToLayoutMetadata`, `layoutMetadataToSummaryInformation`, `hasSummaryInformationFields` — the `SummaryInformationProperties` <-> `document-schema.js`'s `LayoutMetadata` mapping, shared by `doc-codec`/`xls-codec`/`ppt-codec` (see [Property sets](#property-sets)) |
62
64
  | `crypto/md5` | `md5` — RFC 1321 MD5, hand-written (see [Legacy Office encryption](#legacy-office-encryption)) |
63
65
  | `crypto/rc4` | `rc4` — the RC4 stream cipher, hand-written; symmetric, so also the decrypt operation |
64
- | `crypto/office-rc4` | `deriveOfficeRc4BaseHash`, `deriveOfficeRc4BlockKey`, `decryptOfficeRc4`, `OFFICE_RC4_VERIFIER_LENGTH`, `OFFICE_RC4_BLOCK_SIZE` — [MS-OFFCRYPTO] 2.3.6.2's own key derivation and the block-keyed stream decryption built on it |
66
+ | `crypto/office-rc4` | `deriveOfficeRc4BaseHash`, `deriveOfficeRc4BlockKey`, `decryptOfficeRc4`, `OFFICE_RC4_VERIFIER_LENGTH`, `OFFICE_RC4_BLOCK_SIZE`, `OFFICE_RC4_DOC_BLOCK_SIZE` — [MS-OFFCRYPTO] 2.3.6.2's own key derivation and the block-keyed stream decryption built on it |
65
67
 
66
68
  ### Recursive walking
67
69
 
@@ -184,9 +186,9 @@ const baseHash = deriveOfficeRc4BaseHash(password, salt);
184
186
  const plaintext = decryptOfficeRc4(baseHash, streamOffset, ciphertext);
185
187
  ```
186
188
 
187
- `deriveOfficeRc4BaseHash`/`deriveOfficeRc4BlockKey`/`decryptOfficeRc4` implement [MS-OFFCRYPTO] 2.3.6.1/2.3.6.2's RC4 encryption header scheme: a per-workbook base hash derived once from the password and the header's own salt, then a real 40-bit RC4 key re-derived from that base hash at every 1024-byte boundary of the underlying decrypted stream. Both the key length and the block-reset interval come from Apache POI's own `Biff8EncryptionKey`, a mature independent implementation, rather than the published spec's own more generic prose — see each constant's own doc comment for the discrepancy. `decryptOfficeRc4` takes the byte offset a chunk starts at within the whole encrypted stream (not within the chunk itself), so a stream can be decrypted in arbitrary pieces, not only from its own start, and still land on the correct per-block key throughout.
189
+ `deriveOfficeRc4BaseHash`/`deriveOfficeRc4BlockKey`/`decryptOfficeRc4` implement [MS-OFFCRYPTO] 2.3.6.1/2.3.6.2's RC4 encryption header scheme: a per-workbook base hash derived once from the password and the header's own salt, then a full 128-bit RC4 key re-derived from that base hash at every 1024-byte boundary of the underlying decrypted stream — despite [MS-OFFCRYPTO] 2.3.6.1's own field descriptions twice stating "encrypted using a 40-bit RC4 cipher", which is wrong; the real key is Hfinal in full, confirmed against Apache POI's `BinaryRC4Decryptor` and nolze/msoffcrypto-tool's own doctested test vectors, both cross-checked directly rather than trusted from the spec's own prose — see each constant's own doc comment for the full account, including the truncated-to-5-bytes implementation this package shipped briefly before the cross-check caught it. `decryptOfficeRc4` takes the byte offset a chunk starts at within the whole encrypted stream (not within the chunk itself), so a stream can be decrypted in arbitrary pieces, not only from its own start, and still land on the correct per-block key throughout. The 1024-byte re-keying interval is `decryptOfficeRc4`'s own default `blockSize`, since [MS-XLS]'s own FilePass scheme is this module's original consumer, but it is a real [MS-XLS]-specific value, not a property of the algorithm itself: [MS-DOC] 2.2.6.2's own RC4 encryption header (the identical [MS-OFFCRYPTO] 2.3.6.1 structure, confirmed against Apache POI's `EncryptionMode.binaryRC4` resolving both) re-keys every 512 bytes instead (`OFFICE_RC4_DOC_BLOCK_SIZE`), passed explicitly as `decryptOfficeRc4`'s fourth argument.
188
190
 
189
- This is exactly the piece `xls-codec`'s `FilePass`-record reader needs and nothing more: locating the `FilePass` record, reading its own encryption-header bytes, and verifying the password against `EncryptedVerifier`/`EncryptedVerifierHash` are `xls-codec`'s own concern, not this package's — `archive-codec` carries only the format-agnostic cryptography, never a `.xls`-specific byte layout. `md5`/`rc4` are exported individually too, for `doc-codec`/`ppt-codec`'s own eventual integration against the identical header scheme.
191
+ This is exactly the piece `xls-codec`'s `FilePass`-record reader and `doc-codec`'s own `EncryptionHeader` reader (ExaDev/documents.js#1113) both need and nothing more: locating the header, reading its own fields, and verifying the password against `EncryptedVerifier`/`EncryptedVerifierHash` are each codec's own concern, not this package's — `archive-codec` carries only the format-agnostic cryptography, never a `.xls`- or `.doc`-specific byte layout. `decryptOfficeRc4`'s own `blockSize` parameter exists because the two codecs' re-keying intervals genuinely differ (`OFFICE_RC4_BLOCK_SIZE`, 1024, for `xls-codec`; `OFFICE_RC4_DOC_BLOCK_SIZE`, 512, for `doc-codec`) -- confirmed as real, independent values against Apache POI's own `Biff8DecryptingStream` and `BinaryRC4Decryptor` respectively, not one shared constant this package could have assumed. `md5`/`rc4` are exported individually too, for `ppt-codec`'s own eventual integration against the identical header scheme.
190
192
 
191
193
  ### ZIP container
192
194
 
@@ -4,10 +4,12 @@ const require_crypto_rc4 = require("./rc4.cjs");
4
4
  //#region src/crypto/office-rc4.ts
5
5
  /** [MS-OFFCRYPTO] 2.3.6.1's own EncryptedVerifier/EncryptedVerifierHash length, and the salt length the same header carries. */
6
6
  const OFFICE_RC4_VERIFIER_LENGTH = 16;
7
- /** The span of the underlying decrypted stream one derived RC4 key covers before the next block's key takes over -- confirmed against Apache POI's Biff8EncryptionKey, since [MS-OFFCRYPTO] 2.3.6.2's own prose does not state it. */
7
+ /** [MS-XLS]'s own FilePass-protected RC4 scheme's re-keying interval -- confirmed against Apache POI's Biff8DecryptingStream.RC4_REKEYING_INTERVAL, since [MS-OFFCRYPTO] 2.3.6.2's own prose does not state it. `decryptOfficeRc4`'s own default `blockSize`. */
8
8
  const OFFICE_RC4_BLOCK_SIZE = 1024;
9
- /** The real derived RC4 key length for this scheme (40 bits) -- confirmed against Apache POI's Biff8EncryptionKey, since [MS-OFFCRYPTO] 2.3.6.2's own generic prose ("the first 128 bits of Hfinal") describes a different, longer-key variant this header shape does not use. */
10
- const KEY_LENGTH_BYTES = 5;
9
+ /** [MS-DOC] 2.2.6.2's own re-keying interval for its identical RC4 encryption header scheme -- stated directly in the spec's own prose ("encrypted in 512-byte blocks"), confirmed independently against Apache POI's BinaryRC4Decryptor (`chunkSize = 512`). Genuinely different from OFFICE_RC4_BLOCK_SIZE, not a duplicate of it -- pass this as decryptOfficeRc4's own `blockSize` argument when decrypting a .doc stream. */
10
+ const OFFICE_RC4_DOC_BLOCK_SIZE = 512;
11
+ /** The intermediate H0/H1 truncation [MS-OFFCRYPTO] 2.3.6.2 states explicitly ("H0's own first 5 bytes", "H1's own first 5 bytes") -- distinct from the FINAL per-block key length, which is Hfinal in full (see this file's own top comment) and is never truncated. */
12
+ const INTERMEDIATE_HASH_LENGTH_BYTES = 5;
11
13
  function passwordToUtf16LeBytes(password) {
12
14
  const bytes = new Uint8Array(password.length * 2);
13
15
  for (let i = 0; i < password.length; i += 1) {
@@ -19,15 +21,15 @@ function passwordToUtf16LeBytes(password) {
19
21
  }
20
22
  /** The per-workbook intermediate hash (H1's own first 5 bytes) every block's key derives from -- computed once per password+salt pair, then reused across every block via deriveOfficeRc4BlockKey, since recomputing H0/H1 per block would be needless repeated work over the identical 336-byte buffer. */
21
23
  function deriveOfficeRc4BaseHash(password, salt) {
22
- const truncated = require_crypto_md5.md5(passwordToUtf16LeBytes(password)).subarray(0, KEY_LENGTH_BYTES);
24
+ const truncated = require_crypto_md5.md5(passwordToUtf16LeBytes(password)).subarray(0, INTERMEDIATE_HASH_LENGTH_BYTES);
23
25
  const unit = /* @__PURE__ */ new Uint8Array(21);
24
26
  unit.set(truncated, 0);
25
- unit.set(salt, KEY_LENGTH_BYTES);
27
+ unit.set(salt, INTERMEDIATE_HASH_LENGTH_BYTES);
26
28
  const buffer336 = new Uint8Array(unit.length * 16);
27
29
  for (let i = 0; i < 16; i += 1) buffer336.set(unit, i * unit.length);
28
- return require_crypto_md5.md5(buffer336).subarray(0, KEY_LENGTH_BYTES);
30
+ return require_crypto_md5.md5(buffer336).subarray(0, INTERMEDIATE_HASH_LENGTH_BYTES);
29
31
  }
30
- /** The real, block-specific 40-bit RC4 key: MD5(baseHash + the block number as 4 little-endian bytes), truncated to 5 bytes. */
32
+ /** The real, block-specific RC4 key: MD5(baseHash + the block number as 4 little-endian bytes) in full -- all 16 bytes, never truncated (see this file's own top comment for why that matters). */
31
33
  function deriveOfficeRc4BlockKey(baseHash, blockNumber) {
32
34
  const input = new Uint8Array(baseHash.length + 4);
33
35
  input.set(baseHash, 0);
@@ -35,21 +37,21 @@ function deriveOfficeRc4BlockKey(baseHash, blockNumber) {
35
37
  input[baseHash.length + 1] = blockNumber >>> 8 & 255;
36
38
  input[baseHash.length + 2] = blockNumber >>> 16 & 255;
37
39
  input[baseHash.length + 3] = blockNumber >>> 24 & 255;
38
- return require_crypto_md5.md5(input).subarray(0, KEY_LENGTH_BYTES);
40
+ return require_crypto_md5.md5(input);
39
41
  }
40
42
  /**
41
- * Decrypts `data` -- a byte range of the underlying OLE stream starting at `streamOffset` bytes from the very start of that stream -- against the RC4 encryption header scheme, re-deriving the block key at every 1024-byte boundary `data` crosses. RC4 is symmetric, so this same function also encrypts; nothing in this package uses it that way, since nothing in this family writes an encrypted legacy binary document.
43
+ * Decrypts `data` -- a byte range of the underlying OLE stream starting at `streamOffset` bytes from the very start of that stream -- against the RC4 encryption header scheme, re-deriving the block key at every `blockSize`-byte boundary `data` crosses (`OFFICE_RC4_BLOCK_SIZE`, 1024, when omitted -- the value every caller but [MS-DOC]'s own RC4 scheme uses; [MS-DOC] 2.2.6.2 re-keys every 512 bytes instead, a real difference from [MS-XLS]'s own FilePass scheme rather than a shared constant, confirmed against Apache POI's own `BinaryRC4Decryptor` (`chunkSize = 512`) directly contrasted with `Biff8DecryptingStream.RC4_REKEYING_INTERVAL` (1024) -- two genuinely separate implementations, not one shared class with a parameter). RC4 is symmetric, so this same function also encrypts; nothing in this package uses it that way, since nothing in this family writes an encrypted legacy binary document.
42
44
  *
43
- * `streamOffset` matters because the block number is the byte's own absolute position in the stream divided by 1024, not its position within whatever slice `data` happens to be -- decrypting a stream in arbitrary chunks (not just from offset 0) still lands on the correct per-block key this way.
45
+ * `streamOffset` matters because the block number is the byte's own absolute position in the stream divided by `blockSize`, not its position within whatever slice `data` happens to be -- decrypting a stream in arbitrary chunks (not just from offset 0) still lands on the correct per-block key this way.
44
46
  */
45
- function decryptOfficeRc4(baseHash, streamOffset, data) {
47
+ function decryptOfficeRc4(baseHash, streamOffset, data, blockSize = OFFICE_RC4_BLOCK_SIZE) {
46
48
  const out = new Uint8Array(data.length);
47
49
  let position = 0;
48
50
  while (position < data.length) {
49
51
  const absolute = streamOffset + position;
50
- const blockNumber = Math.floor(absolute / OFFICE_RC4_BLOCK_SIZE);
51
- const offsetWithinBlock = absolute - blockNumber * OFFICE_RC4_BLOCK_SIZE;
52
- const bytesLeftInBlock = OFFICE_RC4_BLOCK_SIZE - offsetWithinBlock;
52
+ const blockNumber = Math.floor(absolute / blockSize);
53
+ const offsetWithinBlock = absolute - blockNumber * blockSize;
54
+ const bytesLeftInBlock = blockSize - offsetWithinBlock;
53
55
  const chunkLength = Math.min(bytesLeftInBlock, data.length - position);
54
56
  const key = deriveOfficeRc4BlockKey(baseHash, blockNumber);
55
57
  const keystreamPrefixAndChunk = require_crypto_rc4.rc4(key, new Uint8Array(offsetWithinBlock + chunkLength));
@@ -63,6 +65,7 @@ function decryptOfficeRc4(baseHash, streamOffset, data) {
63
65
  }
64
66
  //#endregion
65
67
  exports.OFFICE_RC4_BLOCK_SIZE = OFFICE_RC4_BLOCK_SIZE;
68
+ exports.OFFICE_RC4_DOC_BLOCK_SIZE = OFFICE_RC4_DOC_BLOCK_SIZE;
66
69
  exports.OFFICE_RC4_VERIFIER_LENGTH = OFFICE_RC4_VERIFIER_LENGTH;
67
70
  exports.decryptOfficeRc4 = decryptOfficeRc4;
68
71
  exports.deriveOfficeRc4BaseHash = deriveOfficeRc4BaseHash;
@@ -1,17 +1,19 @@
1
1
  //#region src/crypto/office-rc4.d.ts
2
2
  /** [MS-OFFCRYPTO] 2.3.6.1's own EncryptedVerifier/EncryptedVerifierHash length, and the salt length the same header carries. */
3
3
  declare const OFFICE_RC4_VERIFIER_LENGTH = 16;
4
- /** The span of the underlying decrypted stream one derived RC4 key covers before the next block's key takes over -- confirmed against Apache POI's Biff8EncryptionKey, since [MS-OFFCRYPTO] 2.3.6.2's own prose does not state it. */
4
+ /** [MS-XLS]'s own FilePass-protected RC4 scheme's re-keying interval -- confirmed against Apache POI's Biff8DecryptingStream.RC4_REKEYING_INTERVAL, since [MS-OFFCRYPTO] 2.3.6.2's own prose does not state it. `decryptOfficeRc4`'s own default `blockSize`. */
5
5
  declare const OFFICE_RC4_BLOCK_SIZE = 1024;
6
+ /** [MS-DOC] 2.2.6.2's own re-keying interval for its identical RC4 encryption header scheme -- stated directly in the spec's own prose ("encrypted in 512-byte blocks"), confirmed independently against Apache POI's BinaryRC4Decryptor (`chunkSize = 512`). Genuinely different from OFFICE_RC4_BLOCK_SIZE, not a duplicate of it -- pass this as decryptOfficeRc4's own `blockSize` argument when decrypting a .doc stream. */
7
+ declare const OFFICE_RC4_DOC_BLOCK_SIZE = 512;
6
8
  /** The per-workbook intermediate hash (H1's own first 5 bytes) every block's key derives from -- computed once per password+salt pair, then reused across every block via deriveOfficeRc4BlockKey, since recomputing H0/H1 per block would be needless repeated work over the identical 336-byte buffer. */
7
9
  declare function deriveOfficeRc4BaseHash(password: string, salt: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>;
8
- /** The real, block-specific 40-bit RC4 key: MD5(baseHash + the block number as 4 little-endian bytes), truncated to 5 bytes. */
10
+ /** The real, block-specific RC4 key: MD5(baseHash + the block number as 4 little-endian bytes) in full -- all 16 bytes, never truncated (see this file's own top comment for why that matters). */
9
11
  declare function deriveOfficeRc4BlockKey(baseHash: Uint8Array<ArrayBuffer>, blockNumber: number): Uint8Array<ArrayBuffer>;
10
12
  /**
11
- * Decrypts `data` -- a byte range of the underlying OLE stream starting at `streamOffset` bytes from the very start of that stream -- against the RC4 encryption header scheme, re-deriving the block key at every 1024-byte boundary `data` crosses. RC4 is symmetric, so this same function also encrypts; nothing in this package uses it that way, since nothing in this family writes an encrypted legacy binary document.
13
+ * Decrypts `data` -- a byte range of the underlying OLE stream starting at `streamOffset` bytes from the very start of that stream -- against the RC4 encryption header scheme, re-deriving the block key at every `blockSize`-byte boundary `data` crosses (`OFFICE_RC4_BLOCK_SIZE`, 1024, when omitted -- the value every caller but [MS-DOC]'s own RC4 scheme uses; [MS-DOC] 2.2.6.2 re-keys every 512 bytes instead, a real difference from [MS-XLS]'s own FilePass scheme rather than a shared constant, confirmed against Apache POI's own `BinaryRC4Decryptor` (`chunkSize = 512`) directly contrasted with `Biff8DecryptingStream.RC4_REKEYING_INTERVAL` (1024) -- two genuinely separate implementations, not one shared class with a parameter). RC4 is symmetric, so this same function also encrypts; nothing in this package uses it that way, since nothing in this family writes an encrypted legacy binary document.
12
14
  *
13
- * `streamOffset` matters because the block number is the byte's own absolute position in the stream divided by 1024, not its position within whatever slice `data` happens to be -- decrypting a stream in arbitrary chunks (not just from offset 0) still lands on the correct per-block key this way.
15
+ * `streamOffset` matters because the block number is the byte's own absolute position in the stream divided by `blockSize`, not its position within whatever slice `data` happens to be -- decrypting a stream in arbitrary chunks (not just from offset 0) still lands on the correct per-block key this way.
14
16
  */
15
- declare function decryptOfficeRc4(baseHash: Uint8Array<ArrayBuffer>, streamOffset: number, data: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>;
17
+ declare function decryptOfficeRc4(baseHash: Uint8Array<ArrayBuffer>, streamOffset: number, data: Uint8Array<ArrayBuffer>, blockSize?: number): Uint8Array<ArrayBuffer>;
16
18
  //#endregion
17
- export { OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey };
19
+ export { OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey };
@@ -1,17 +1,19 @@
1
1
  //#region src/crypto/office-rc4.d.ts
2
2
  /** [MS-OFFCRYPTO] 2.3.6.1's own EncryptedVerifier/EncryptedVerifierHash length, and the salt length the same header carries. */
3
3
  declare const OFFICE_RC4_VERIFIER_LENGTH = 16;
4
- /** The span of the underlying decrypted stream one derived RC4 key covers before the next block's key takes over -- confirmed against Apache POI's Biff8EncryptionKey, since [MS-OFFCRYPTO] 2.3.6.2's own prose does not state it. */
4
+ /** [MS-XLS]'s own FilePass-protected RC4 scheme's re-keying interval -- confirmed against Apache POI's Biff8DecryptingStream.RC4_REKEYING_INTERVAL, since [MS-OFFCRYPTO] 2.3.6.2's own prose does not state it. `decryptOfficeRc4`'s own default `blockSize`. */
5
5
  declare const OFFICE_RC4_BLOCK_SIZE = 1024;
6
+ /** [MS-DOC] 2.2.6.2's own re-keying interval for its identical RC4 encryption header scheme -- stated directly in the spec's own prose ("encrypted in 512-byte blocks"), confirmed independently against Apache POI's BinaryRC4Decryptor (`chunkSize = 512`). Genuinely different from OFFICE_RC4_BLOCK_SIZE, not a duplicate of it -- pass this as decryptOfficeRc4's own `blockSize` argument when decrypting a .doc stream. */
7
+ declare const OFFICE_RC4_DOC_BLOCK_SIZE = 512;
6
8
  /** The per-workbook intermediate hash (H1's own first 5 bytes) every block's key derives from -- computed once per password+salt pair, then reused across every block via deriveOfficeRc4BlockKey, since recomputing H0/H1 per block would be needless repeated work over the identical 336-byte buffer. */
7
9
  declare function deriveOfficeRc4BaseHash(password: string, salt: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>;
8
- /** The real, block-specific 40-bit RC4 key: MD5(baseHash + the block number as 4 little-endian bytes), truncated to 5 bytes. */
10
+ /** The real, block-specific RC4 key: MD5(baseHash + the block number as 4 little-endian bytes) in full -- all 16 bytes, never truncated (see this file's own top comment for why that matters). */
9
11
  declare function deriveOfficeRc4BlockKey(baseHash: Uint8Array<ArrayBuffer>, blockNumber: number): Uint8Array<ArrayBuffer>;
10
12
  /**
11
- * Decrypts `data` -- a byte range of the underlying OLE stream starting at `streamOffset` bytes from the very start of that stream -- against the RC4 encryption header scheme, re-deriving the block key at every 1024-byte boundary `data` crosses. RC4 is symmetric, so this same function also encrypts; nothing in this package uses it that way, since nothing in this family writes an encrypted legacy binary document.
13
+ * Decrypts `data` -- a byte range of the underlying OLE stream starting at `streamOffset` bytes from the very start of that stream -- against the RC4 encryption header scheme, re-deriving the block key at every `blockSize`-byte boundary `data` crosses (`OFFICE_RC4_BLOCK_SIZE`, 1024, when omitted -- the value every caller but [MS-DOC]'s own RC4 scheme uses; [MS-DOC] 2.2.6.2 re-keys every 512 bytes instead, a real difference from [MS-XLS]'s own FilePass scheme rather than a shared constant, confirmed against Apache POI's own `BinaryRC4Decryptor` (`chunkSize = 512`) directly contrasted with `Biff8DecryptingStream.RC4_REKEYING_INTERVAL` (1024) -- two genuinely separate implementations, not one shared class with a parameter). RC4 is symmetric, so this same function also encrypts; nothing in this package uses it that way, since nothing in this family writes an encrypted legacy binary document.
12
14
  *
13
- * `streamOffset` matters because the block number is the byte's own absolute position in the stream divided by 1024, not its position within whatever slice `data` happens to be -- decrypting a stream in arbitrary chunks (not just from offset 0) still lands on the correct per-block key this way.
15
+ * `streamOffset` matters because the block number is the byte's own absolute position in the stream divided by `blockSize`, not its position within whatever slice `data` happens to be -- decrypting a stream in arbitrary chunks (not just from offset 0) still lands on the correct per-block key this way.
14
16
  */
15
- declare function decryptOfficeRc4(baseHash: Uint8Array<ArrayBuffer>, streamOffset: number, data: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>;
17
+ declare function decryptOfficeRc4(baseHash: Uint8Array<ArrayBuffer>, streamOffset: number, data: Uint8Array<ArrayBuffer>, blockSize?: number): Uint8Array<ArrayBuffer>;
16
18
  //#endregion
17
- export { OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey };
19
+ export { OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey };
@@ -3,10 +3,12 @@ import { rc4 } from "./rc4.js";
3
3
  //#region src/crypto/office-rc4.ts
4
4
  /** [MS-OFFCRYPTO] 2.3.6.1's own EncryptedVerifier/EncryptedVerifierHash length, and the salt length the same header carries. */
5
5
  const OFFICE_RC4_VERIFIER_LENGTH = 16;
6
- /** The span of the underlying decrypted stream one derived RC4 key covers before the next block's key takes over -- confirmed against Apache POI's Biff8EncryptionKey, since [MS-OFFCRYPTO] 2.3.6.2's own prose does not state it. */
6
+ /** [MS-XLS]'s own FilePass-protected RC4 scheme's re-keying interval -- confirmed against Apache POI's Biff8DecryptingStream.RC4_REKEYING_INTERVAL, since [MS-OFFCRYPTO] 2.3.6.2's own prose does not state it. `decryptOfficeRc4`'s own default `blockSize`. */
7
7
  const OFFICE_RC4_BLOCK_SIZE = 1024;
8
- /** The real derived RC4 key length for this scheme (40 bits) -- confirmed against Apache POI's Biff8EncryptionKey, since [MS-OFFCRYPTO] 2.3.6.2's own generic prose ("the first 128 bits of Hfinal") describes a different, longer-key variant this header shape does not use. */
9
- const KEY_LENGTH_BYTES = 5;
8
+ /** [MS-DOC] 2.2.6.2's own re-keying interval for its identical RC4 encryption header scheme -- stated directly in the spec's own prose ("encrypted in 512-byte blocks"), confirmed independently against Apache POI's BinaryRC4Decryptor (`chunkSize = 512`). Genuinely different from OFFICE_RC4_BLOCK_SIZE, not a duplicate of it -- pass this as decryptOfficeRc4's own `blockSize` argument when decrypting a .doc stream. */
9
+ const OFFICE_RC4_DOC_BLOCK_SIZE = 512;
10
+ /** The intermediate H0/H1 truncation [MS-OFFCRYPTO] 2.3.6.2 states explicitly ("H0's own first 5 bytes", "H1's own first 5 bytes") -- distinct from the FINAL per-block key length, which is Hfinal in full (see this file's own top comment) and is never truncated. */
11
+ const INTERMEDIATE_HASH_LENGTH_BYTES = 5;
10
12
  function passwordToUtf16LeBytes(password) {
11
13
  const bytes = new Uint8Array(password.length * 2);
12
14
  for (let i = 0; i < password.length; i += 1) {
@@ -18,15 +20,15 @@ function passwordToUtf16LeBytes(password) {
18
20
  }
19
21
  /** The per-workbook intermediate hash (H1's own first 5 bytes) every block's key derives from -- computed once per password+salt pair, then reused across every block via deriveOfficeRc4BlockKey, since recomputing H0/H1 per block would be needless repeated work over the identical 336-byte buffer. */
20
22
  function deriveOfficeRc4BaseHash(password, salt) {
21
- const truncated = md5(passwordToUtf16LeBytes(password)).subarray(0, KEY_LENGTH_BYTES);
23
+ const truncated = md5(passwordToUtf16LeBytes(password)).subarray(0, INTERMEDIATE_HASH_LENGTH_BYTES);
22
24
  const unit = /* @__PURE__ */ new Uint8Array(21);
23
25
  unit.set(truncated, 0);
24
- unit.set(salt, KEY_LENGTH_BYTES);
26
+ unit.set(salt, INTERMEDIATE_HASH_LENGTH_BYTES);
25
27
  const buffer336 = new Uint8Array(unit.length * 16);
26
28
  for (let i = 0; i < 16; i += 1) buffer336.set(unit, i * unit.length);
27
- return md5(buffer336).subarray(0, KEY_LENGTH_BYTES);
29
+ return md5(buffer336).subarray(0, INTERMEDIATE_HASH_LENGTH_BYTES);
28
30
  }
29
- /** The real, block-specific 40-bit RC4 key: MD5(baseHash + the block number as 4 little-endian bytes), truncated to 5 bytes. */
31
+ /** The real, block-specific RC4 key: MD5(baseHash + the block number as 4 little-endian bytes) in full -- all 16 bytes, never truncated (see this file's own top comment for why that matters). */
30
32
  function deriveOfficeRc4BlockKey(baseHash, blockNumber) {
31
33
  const input = new Uint8Array(baseHash.length + 4);
32
34
  input.set(baseHash, 0);
@@ -34,21 +36,21 @@ function deriveOfficeRc4BlockKey(baseHash, blockNumber) {
34
36
  input[baseHash.length + 1] = blockNumber >>> 8 & 255;
35
37
  input[baseHash.length + 2] = blockNumber >>> 16 & 255;
36
38
  input[baseHash.length + 3] = blockNumber >>> 24 & 255;
37
- return md5(input).subarray(0, KEY_LENGTH_BYTES);
39
+ return md5(input);
38
40
  }
39
41
  /**
40
- * Decrypts `data` -- a byte range of the underlying OLE stream starting at `streamOffset` bytes from the very start of that stream -- against the RC4 encryption header scheme, re-deriving the block key at every 1024-byte boundary `data` crosses. RC4 is symmetric, so this same function also encrypts; nothing in this package uses it that way, since nothing in this family writes an encrypted legacy binary document.
42
+ * Decrypts `data` -- a byte range of the underlying OLE stream starting at `streamOffset` bytes from the very start of that stream -- against the RC4 encryption header scheme, re-deriving the block key at every `blockSize`-byte boundary `data` crosses (`OFFICE_RC4_BLOCK_SIZE`, 1024, when omitted -- the value every caller but [MS-DOC]'s own RC4 scheme uses; [MS-DOC] 2.2.6.2 re-keys every 512 bytes instead, a real difference from [MS-XLS]'s own FilePass scheme rather than a shared constant, confirmed against Apache POI's own `BinaryRC4Decryptor` (`chunkSize = 512`) directly contrasted with `Biff8DecryptingStream.RC4_REKEYING_INTERVAL` (1024) -- two genuinely separate implementations, not one shared class with a parameter). RC4 is symmetric, so this same function also encrypts; nothing in this package uses it that way, since nothing in this family writes an encrypted legacy binary document.
41
43
  *
42
- * `streamOffset` matters because the block number is the byte's own absolute position in the stream divided by 1024, not its position within whatever slice `data` happens to be -- decrypting a stream in arbitrary chunks (not just from offset 0) still lands on the correct per-block key this way.
44
+ * `streamOffset` matters because the block number is the byte's own absolute position in the stream divided by `blockSize`, not its position within whatever slice `data` happens to be -- decrypting a stream in arbitrary chunks (not just from offset 0) still lands on the correct per-block key this way.
43
45
  */
44
- function decryptOfficeRc4(baseHash, streamOffset, data) {
46
+ function decryptOfficeRc4(baseHash, streamOffset, data, blockSize = OFFICE_RC4_BLOCK_SIZE) {
45
47
  const out = new Uint8Array(data.length);
46
48
  let position = 0;
47
49
  while (position < data.length) {
48
50
  const absolute = streamOffset + position;
49
- const blockNumber = Math.floor(absolute / OFFICE_RC4_BLOCK_SIZE);
50
- const offsetWithinBlock = absolute - blockNumber * OFFICE_RC4_BLOCK_SIZE;
51
- const bytesLeftInBlock = OFFICE_RC4_BLOCK_SIZE - offsetWithinBlock;
51
+ const blockNumber = Math.floor(absolute / blockSize);
52
+ const offsetWithinBlock = absolute - blockNumber * blockSize;
53
+ const bytesLeftInBlock = blockSize - offsetWithinBlock;
52
54
  const chunkLength = Math.min(bytesLeftInBlock, data.length - position);
53
55
  const key = deriveOfficeRc4BlockKey(baseHash, blockNumber);
54
56
  const keystreamPrefixAndChunk = rc4(key, new Uint8Array(offsetWithinBlock + chunkLength));
@@ -61,4 +63,4 @@ function decryptOfficeRc4(baseHash, streamOffset, data) {
61
63
  return out;
62
64
  }
63
65
  //#endregion
64
- export { OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey };
66
+ export { OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey };
package/dist/index.cjs CHANGED
@@ -21,6 +21,7 @@ exports.MAX_CFB_TOTAL_STREAM_BYTES = require_cfb_read.MAX_CFB_TOTAL_STREAM_BYTES
21
21
  exports.MAX_WALK_DEPTH = require_zip_walk.MAX_WALK_DEPTH;
22
22
  exports.MAX_WALK_TOTAL_BYTES = require_zip_walk.MAX_WALK_TOTAL_BYTES;
23
23
  exports.OFFICE_RC4_BLOCK_SIZE = require_crypto_office_rc4.OFFICE_RC4_BLOCK_SIZE;
24
+ exports.OFFICE_RC4_DOC_BLOCK_SIZE = require_crypto_office_rc4.OFFICE_RC4_DOC_BLOCK_SIZE;
24
25
  exports.OFFICE_RC4_VERIFIER_LENGTH = require_crypto_office_rc4.OFFICE_RC4_VERIFIER_LENGTH;
25
26
  exports.OlePackageFormatError = require_cfb_ole_package.OlePackageFormatError;
26
27
  exports.OlePackageWriteError = require_cfb_ole_package.OlePackageWriteError;
package/dist/index.d.cts CHANGED
@@ -3,7 +3,7 @@ import { OlePackage, OlePackageFormatError, OlePackageWriteError, readOlePackage
3
3
  import { CompoundFileFormatError, CompoundFileStream, MAX_CFB_TOTAL_STREAM_BYTES, ReadCompoundFileOptions, readCompoundFile } from "./cfb/read.cjs";
4
4
  import { CompoundFileWriteError, WriteCompoundFileOptions, writeCompoundFile } from "./cfb/write.cjs";
5
5
  import { md5 } from "./crypto/md5.cjs";
6
- import { OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey } from "./crypto/office-rc4.cjs";
6
+ import { OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey } from "./crypto/office-rc4.cjs";
7
7
  import { rc4 } from "./crypto/rc4.cjs";
8
8
  import { FMTID_SUMMARY_INFORMATION, SummaryInformationProperties, readSummaryInformation, writeSummaryInformationStream } from "./oleps/summary-information.cjs";
9
9
  import { hasSummaryInformationFields, layoutMetadataToSummaryInformation, summaryInformationToLayoutMetadata } from "./oleps/layout-metadata.cjs";
@@ -13,4 +13,4 @@ import { PropertySetWriteError, writePropertySetStream } from "./oleps/write.cjs
13
13
  import { ZipEntry, unzipPackage, zipPackage } from "./zip/container.cjs";
14
14
  import { ArchiveFormat, detectArchiveFormat, isZipArchive } from "./zip/detect.cjs";
15
15
  import { ArchiveWalkEntry, ArchiveWalkLimit, ArchiveWalkLimitError, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, WalkArchiveOptions, walkArchive } from "./zip/walk.cjs";
16
- export { ArchiveFormat, ArchiveWalkEntry, ArchiveWalkLimit, ArchiveWalkLimitError, CompoundFileFormatError, CompoundFileStream, CompoundFileWriteError, FMTID_SUMMARY_INFORMATION, MAX_CFB_TOTAL_STREAM_BYTES, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, OlePackage, OlePackageFormatError, OlePackageWriteError, type PropertySet, PropertySetFormatError, PropertySetWriteError, type PropertyValue, ReadCompoundFileOptions, SummaryInformationProperties, WalkArchiveOptions, WriteCompoundFileOptions, ZipEntry, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey, detectArchiveFormat, hasSummaryInformationFields, isCompoundFile, isZipArchive, layoutMetadataToSummaryInformation, md5, rc4, readCompoundFile, readOlePackage, readPropertySetStream, readSummaryInformation, summaryInformationToLayoutMetadata, unzipPackage, walkArchive, writeCompoundFile, writeOlePackage, writePropertySetStream, writeSummaryInformationStream, zipPackage };
16
+ export { ArchiveFormat, ArchiveWalkEntry, ArchiveWalkLimit, ArchiveWalkLimitError, CompoundFileFormatError, CompoundFileStream, CompoundFileWriteError, FMTID_SUMMARY_INFORMATION, MAX_CFB_TOTAL_STREAM_BYTES, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, OlePackage, OlePackageFormatError, OlePackageWriteError, type PropertySet, PropertySetFormatError, PropertySetWriteError, type PropertyValue, ReadCompoundFileOptions, SummaryInformationProperties, WalkArchiveOptions, WriteCompoundFileOptions, ZipEntry, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey, detectArchiveFormat, hasSummaryInformationFields, isCompoundFile, isZipArchive, layoutMetadataToSummaryInformation, md5, rc4, readCompoundFile, readOlePackage, readPropertySetStream, readSummaryInformation, summaryInformationToLayoutMetadata, unzipPackage, walkArchive, writeCompoundFile, writeOlePackage, writePropertySetStream, writeSummaryInformationStream, zipPackage };
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { OlePackage, OlePackageFormatError, OlePackageWriteError, readOlePackage
3
3
  import { CompoundFileFormatError, CompoundFileStream, MAX_CFB_TOTAL_STREAM_BYTES, ReadCompoundFileOptions, readCompoundFile } from "./cfb/read.js";
4
4
  import { CompoundFileWriteError, WriteCompoundFileOptions, writeCompoundFile } from "./cfb/write.js";
5
5
  import { md5 } from "./crypto/md5.js";
6
- import { OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey } from "./crypto/office-rc4.js";
6
+ import { OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey } from "./crypto/office-rc4.js";
7
7
  import { rc4 } from "./crypto/rc4.js";
8
8
  import { FMTID_SUMMARY_INFORMATION, SummaryInformationProperties, readSummaryInformation, writeSummaryInformationStream } from "./oleps/summary-information.js";
9
9
  import { hasSummaryInformationFields, layoutMetadataToSummaryInformation, summaryInformationToLayoutMetadata } from "./oleps/layout-metadata.js";
@@ -13,4 +13,4 @@ import { PropertySetWriteError, writePropertySetStream } from "./oleps/write.js"
13
13
  import { ZipEntry, unzipPackage, zipPackage } from "./zip/container.js";
14
14
  import { ArchiveFormat, detectArchiveFormat, isZipArchive } from "./zip/detect.js";
15
15
  import { ArchiveWalkEntry, ArchiveWalkLimit, ArchiveWalkLimitError, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, WalkArchiveOptions, walkArchive } from "./zip/walk.js";
16
- export { ArchiveFormat, ArchiveWalkEntry, ArchiveWalkLimit, ArchiveWalkLimitError, CompoundFileFormatError, CompoundFileStream, CompoundFileWriteError, FMTID_SUMMARY_INFORMATION, MAX_CFB_TOTAL_STREAM_BYTES, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, OlePackage, OlePackageFormatError, OlePackageWriteError, type PropertySet, PropertySetFormatError, PropertySetWriteError, type PropertyValue, ReadCompoundFileOptions, SummaryInformationProperties, WalkArchiveOptions, WriteCompoundFileOptions, ZipEntry, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey, detectArchiveFormat, hasSummaryInformationFields, isCompoundFile, isZipArchive, layoutMetadataToSummaryInformation, md5, rc4, readCompoundFile, readOlePackage, readPropertySetStream, readSummaryInformation, summaryInformationToLayoutMetadata, unzipPackage, walkArchive, writeCompoundFile, writeOlePackage, writePropertySetStream, writeSummaryInformationStream, zipPackage };
16
+ export { ArchiveFormat, ArchiveWalkEntry, ArchiveWalkLimit, ArchiveWalkLimitError, CompoundFileFormatError, CompoundFileStream, CompoundFileWriteError, FMTID_SUMMARY_INFORMATION, MAX_CFB_TOTAL_STREAM_BYTES, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, OlePackage, OlePackageFormatError, OlePackageWriteError, type PropertySet, PropertySetFormatError, PropertySetWriteError, type PropertyValue, ReadCompoundFileOptions, SummaryInformationProperties, WalkArchiveOptions, WriteCompoundFileOptions, ZipEntry, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey, detectArchiveFormat, hasSummaryInformationFields, isCompoundFile, isZipArchive, layoutMetadataToSummaryInformation, md5, rc4, readCompoundFile, readOlePackage, readPropertySetStream, readSummaryInformation, summaryInformationToLayoutMetadata, unzipPackage, walkArchive, writeCompoundFile, writeOlePackage, writePropertySetStream, writeSummaryInformationStream, zipPackage };
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import { CompoundFileFormatError, MAX_CFB_TOTAL_STREAM_BYTES, readCompoundFile }
4
4
  import { CompoundFileWriteError, writeCompoundFile } from "./cfb/write.js";
5
5
  import { md5 } from "./crypto/md5.js";
6
6
  import { rc4 } from "./crypto/rc4.js";
7
- import { OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey } from "./crypto/office-rc4.js";
7
+ import { OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey } from "./crypto/office-rc4.js";
8
8
  import { hasSummaryInformationFields, layoutMetadataToSummaryInformation, summaryInformationToLayoutMetadata } from "./oleps/layout-metadata.js";
9
9
  import { PropertySetFormatError, readPropertySetStream } from "./oleps/read.js";
10
10
  import { PropertySetWriteError, writePropertySetStream } from "./oleps/write.js";
@@ -12,4 +12,4 @@ import { FMTID_SUMMARY_INFORMATION, readSummaryInformation, writeSummaryInformat
12
12
  import { unzipPackage, zipPackage } from "./zip/container.js";
13
13
  import { detectArchiveFormat, isZipArchive } from "./zip/detect.js";
14
14
  import { ArchiveWalkLimitError, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, walkArchive } from "./zip/walk.js";
15
- export { ArchiveWalkLimitError, CompoundFileFormatError, CompoundFileWriteError, FMTID_SUMMARY_INFORMATION, MAX_CFB_TOTAL_STREAM_BYTES, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, OlePackageFormatError, OlePackageWriteError, PropertySetFormatError, PropertySetWriteError, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey, detectArchiveFormat, hasSummaryInformationFields, isCompoundFile, isZipArchive, layoutMetadataToSummaryInformation, md5, rc4, readCompoundFile, readOlePackage, readPropertySetStream, readSummaryInformation, summaryInformationToLayoutMetadata, unzipPackage, walkArchive, writeCompoundFile, writeOlePackage, writePropertySetStream, writeSummaryInformationStream, zipPackage };
15
+ export { ArchiveWalkLimitError, CompoundFileFormatError, CompoundFileWriteError, FMTID_SUMMARY_INFORMATION, MAX_CFB_TOTAL_STREAM_BYTES, MAX_WALK_DEPTH, MAX_WALK_TOTAL_BYTES, OFFICE_RC4_BLOCK_SIZE, OFFICE_RC4_DOC_BLOCK_SIZE, OFFICE_RC4_VERIFIER_LENGTH, OlePackageFormatError, OlePackageWriteError, PropertySetFormatError, PropertySetWriteError, decryptOfficeRc4, deriveOfficeRc4BaseHash, deriveOfficeRc4BlockKey, detectArchiveFormat, hasSummaryInformationFields, isCompoundFile, isZipArchive, layoutMetadataToSummaryInformation, md5, rc4, readCompoundFile, readOlePackage, readPropertySetStream, readSummaryInformation, summaryInformationToLayoutMetadata, unzipPackage, walkArchive, writeCompoundFile, writeOlePackage, writePropertySetStream, writeSummaryInformationStream, zipPackage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "archive-codec",
3
- "version": "1.7.1",
3
+ "version": "1.8.0",
4
4
  "description": "ZIP-in-ZIP recursive walking with depth and cumulative decompressed-size guards, bounded classic OLE compound-file ([MS-CFB]) reading and writing, and [MS-OLEPS] Property Set Stream reading and writing - zero document-format knowledge, the archive and container utility package for the documents.js family.",
5
5
  "type": "module",
6
6
  "repository": {