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 +5 -3
- package/dist/crypto/office-rc4.cjs +17 -14
- package/dist/crypto/office-rc4.d.cts +8 -6
- package/dist/crypto/office-rc4.d.ts +8 -6
- package/dist/crypto/office-rc4.js +17 -15
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/package.json +1 -1
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
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
10
|
-
const
|
|
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,
|
|
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,
|
|
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,
|
|
30
|
+
return require_crypto_md5.md5(buffer336).subarray(0, INTERMEDIATE_HASH_LENGTH_BYTES);
|
|
29
31
|
}
|
|
30
|
-
/** The real, block-specific
|
|
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)
|
|
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
|
|
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
|
|
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 /
|
|
51
|
-
const offsetWithinBlock = absolute - blockNumber *
|
|
52
|
-
const bytesLeftInBlock =
|
|
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
|
-
/**
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
/**
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
9
|
-
const
|
|
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,
|
|
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,
|
|
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,
|
|
29
|
+
return md5(buffer336).subarray(0, INTERMEDIATE_HASH_LENGTH_BYTES);
|
|
28
30
|
}
|
|
29
|
-
/** The real, block-specific
|
|
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)
|
|
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
|
|
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
|
|
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 /
|
|
50
|
-
const offsetWithinBlock = absolute - blockNumber *
|
|
51
|
-
const bytesLeftInBlock =
|
|
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.
|
|
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": {
|