pdf-codec 4.0.13 → 4.2.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 +6 -5
- package/dist/annotations.d.cts +1 -1
- package/dist/annotations.d.ts +1 -1
- package/dist/attachments.d.cts +1 -1
- package/dist/attachments.d.ts +1 -1
- package/dist/content-read.d.cts +1 -1
- package/dist/content-read.d.ts +1 -1
- package/dist/crypto/random.cjs +9 -0
- package/dist/crypto/random.d.cts +4 -0
- package/dist/crypto/random.d.ts +4 -0
- package/dist/crypto/random.js +8 -0
- package/dist/document.d.cts +1 -1
- package/dist/document.d.ts +1 -1
- package/dist/embedded-font-write.d.cts +1 -1
- package/dist/embedded-font-write.d.ts +1 -1
- package/dist/encrypt-write.cjs +234 -0
- package/dist/encrypt-write.d.cts +31 -0
- package/dist/encrypt-write.d.ts +31 -0
- package/dist/encrypt-write.js +231 -0
- package/dist/encrypt.cjs +50 -20
- package/dist/encrypt.d.cts +18 -2
- package/dist/encrypt.d.ts +18 -2
- package/dist/encrypt.js +35 -21
- package/dist/filters.d.cts +1 -1
- package/dist/filters.d.ts +1 -1
- package/dist/font-read.d.cts +1 -1
- package/dist/font-read.d.ts +1 -1
- package/dist/form.d.cts +1 -1
- package/dist/form.d.ts +1 -1
- package/dist/images-read.d.cts +1 -1
- package/dist/images-read.d.ts +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/interpret.d.cts +1 -1
- package/dist/interpret.d.ts +1 -1
- package/dist/math-font-write.d.cts +1 -1
- package/dist/math-font-write.d.ts +1 -1
- package/dist/names.d.cts +1 -1
- package/dist/names.d.ts +1 -1
- package/dist/navigation.d.cts +1 -1
- package/dist/navigation.d.ts +1 -1
- package/dist/objects-B7HdMeWS.d.cts +59 -0
- package/dist/objects-B7HdMeWS.d.ts +59 -0
- package/dist/objects.d.cts +1 -58
- package/dist/objects.d.ts +1 -58
- package/dist/optional-content.d.cts +1 -1
- package/dist/optional-content.d.ts +1 -1
- package/dist/parse.d.cts +1 -1
- package/dist/parse.d.ts +1 -1
- package/dist/predictors.d.cts +1 -1
- package/dist/predictors.d.ts +1 -1
- package/dist/serialize.d.cts +1 -1
- package/dist/serialize.d.ts +1 -1
- package/dist/structure.d.cts +1 -1
- package/dist/structure.d.ts +1 -1
- package/dist/tounicode.d.cts +1 -1
- package/dist/tounicode.d.ts +1 -1
- package/dist/write.cjs +123 -15
- package/dist/write.d.cts +2 -0
- package/dist/write.d.ts +2 -0
- package/dist/write.js +124 -16
- package/dist/xref.d.cts +1 -1
- package/dist/xref.d.ts +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { pdfArray, pdfBool, pdfDict, pdfHexString, pdfName, pdfNum } from "./objects.js";
|
|
2
|
+
import { concatBytes } from "./bytes/writer.js";
|
|
3
|
+
import { aesCbcEncrypt } from "./crypto/aes.js";
|
|
4
|
+
import { md5 } from "./crypto/md5.js";
|
|
5
|
+
import { rc4 } from "./crypto/rc4.js";
|
|
6
|
+
import { PASSWORD_PADDING, ZERO_IV, computeLegacyFileKeyFromPaddedPassword, hardenedHash, legacyUserValueCore, objectKey, padOrTruncatePassword, permissionsBytes } from "./encrypt.js";
|
|
7
|
+
import { randomBytes } from "./crypto/random.js";
|
|
8
|
+
//#region src/encrypt-write.ts
|
|
9
|
+
var PdfEncryptionError = class extends Error {
|
|
10
|
+
constructor(message) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = "PdfEncryptionError";
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const RC4_128_KEY_BYTES = 16;
|
|
16
|
+
const R6_PASSWORD_MAX_BYTES = 127;
|
|
17
|
+
const RESERVED_BIT_7_AND_8 = 192;
|
|
18
|
+
const DEPRECATED_ALWAYS_ONE_BIT_10 = 512;
|
|
19
|
+
const SCHEME_SPECS = {
|
|
20
|
+
"rc4-40": {
|
|
21
|
+
v: 1,
|
|
22
|
+
r: 2,
|
|
23
|
+
keyBytes: 5,
|
|
24
|
+
method: "rc4"
|
|
25
|
+
},
|
|
26
|
+
"rc4-128": {
|
|
27
|
+
v: 2,
|
|
28
|
+
r: 3,
|
|
29
|
+
keyBytes: RC4_128_KEY_BYTES,
|
|
30
|
+
method: "rc4"
|
|
31
|
+
},
|
|
32
|
+
"aes-128": {
|
|
33
|
+
v: 4,
|
|
34
|
+
r: 4,
|
|
35
|
+
keyBytes: 16,
|
|
36
|
+
method: "aes"
|
|
37
|
+
},
|
|
38
|
+
"aes-256": {
|
|
39
|
+
v: 5,
|
|
40
|
+
r: 6,
|
|
41
|
+
keyBytes: 32,
|
|
42
|
+
method: "aes"
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
function legacyPasswordBytes(password) {
|
|
46
|
+
const bytes = new Uint8Array(password.length);
|
|
47
|
+
for (let i = 0; i < password.length; i++) {
|
|
48
|
+
const code = password.charCodeAt(i);
|
|
49
|
+
if (code > 127) throw new PdfEncryptionError(`password contains character code ${String(code)}, outside the printable-ASCII range this writer supports for the rc4-40/rc4-128/aes-128 schemes; use a plain-ASCII password, or the aes-256 scheme, whose revision-6 passwords are Unicode`);
|
|
50
|
+
bytes[i] = code;
|
|
51
|
+
}
|
|
52
|
+
return bytes;
|
|
53
|
+
}
|
|
54
|
+
function r6PasswordBytes(password) {
|
|
55
|
+
return new TextEncoder().encode(password.normalize("NFKC")).subarray(0, R6_PASSWORD_MAX_BYTES);
|
|
56
|
+
}
|
|
57
|
+
function permissionsToP(permissions) {
|
|
58
|
+
let p = 0;
|
|
59
|
+
if (permissions?.print ?? true) p |= 4;
|
|
60
|
+
if (permissions?.modifyContents ?? true) p |= 8;
|
|
61
|
+
if (permissions?.copy ?? true) p |= 16;
|
|
62
|
+
if (permissions?.annotate ?? true) p |= 32;
|
|
63
|
+
p |= RESERVED_BIT_7_AND_8;
|
|
64
|
+
if (permissions?.fillForms ?? true) p |= 256;
|
|
65
|
+
p |= DEPRECATED_ALWAYS_ONE_BIT_10;
|
|
66
|
+
if (permissions?.assemble ?? true) p |= 1024;
|
|
67
|
+
if (permissions?.printHighRes ?? true) p |= 2048;
|
|
68
|
+
for (let bit = 13; bit <= 32; bit++) p |= 1 << bit - 1;
|
|
69
|
+
return p;
|
|
70
|
+
}
|
|
71
|
+
function computeLegacyOwnerValue(ownerPassword, userPassword, revision, keyBytes) {
|
|
72
|
+
let digest = md5(padOrTruncatePassword(ownerPassword));
|
|
73
|
+
if (revision >= 3) for (let i = 0; i < 50; i++) digest = md5(digest);
|
|
74
|
+
const ownerKey = digest.subarray(0, keyBytes);
|
|
75
|
+
let value = rc4(ownerKey, padOrTruncatePassword(userPassword));
|
|
76
|
+
if (revision >= 3) for (let i = 1; i <= 19; i++) {
|
|
77
|
+
const roundKey = Uint8Array.from(ownerKey, (byte) => byte ^ i);
|
|
78
|
+
value = rc4(roundKey, value);
|
|
79
|
+
}
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
function computeLegacyUserValue(fileKey, fileId, revision) {
|
|
83
|
+
const core = legacyUserValueCore(fileKey, fileId, revision);
|
|
84
|
+
if (revision === 2) return core;
|
|
85
|
+
return concatBytes([core, randomBytes(PASSWORD_PADDING.length - core.length)]);
|
|
86
|
+
}
|
|
87
|
+
function encryptAes(key, data) {
|
|
88
|
+
const iv = randomBytes(16);
|
|
89
|
+
const padLength = 16 - data.length % 16;
|
|
90
|
+
const padded = new Uint8Array(data.length + padLength);
|
|
91
|
+
padded.set(data);
|
|
92
|
+
padded.fill(padLength, data.length);
|
|
93
|
+
return concatBytes([iv, aesCbcEncrypt(key, iv, padded)]);
|
|
94
|
+
}
|
|
95
|
+
function applyEncryptMethod(method, fileKey, perObjectKeys, bytes, num, gen) {
|
|
96
|
+
if (method === "identity") return bytes;
|
|
97
|
+
const key = perObjectKeys ? objectKey(fileKey, num, gen, method) : fileKey;
|
|
98
|
+
return method === "rc4" ? rc4(key, bytes) : encryptAes(key, bytes);
|
|
99
|
+
}
|
|
100
|
+
function buildEncryptor(encryptDict, fileKey, method, perObjectKeys, encryptMetadata) {
|
|
101
|
+
return {
|
|
102
|
+
encryptDict,
|
|
103
|
+
encryptString(bytes, num, gen) {
|
|
104
|
+
return applyEncryptMethod(method, fileKey, perObjectKeys, bytes, num, gen);
|
|
105
|
+
},
|
|
106
|
+
encryptStream(bytes, dict, num, gen) {
|
|
107
|
+
const type = dict.entries.get("Type");
|
|
108
|
+
if (!encryptMetadata && type?.kind === "name" && type.name === "Metadata") return bytes;
|
|
109
|
+
return applyEncryptMethod(method, fileKey, perObjectKeys, bytes, num, gen);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function buildLegacyEncryptor(spec, options, fileId) {
|
|
114
|
+
const userPassword = legacyPasswordBytes(options.userPassword ?? "");
|
|
115
|
+
const ownerPassword = legacyPasswordBytes(options.ownerPassword ?? options.userPassword ?? "");
|
|
116
|
+
const encryptMetadata = options.encryptMetadata ?? true;
|
|
117
|
+
const p = permissionsToP(options.permissions);
|
|
118
|
+
const owner = computeLegacyOwnerValue(ownerPassword, userPassword, spec.r, spec.keyBytes);
|
|
119
|
+
const fileKey = computeLegacyFileKeyFromPaddedPassword(padOrTruncatePassword(userPassword), owner, p, fileId, spec.r, spec.keyBytes, encryptMetadata);
|
|
120
|
+
const user = computeLegacyUserValue(fileKey, fileId, spec.r);
|
|
121
|
+
const entries = /* @__PURE__ */ new Map([
|
|
122
|
+
["Filter", pdfName("Standard")],
|
|
123
|
+
["V", pdfNum(spec.v)],
|
|
124
|
+
["R", pdfNum(spec.r)],
|
|
125
|
+
["O", pdfHexString(owner)],
|
|
126
|
+
["U", pdfHexString(user)],
|
|
127
|
+
["P", pdfNum(p)],
|
|
128
|
+
["Length", pdfNum(spec.keyBytes * 8)]
|
|
129
|
+
]);
|
|
130
|
+
if (spec.v === 4) {
|
|
131
|
+
entries.set("CF", pdfDict({ StdCF: pdfDict({
|
|
132
|
+
AuthEvent: pdfName("DocOpen"),
|
|
133
|
+
CFM: pdfName("AESV2"),
|
|
134
|
+
Length: pdfNum(spec.keyBytes)
|
|
135
|
+
}) }));
|
|
136
|
+
entries.set("StmF", pdfName("StdCF"));
|
|
137
|
+
entries.set("StrF", pdfName("StdCF"));
|
|
138
|
+
entries.set("EncryptMetadata", pdfBool(encryptMetadata));
|
|
139
|
+
}
|
|
140
|
+
return buildEncryptor(pdfDict(entries), fileKey, spec.method, true, encryptMetadata);
|
|
141
|
+
}
|
|
142
|
+
function buildAes256Encryptor(spec, options) {
|
|
143
|
+
const userPassword = r6PasswordBytes(options.userPassword ?? "");
|
|
144
|
+
const ownerPassword = r6PasswordBytes(options.ownerPassword ?? options.userPassword ?? "");
|
|
145
|
+
const encryptMetadata = options.encryptMetadata ?? true;
|
|
146
|
+
const p = permissionsToP(options.permissions);
|
|
147
|
+
const fileKey = randomBytes(32);
|
|
148
|
+
const userValidationSalt = randomBytes(8);
|
|
149
|
+
const userKeySalt = randomBytes(8);
|
|
150
|
+
const empty = /* @__PURE__ */ new Uint8Array(0);
|
|
151
|
+
const userHash = hardenedHash(userPassword, userValidationSalt, empty, spec.r);
|
|
152
|
+
const u = concatBytes([
|
|
153
|
+
userHash,
|
|
154
|
+
userValidationSalt,
|
|
155
|
+
userKeySalt
|
|
156
|
+
]);
|
|
157
|
+
const userIntermediateKey = hardenedHash(userPassword, userKeySalt, empty, spec.r);
|
|
158
|
+
const ue = aesCbcEncrypt(userIntermediateKey, ZERO_IV, fileKey);
|
|
159
|
+
const ownerValidationSalt = randomBytes(8);
|
|
160
|
+
const ownerKeySalt = randomBytes(8);
|
|
161
|
+
const ownerHash = hardenedHash(ownerPassword, ownerValidationSalt, u, spec.r);
|
|
162
|
+
const o = concatBytes([
|
|
163
|
+
ownerHash,
|
|
164
|
+
ownerValidationSalt,
|
|
165
|
+
ownerKeySalt
|
|
166
|
+
]);
|
|
167
|
+
const ownerIntermediateKey = hardenedHash(ownerPassword, ownerKeySalt, u, spec.r);
|
|
168
|
+
const oe = aesCbcEncrypt(ownerIntermediateKey, ZERO_IV, fileKey);
|
|
169
|
+
const permsBlock = /* @__PURE__ */ new Uint8Array(16);
|
|
170
|
+
permsBlock.set(permissionsBytes(p), 0);
|
|
171
|
+
permsBlock.set([
|
|
172
|
+
255,
|
|
173
|
+
255,
|
|
174
|
+
255,
|
|
175
|
+
255
|
|
176
|
+
], 4);
|
|
177
|
+
permsBlock[8] = encryptMetadata ? 84 : 70;
|
|
178
|
+
permsBlock.set([
|
|
179
|
+
97,
|
|
180
|
+
100,
|
|
181
|
+
98
|
|
182
|
+
], 9);
|
|
183
|
+
permsBlock.set(randomBytes(4), 12);
|
|
184
|
+
const perms = aesCbcEncrypt(fileKey, ZERO_IV, permsBlock);
|
|
185
|
+
const entries = /* @__PURE__ */ new Map([
|
|
186
|
+
["Filter", pdfName("Standard")],
|
|
187
|
+
["V", pdfNum(spec.v)],
|
|
188
|
+
["R", pdfNum(spec.r)],
|
|
189
|
+
["O", pdfHexString(o)],
|
|
190
|
+
["U", pdfHexString(u)],
|
|
191
|
+
["OE", pdfHexString(oe)],
|
|
192
|
+
["UE", pdfHexString(ue)],
|
|
193
|
+
["P", pdfNum(p)],
|
|
194
|
+
["Perms", pdfHexString(perms)],
|
|
195
|
+
["Length", pdfNum(spec.keyBytes * 8)],
|
|
196
|
+
["CF", pdfDict({ StdCF: pdfDict({
|
|
197
|
+
AuthEvent: pdfName("DocOpen"),
|
|
198
|
+
CFM: pdfName("AESV3"),
|
|
199
|
+
Length: pdfNum(spec.keyBytes)
|
|
200
|
+
}) })],
|
|
201
|
+
["StmF", pdfName("StdCF")],
|
|
202
|
+
["StrF", pdfName("StdCF")],
|
|
203
|
+
["EncryptMetadata", pdfBool(encryptMetadata)]
|
|
204
|
+
]);
|
|
205
|
+
return buildEncryptor(pdfDict(entries), fileKey, spec.method, false, encryptMetadata);
|
|
206
|
+
}
|
|
207
|
+
function createStandardEncryptor(options, fileId) {
|
|
208
|
+
const scheme = options.scheme ?? "aes-256";
|
|
209
|
+
const spec = SCHEME_SPECS[scheme];
|
|
210
|
+
return spec.v === 5 ? buildAes256Encryptor(spec, options) : buildLegacyEncryptor(spec, options, fileId);
|
|
211
|
+
}
|
|
212
|
+
function encryptIndirectObject(value, num, gen, encryptor) {
|
|
213
|
+
if (value.kind === "string") return {
|
|
214
|
+
kind: "string",
|
|
215
|
+
bytes: encryptor.encryptString(value.bytes, num, gen),
|
|
216
|
+
hex: value.hex
|
|
217
|
+
};
|
|
218
|
+
if (value.kind === "array") return pdfArray(value.items.map((item) => encryptIndirectObject(item, num, gen, encryptor)));
|
|
219
|
+
if (value.kind === "dict") return encryptDictEntries(value, num, gen, encryptor);
|
|
220
|
+
if (value.kind === "stream") return {
|
|
221
|
+
kind: "stream",
|
|
222
|
+
dict: encryptDictEntries(value.dict, num, gen, encryptor),
|
|
223
|
+
raw: encryptor.encryptStream(value.raw, value.dict, num, gen)
|
|
224
|
+
};
|
|
225
|
+
return value;
|
|
226
|
+
}
|
|
227
|
+
function encryptDictEntries(dict, num, gen, encryptor) {
|
|
228
|
+
return pdfDict(new Map(Array.from(dict.entries, ([key, entry]) => [key, encryptIndirectObject(entry, num, gen, encryptor)])));
|
|
229
|
+
}
|
|
230
|
+
//#endregion
|
|
231
|
+
export { PdfEncryptionError, createStandardEncryptor, encryptIndirectObject };
|
package/dist/encrypt.cjs
CHANGED
|
@@ -50,11 +50,12 @@ const AES_OBJECT_KEY_SALT = new Uint8Array([
|
|
|
50
50
|
const MD5_DIGEST_BYTES = 16;
|
|
51
51
|
const OBJECT_KEY_EXTRA_BYTES = 5;
|
|
52
52
|
const LEGACY_KEY_ITERATIONS = 50;
|
|
53
|
-
const
|
|
53
|
+
const RC4_OBFUSCATION_ROUNDS = 19;
|
|
54
54
|
const R6_MINIMUM_ROUNDS = 64;
|
|
55
55
|
const R6_ROUND_REPEATS = 64;
|
|
56
56
|
const R6_TERMINATION_MARGIN = 32;
|
|
57
57
|
const AESV3_KEY_BYTES = 32;
|
|
58
|
+
const AESV3_SALT_BYTES = 8;
|
|
58
59
|
const RC4_40_KEY_BYTES = 5;
|
|
59
60
|
const AESV2_KEY_BYTES = 16;
|
|
60
61
|
const DEFAULT_KEY_BITS = 40;
|
|
@@ -80,11 +81,16 @@ function permissionsBytes(p) {
|
|
|
80
81
|
unsigned >>> 24 & 255
|
|
81
82
|
]);
|
|
82
83
|
}
|
|
83
|
-
function
|
|
84
|
-
|
|
85
|
-
const
|
|
84
|
+
function padOrTruncatePassword(password) {
|
|
85
|
+
if (password.length >= PASSWORD_PADDING.length) return password.subarray(0, PASSWORD_PADDING.length);
|
|
86
|
+
const padded = new Uint8Array(PASSWORD_PADDING.length);
|
|
87
|
+
padded.set(password);
|
|
88
|
+
padded.set(PASSWORD_PADDING.subarray(0, PASSWORD_PADDING.length - password.length), password.length);
|
|
89
|
+
return padded;
|
|
90
|
+
}
|
|
91
|
+
function computeLegacyFileKeyFromPaddedPassword(paddedPassword, owner, permissions, fileId, revision, keyBytes, encryptMetadata) {
|
|
86
92
|
const parts = [
|
|
87
|
-
|
|
93
|
+
paddedPassword,
|
|
88
94
|
owner.subarray(0, PASSWORD_PADDING.length),
|
|
89
95
|
permissionsBytes(permissions),
|
|
90
96
|
fileId
|
|
@@ -96,18 +102,26 @@ function computeLegacyFileKey(encryptDict, fileId, revision, keyBytes, encryptMe
|
|
|
96
102
|
255
|
|
97
103
|
]));
|
|
98
104
|
let digest = require_crypto_md5.md5(require_bytes_writer.concatBytes(parts));
|
|
99
|
-
if (revision >= 3) for (let i = 0; i <
|
|
105
|
+
if (revision >= 3) for (let i = 0; i < 50; i++) digest = require_crypto_md5.md5(digest.subarray(0, keyBytes));
|
|
100
106
|
return digest.subarray(0, keyBytes);
|
|
101
107
|
}
|
|
102
|
-
function
|
|
103
|
-
const
|
|
104
|
-
|
|
108
|
+
function computeLegacyFileKey(encryptDict, fileId, revision, keyBytes, encryptMetadata) {
|
|
109
|
+
const owner = requireStringBytes(encryptDict, "O");
|
|
110
|
+
const permissions = require_objects.asNumber(require_objects.dictGet(encryptDict, "P")) ?? 0;
|
|
111
|
+
return computeLegacyFileKeyFromPaddedPassword(PASSWORD_PADDING, owner, permissions, fileId, revision, keyBytes, encryptMetadata);
|
|
112
|
+
}
|
|
113
|
+
function legacyUserValueCore(fileKey, fileId, revision) {
|
|
114
|
+
if (revision === 2) return require_crypto_rc4.rc4(fileKey, PASSWORD_PADDING);
|
|
105
115
|
let value = require_crypto_rc4.rc4(fileKey, require_crypto_md5.md5(require_bytes_writer.concatBytes([PASSWORD_PADDING, fileId])));
|
|
106
|
-
for (let i = 1; i <=
|
|
116
|
+
for (let i = 1; i <= 19; i++) {
|
|
107
117
|
const roundKey = Uint8Array.from(fileKey, (byte) => byte ^ i);
|
|
108
118
|
value = require_crypto_rc4.rc4(roundKey, value);
|
|
109
119
|
}
|
|
110
|
-
return
|
|
120
|
+
return value;
|
|
121
|
+
}
|
|
122
|
+
function legacyUserPasswordVerifies(encryptDict, fileId, revision, fileKey) {
|
|
123
|
+
const storedUser = requireStringBytes(encryptDict, "U");
|
|
124
|
+
return bytesEqual(legacyUserValueCore(fileKey, fileId, revision), storedUser, revision === 2 ? PASSWORD_PADDING.length : 16);
|
|
111
125
|
}
|
|
112
126
|
function hardenedHash(password, salt, userData, revision) {
|
|
113
127
|
let k = require_crypto_sha2.sha256(require_bytes_writer.concatBytes([
|
|
@@ -133,20 +147,20 @@ function hardenedHash(password, salt, userData, revision) {
|
|
|
133
147
|
k = selector === 0 ? require_crypto_sha2.sha256(e) : selector === 1 ? require_crypto_sha2.sha384(e) : require_crypto_sha2.sha512(e);
|
|
134
148
|
round++;
|
|
135
149
|
}
|
|
136
|
-
return k.subarray(0,
|
|
150
|
+
return k.subarray(0, 32);
|
|
137
151
|
}
|
|
138
152
|
function computeAesV3FileKey(encryptDict, revision) {
|
|
139
153
|
const storedUser = requireStringBytes(encryptDict, "U");
|
|
140
154
|
const expectedLength = 48;
|
|
141
155
|
if (storedUser.length < expectedLength) throw new require_diagnostics.PdfEncryptedError(`the /Encrypt dictionary's /U entry is ${String(storedUser.length)} bytes; revision ${String(revision)} requires ${String(expectedLength)}`);
|
|
142
156
|
const empty = /* @__PURE__ */ new Uint8Array(0);
|
|
143
|
-
const validationSalt = storedUser.subarray(
|
|
157
|
+
const validationSalt = storedUser.subarray(32, 40);
|
|
144
158
|
const keySalt = storedUser.subarray(40, expectedLength);
|
|
145
|
-
if (!bytesEqual(hardenedHash(empty, validationSalt, empty, revision), storedUser,
|
|
159
|
+
if (!bytesEqual(hardenedHash(empty, validationSalt, empty, revision), storedUser, 32)) throw new require_diagnostics.PdfPasswordRequiredError();
|
|
146
160
|
const intermediateKey = hardenedHash(empty, keySalt, empty, revision);
|
|
147
161
|
const wrappedKey = requireStringBytes(encryptDict, "UE");
|
|
148
|
-
if (wrappedKey.length <
|
|
149
|
-
return require_crypto_aes.aesCbcDecrypt(intermediateKey, ZERO_IV, wrappedKey.subarray(0,
|
|
162
|
+
if (wrappedKey.length < 32) throw new require_diagnostics.PdfEncryptedError(`the /Encrypt dictionary's /UE entry is ${String(wrappedKey.length)} bytes; revision ${String(revision)} requires ${String(32)}`);
|
|
163
|
+
return require_crypto_aes.aesCbcDecrypt(intermediateKey, ZERO_IV, wrappedKey.subarray(0, 32));
|
|
150
164
|
}
|
|
151
165
|
function methodFromCryptFilterName(encryptDict, entryKey) {
|
|
152
166
|
const name = require_objects.asName(require_objects.dictGet(encryptDict, entryKey)) ?? "Identity";
|
|
@@ -164,7 +178,7 @@ function cryptFilterKeyBytes(encryptDict, declaredBits) {
|
|
|
164
178
|
const streamFilterName = require_objects.asName(require_objects.dictGet(encryptDict, "StmF")) ?? "Identity";
|
|
165
179
|
const filters = require_objects.asDict(require_objects.dictGet(encryptDict, "CF"));
|
|
166
180
|
const filter = filters !== void 0 ? require_objects.asDict(require_objects.dictGet(filters, streamFilterName)) : void 0;
|
|
167
|
-
if ((filter !== void 0 ? require_objects.asName(require_objects.dictGet(filter, "CFM")) : void 0) === "AESV2") return
|
|
181
|
+
if ((filter !== void 0 ? require_objects.asName(require_objects.dictGet(filter, "CFM")) : void 0) === "AESV2") return 16;
|
|
168
182
|
const declared = filter !== void 0 ? require_objects.asNumber(require_objects.dictGet(filter, "Length")) : void 0;
|
|
169
183
|
if (declared === void 0) return Math.floor(declaredBits / BITS_PER_BYTE);
|
|
170
184
|
return declared >= DEFAULT_KEY_BITS ? Math.floor(declared / BITS_PER_BYTE) : declared;
|
|
@@ -189,8 +203,8 @@ function setUpHandler(encryptDict, fileId) {
|
|
|
189
203
|
if (revision < 2 || revision > 4) throw new require_diagnostics.PdfEncryptedError(`unsupported standard security handler revision /R ${String(revision)}`);
|
|
190
204
|
const streamMethod = version === 4 ? methodFromCryptFilterName(encryptDict, "StmF") : "rc4";
|
|
191
205
|
const stringMethod = version === 4 ? methodFromCryptFilterName(encryptDict, "StrF") : "rc4";
|
|
192
|
-
const keyBytes = version === 1 ?
|
|
193
|
-
if (keyBytes <
|
|
206
|
+
const keyBytes = version === 1 ? 5 : version === 2 ? Math.floor(declaredBits / BITS_PER_BYTE) : cryptFilterKeyBytes(encryptDict, declaredBits);
|
|
207
|
+
if (keyBytes < 5 || keyBytes > MAX_RC4_KEY_BYTES) throw new require_diagnostics.PdfEncryptedError(`the /Encrypt dictionary declares a ${String(keyBytes * BITS_PER_BYTE)}-bit file key, outside the 40-128 bit range /V ${String(version)} permits`);
|
|
194
208
|
const fileKey = computeLegacyFileKey(encryptDict, fileId, revision, keyBytes, encryptMetadata);
|
|
195
209
|
if (!legacyUserPasswordVerifies(encryptDict, fileId, revision, fileKey)) throw new require_diagnostics.PdfPasswordRequiredError();
|
|
196
210
|
return {
|
|
@@ -212,7 +226,7 @@ function objectKey(fileKey, num, gen, method) {
|
|
|
212
226
|
fileKey,
|
|
213
227
|
extra,
|
|
214
228
|
AES_OBJECT_KEY_SALT
|
|
215
|
-
] : [fileKey, extra])).subarray(0, Math.min(fileKey.length + OBJECT_KEY_EXTRA_BYTES,
|
|
229
|
+
] : [fileKey, extra])).subarray(0, Math.min(fileKey.length + OBJECT_KEY_EXTRA_BYTES, 16));
|
|
216
230
|
}
|
|
217
231
|
function decryptAes(key, data, sink) {
|
|
218
232
|
if (data.length <= 16) {
|
|
@@ -261,4 +275,20 @@ function createStandardDecryptor(encryptDict, fileId, sink) {
|
|
|
261
275
|
};
|
|
262
276
|
}
|
|
263
277
|
//#endregion
|
|
278
|
+
exports.AESV2_KEY_BYTES = AESV2_KEY_BYTES;
|
|
279
|
+
exports.AESV3_KEY_BYTES = AESV3_KEY_BYTES;
|
|
280
|
+
exports.AESV3_SALT_BYTES = AESV3_SALT_BYTES;
|
|
281
|
+
exports.AES_OBJECT_KEY_SALT = AES_OBJECT_KEY_SALT;
|
|
282
|
+
exports.LEGACY_KEY_ITERATIONS = LEGACY_KEY_ITERATIONS;
|
|
283
|
+
exports.MD5_DIGEST_BYTES = MD5_DIGEST_BYTES;
|
|
284
|
+
exports.PASSWORD_PADDING = PASSWORD_PADDING;
|
|
285
|
+
exports.RC4_40_KEY_BYTES = RC4_40_KEY_BYTES;
|
|
286
|
+
exports.RC4_OBFUSCATION_ROUNDS = RC4_OBFUSCATION_ROUNDS;
|
|
287
|
+
exports.ZERO_IV = ZERO_IV;
|
|
288
|
+
exports.computeLegacyFileKeyFromPaddedPassword = computeLegacyFileKeyFromPaddedPassword;
|
|
264
289
|
exports.createStandardDecryptor = createStandardDecryptor;
|
|
290
|
+
exports.hardenedHash = hardenedHash;
|
|
291
|
+
exports.legacyUserValueCore = legacyUserValueCore;
|
|
292
|
+
exports.objectKey = objectKey;
|
|
293
|
+
exports.padOrTruncatePassword = padOrTruncatePassword;
|
|
294
|
+
exports.permissionsBytes = permissionsBytes;
|
package/dist/encrypt.d.cts
CHANGED
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import { PdfDiagnosticSink } from "./diagnostics.cjs";
|
|
2
|
-
import { PdfDict } from "./objects.cjs";
|
|
2
|
+
import { n as PdfDict } from "./objects-B7HdMeWS.cjs";
|
|
3
3
|
//#region src/encrypt.d.ts
|
|
4
4
|
type CipherMethod = "identity" | "rc4" | "aes";
|
|
5
5
|
interface PdfDecryptor {
|
|
6
6
|
decryptString(bytes: Uint8Array<ArrayBuffer>, num: number, gen: number): Uint8Array<ArrayBuffer>;
|
|
7
7
|
decryptStream(bytes: Uint8Array<ArrayBuffer>, dict: PdfDict, num: number, gen: number): Uint8Array<ArrayBuffer>;
|
|
8
8
|
}
|
|
9
|
+
declare const PASSWORD_PADDING: Uint8Array<ArrayBuffer>;
|
|
10
|
+
declare const AES_OBJECT_KEY_SALT: Uint8Array<ArrayBuffer>;
|
|
11
|
+
declare const MD5_DIGEST_BYTES = 16;
|
|
12
|
+
declare const LEGACY_KEY_ITERATIONS = 50;
|
|
13
|
+
declare const RC4_OBFUSCATION_ROUNDS = 19;
|
|
14
|
+
declare const AESV3_KEY_BYTES = 32;
|
|
15
|
+
declare const AESV3_SALT_BYTES = 8;
|
|
16
|
+
declare const RC4_40_KEY_BYTES = 5;
|
|
17
|
+
declare const AESV2_KEY_BYTES = 16;
|
|
18
|
+
declare const ZERO_IV: Uint8Array<ArrayBuffer>;
|
|
19
|
+
declare function permissionsBytes(p: number): Uint8Array<ArrayBuffer>;
|
|
20
|
+
declare function padOrTruncatePassword(password: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>;
|
|
21
|
+
declare function computeLegacyFileKeyFromPaddedPassword(paddedPassword: Uint8Array<ArrayBuffer>, owner: Uint8Array<ArrayBuffer>, permissions: number, fileId: Uint8Array<ArrayBuffer>, revision: number, keyBytes: number, encryptMetadata: boolean): Uint8Array<ArrayBuffer>;
|
|
22
|
+
declare function legacyUserValueCore(fileKey: Uint8Array<ArrayBuffer>, fileId: Uint8Array<ArrayBuffer>, revision: number): Uint8Array<ArrayBuffer>;
|
|
23
|
+
declare function hardenedHash(password: Uint8Array<ArrayBuffer>, salt: Uint8Array<ArrayBuffer>, userData: Uint8Array<ArrayBuffer>, revision: number): Uint8Array<ArrayBuffer>;
|
|
24
|
+
declare function objectKey(fileKey: Uint8Array<ArrayBuffer>, num: number, gen: number, method: CipherMethod): Uint8Array<ArrayBuffer>;
|
|
9
25
|
declare function createStandardDecryptor(encryptDict: PdfDict, fileId: Uint8Array<ArrayBuffer>, sink: PdfDiagnosticSink): PdfDecryptor;
|
|
10
26
|
//#endregion
|
|
11
|
-
export { CipherMethod, PdfDecryptor, createStandardDecryptor };
|
|
27
|
+
export { AESV2_KEY_BYTES, AESV3_KEY_BYTES, AESV3_SALT_BYTES, AES_OBJECT_KEY_SALT, CipherMethod, LEGACY_KEY_ITERATIONS, MD5_DIGEST_BYTES, PASSWORD_PADDING, PdfDecryptor, RC4_40_KEY_BYTES, RC4_OBFUSCATION_ROUNDS, ZERO_IV, computeLegacyFileKeyFromPaddedPassword, createStandardDecryptor, hardenedHash, legacyUserValueCore, objectKey, padOrTruncatePassword, permissionsBytes };
|
package/dist/encrypt.d.ts
CHANGED
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import { PdfDiagnosticSink } from "./diagnostics.js";
|
|
2
|
-
import { PdfDict } from "./objects.js";
|
|
2
|
+
import { n as PdfDict } from "./objects-B7HdMeWS.js";
|
|
3
3
|
//#region src/encrypt.d.ts
|
|
4
4
|
type CipherMethod = "identity" | "rc4" | "aes";
|
|
5
5
|
interface PdfDecryptor {
|
|
6
6
|
decryptString(bytes: Uint8Array<ArrayBuffer>, num: number, gen: number): Uint8Array<ArrayBuffer>;
|
|
7
7
|
decryptStream(bytes: Uint8Array<ArrayBuffer>, dict: PdfDict, num: number, gen: number): Uint8Array<ArrayBuffer>;
|
|
8
8
|
}
|
|
9
|
+
declare const PASSWORD_PADDING: Uint8Array<ArrayBuffer>;
|
|
10
|
+
declare const AES_OBJECT_KEY_SALT: Uint8Array<ArrayBuffer>;
|
|
11
|
+
declare const MD5_DIGEST_BYTES = 16;
|
|
12
|
+
declare const LEGACY_KEY_ITERATIONS = 50;
|
|
13
|
+
declare const RC4_OBFUSCATION_ROUNDS = 19;
|
|
14
|
+
declare const AESV3_KEY_BYTES = 32;
|
|
15
|
+
declare const AESV3_SALT_BYTES = 8;
|
|
16
|
+
declare const RC4_40_KEY_BYTES = 5;
|
|
17
|
+
declare const AESV2_KEY_BYTES = 16;
|
|
18
|
+
declare const ZERO_IV: Uint8Array<ArrayBuffer>;
|
|
19
|
+
declare function permissionsBytes(p: number): Uint8Array<ArrayBuffer>;
|
|
20
|
+
declare function padOrTruncatePassword(password: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>;
|
|
21
|
+
declare function computeLegacyFileKeyFromPaddedPassword(paddedPassword: Uint8Array<ArrayBuffer>, owner: Uint8Array<ArrayBuffer>, permissions: number, fileId: Uint8Array<ArrayBuffer>, revision: number, keyBytes: number, encryptMetadata: boolean): Uint8Array<ArrayBuffer>;
|
|
22
|
+
declare function legacyUserValueCore(fileKey: Uint8Array<ArrayBuffer>, fileId: Uint8Array<ArrayBuffer>, revision: number): Uint8Array<ArrayBuffer>;
|
|
23
|
+
declare function hardenedHash(password: Uint8Array<ArrayBuffer>, salt: Uint8Array<ArrayBuffer>, userData: Uint8Array<ArrayBuffer>, revision: number): Uint8Array<ArrayBuffer>;
|
|
24
|
+
declare function objectKey(fileKey: Uint8Array<ArrayBuffer>, num: number, gen: number, method: CipherMethod): Uint8Array<ArrayBuffer>;
|
|
9
25
|
declare function createStandardDecryptor(encryptDict: PdfDict, fileId: Uint8Array<ArrayBuffer>, sink: PdfDiagnosticSink): PdfDecryptor;
|
|
10
26
|
//#endregion
|
|
11
|
-
export { CipherMethod, PdfDecryptor, createStandardDecryptor };
|
|
27
|
+
export { AESV2_KEY_BYTES, AESV3_KEY_BYTES, AESV3_SALT_BYTES, AES_OBJECT_KEY_SALT, CipherMethod, LEGACY_KEY_ITERATIONS, MD5_DIGEST_BYTES, PASSWORD_PADDING, PdfDecryptor, RC4_40_KEY_BYTES, RC4_OBFUSCATION_ROUNDS, ZERO_IV, computeLegacyFileKeyFromPaddedPassword, createStandardDecryptor, hardenedHash, legacyUserValueCore, objectKey, padOrTruncatePassword, permissionsBytes };
|
package/dist/encrypt.js
CHANGED
|
@@ -49,11 +49,12 @@ const AES_OBJECT_KEY_SALT = new Uint8Array([
|
|
|
49
49
|
const MD5_DIGEST_BYTES = 16;
|
|
50
50
|
const OBJECT_KEY_EXTRA_BYTES = 5;
|
|
51
51
|
const LEGACY_KEY_ITERATIONS = 50;
|
|
52
|
-
const
|
|
52
|
+
const RC4_OBFUSCATION_ROUNDS = 19;
|
|
53
53
|
const R6_MINIMUM_ROUNDS = 64;
|
|
54
54
|
const R6_ROUND_REPEATS = 64;
|
|
55
55
|
const R6_TERMINATION_MARGIN = 32;
|
|
56
56
|
const AESV3_KEY_BYTES = 32;
|
|
57
|
+
const AESV3_SALT_BYTES = 8;
|
|
57
58
|
const RC4_40_KEY_BYTES = 5;
|
|
58
59
|
const AESV2_KEY_BYTES = 16;
|
|
59
60
|
const DEFAULT_KEY_BITS = 40;
|
|
@@ -79,11 +80,16 @@ function permissionsBytes(p) {
|
|
|
79
80
|
unsigned >>> 24 & 255
|
|
80
81
|
]);
|
|
81
82
|
}
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
const
|
|
83
|
+
function padOrTruncatePassword(password) {
|
|
84
|
+
if (password.length >= PASSWORD_PADDING.length) return password.subarray(0, PASSWORD_PADDING.length);
|
|
85
|
+
const padded = new Uint8Array(PASSWORD_PADDING.length);
|
|
86
|
+
padded.set(password);
|
|
87
|
+
padded.set(PASSWORD_PADDING.subarray(0, PASSWORD_PADDING.length - password.length), password.length);
|
|
88
|
+
return padded;
|
|
89
|
+
}
|
|
90
|
+
function computeLegacyFileKeyFromPaddedPassword(paddedPassword, owner, permissions, fileId, revision, keyBytes, encryptMetadata) {
|
|
85
91
|
const parts = [
|
|
86
|
-
|
|
92
|
+
paddedPassword,
|
|
87
93
|
owner.subarray(0, PASSWORD_PADDING.length),
|
|
88
94
|
permissionsBytes(permissions),
|
|
89
95
|
fileId
|
|
@@ -95,18 +101,26 @@ function computeLegacyFileKey(encryptDict, fileId, revision, keyBytes, encryptMe
|
|
|
95
101
|
255
|
|
96
102
|
]));
|
|
97
103
|
let digest = md5(concatBytes(parts));
|
|
98
|
-
if (revision >= 3) for (let i = 0; i <
|
|
104
|
+
if (revision >= 3) for (let i = 0; i < 50; i++) digest = md5(digest.subarray(0, keyBytes));
|
|
99
105
|
return digest.subarray(0, keyBytes);
|
|
100
106
|
}
|
|
101
|
-
function
|
|
102
|
-
const
|
|
103
|
-
|
|
107
|
+
function computeLegacyFileKey(encryptDict, fileId, revision, keyBytes, encryptMetadata) {
|
|
108
|
+
const owner = requireStringBytes(encryptDict, "O");
|
|
109
|
+
const permissions = asNumber(dictGet(encryptDict, "P")) ?? 0;
|
|
110
|
+
return computeLegacyFileKeyFromPaddedPassword(PASSWORD_PADDING, owner, permissions, fileId, revision, keyBytes, encryptMetadata);
|
|
111
|
+
}
|
|
112
|
+
function legacyUserValueCore(fileKey, fileId, revision) {
|
|
113
|
+
if (revision === 2) return rc4(fileKey, PASSWORD_PADDING);
|
|
104
114
|
let value = rc4(fileKey, md5(concatBytes([PASSWORD_PADDING, fileId])));
|
|
105
|
-
for (let i = 1; i <=
|
|
115
|
+
for (let i = 1; i <= 19; i++) {
|
|
106
116
|
const roundKey = Uint8Array.from(fileKey, (byte) => byte ^ i);
|
|
107
117
|
value = rc4(roundKey, value);
|
|
108
118
|
}
|
|
109
|
-
return
|
|
119
|
+
return value;
|
|
120
|
+
}
|
|
121
|
+
function legacyUserPasswordVerifies(encryptDict, fileId, revision, fileKey) {
|
|
122
|
+
const storedUser = requireStringBytes(encryptDict, "U");
|
|
123
|
+
return bytesEqual(legacyUserValueCore(fileKey, fileId, revision), storedUser, revision === 2 ? PASSWORD_PADDING.length : 16);
|
|
110
124
|
}
|
|
111
125
|
function hardenedHash(password, salt, userData, revision) {
|
|
112
126
|
let k = sha256(concatBytes([
|
|
@@ -132,20 +146,20 @@ function hardenedHash(password, salt, userData, revision) {
|
|
|
132
146
|
k = selector === 0 ? sha256(e) : selector === 1 ? sha384(e) : sha512(e);
|
|
133
147
|
round++;
|
|
134
148
|
}
|
|
135
|
-
return k.subarray(0,
|
|
149
|
+
return k.subarray(0, 32);
|
|
136
150
|
}
|
|
137
151
|
function computeAesV3FileKey(encryptDict, revision) {
|
|
138
152
|
const storedUser = requireStringBytes(encryptDict, "U");
|
|
139
153
|
const expectedLength = 48;
|
|
140
154
|
if (storedUser.length < expectedLength) throw new PdfEncryptedError(`the /Encrypt dictionary's /U entry is ${String(storedUser.length)} bytes; revision ${String(revision)} requires ${String(expectedLength)}`);
|
|
141
155
|
const empty = /* @__PURE__ */ new Uint8Array(0);
|
|
142
|
-
const validationSalt = storedUser.subarray(
|
|
156
|
+
const validationSalt = storedUser.subarray(32, 40);
|
|
143
157
|
const keySalt = storedUser.subarray(40, expectedLength);
|
|
144
|
-
if (!bytesEqual(hardenedHash(empty, validationSalt, empty, revision), storedUser,
|
|
158
|
+
if (!bytesEqual(hardenedHash(empty, validationSalt, empty, revision), storedUser, 32)) throw new PdfPasswordRequiredError();
|
|
145
159
|
const intermediateKey = hardenedHash(empty, keySalt, empty, revision);
|
|
146
160
|
const wrappedKey = requireStringBytes(encryptDict, "UE");
|
|
147
|
-
if (wrappedKey.length <
|
|
148
|
-
return aesCbcDecrypt(intermediateKey, ZERO_IV, wrappedKey.subarray(0,
|
|
161
|
+
if (wrappedKey.length < 32) throw new PdfEncryptedError(`the /Encrypt dictionary's /UE entry is ${String(wrappedKey.length)} bytes; revision ${String(revision)} requires ${String(32)}`);
|
|
162
|
+
return aesCbcDecrypt(intermediateKey, ZERO_IV, wrappedKey.subarray(0, 32));
|
|
149
163
|
}
|
|
150
164
|
function methodFromCryptFilterName(encryptDict, entryKey) {
|
|
151
165
|
const name = asName(dictGet(encryptDict, entryKey)) ?? "Identity";
|
|
@@ -163,7 +177,7 @@ function cryptFilterKeyBytes(encryptDict, declaredBits) {
|
|
|
163
177
|
const streamFilterName = asName(dictGet(encryptDict, "StmF")) ?? "Identity";
|
|
164
178
|
const filters = asDict(dictGet(encryptDict, "CF"));
|
|
165
179
|
const filter = filters !== void 0 ? asDict(dictGet(filters, streamFilterName)) : void 0;
|
|
166
|
-
if ((filter !== void 0 ? asName(dictGet(filter, "CFM")) : void 0) === "AESV2") return
|
|
180
|
+
if ((filter !== void 0 ? asName(dictGet(filter, "CFM")) : void 0) === "AESV2") return 16;
|
|
167
181
|
const declared = filter !== void 0 ? asNumber(dictGet(filter, "Length")) : void 0;
|
|
168
182
|
if (declared === void 0) return Math.floor(declaredBits / BITS_PER_BYTE);
|
|
169
183
|
return declared >= DEFAULT_KEY_BITS ? Math.floor(declared / BITS_PER_BYTE) : declared;
|
|
@@ -188,8 +202,8 @@ function setUpHandler(encryptDict, fileId) {
|
|
|
188
202
|
if (revision < 2 || revision > 4) throw new PdfEncryptedError(`unsupported standard security handler revision /R ${String(revision)}`);
|
|
189
203
|
const streamMethod = version === 4 ? methodFromCryptFilterName(encryptDict, "StmF") : "rc4";
|
|
190
204
|
const stringMethod = version === 4 ? methodFromCryptFilterName(encryptDict, "StrF") : "rc4";
|
|
191
|
-
const keyBytes = version === 1 ?
|
|
192
|
-
if (keyBytes <
|
|
205
|
+
const keyBytes = version === 1 ? 5 : version === 2 ? Math.floor(declaredBits / BITS_PER_BYTE) : cryptFilterKeyBytes(encryptDict, declaredBits);
|
|
206
|
+
if (keyBytes < 5 || keyBytes > MAX_RC4_KEY_BYTES) throw new PdfEncryptedError(`the /Encrypt dictionary declares a ${String(keyBytes * BITS_PER_BYTE)}-bit file key, outside the 40-128 bit range /V ${String(version)} permits`);
|
|
193
207
|
const fileKey = computeLegacyFileKey(encryptDict, fileId, revision, keyBytes, encryptMetadata);
|
|
194
208
|
if (!legacyUserPasswordVerifies(encryptDict, fileId, revision, fileKey)) throw new PdfPasswordRequiredError();
|
|
195
209
|
return {
|
|
@@ -211,7 +225,7 @@ function objectKey(fileKey, num, gen, method) {
|
|
|
211
225
|
fileKey,
|
|
212
226
|
extra,
|
|
213
227
|
AES_OBJECT_KEY_SALT
|
|
214
|
-
] : [fileKey, extra])).subarray(0, Math.min(fileKey.length + OBJECT_KEY_EXTRA_BYTES,
|
|
228
|
+
] : [fileKey, extra])).subarray(0, Math.min(fileKey.length + OBJECT_KEY_EXTRA_BYTES, 16));
|
|
215
229
|
}
|
|
216
230
|
function decryptAes(key, data, sink) {
|
|
217
231
|
if (data.length <= 16) {
|
|
@@ -260,4 +274,4 @@ function createStandardDecryptor(encryptDict, fileId, sink) {
|
|
|
260
274
|
};
|
|
261
275
|
}
|
|
262
276
|
//#endregion
|
|
263
|
-
export { createStandardDecryptor };
|
|
277
|
+
export { AESV2_KEY_BYTES, AESV3_KEY_BYTES, AESV3_SALT_BYTES, AES_OBJECT_KEY_SALT, LEGACY_KEY_ITERATIONS, MD5_DIGEST_BYTES, PASSWORD_PADDING, RC4_40_KEY_BYTES, RC4_OBFUSCATION_ROUNDS, ZERO_IV, computeLegacyFileKeyFromPaddedPassword, createStandardDecryptor, hardenedHash, legacyUserValueCore, objectKey, padOrTruncatePassword, permissionsBytes };
|
package/dist/filters.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PdfDiagnosticSink } from "./diagnostics.cjs";
|
|
2
|
-
import { PdfDict, PdfObject } from "./objects.cjs";
|
|
2
|
+
import { n as PdfDict, r as PdfObject } from "./objects-B7HdMeWS.cjs";
|
|
3
3
|
//#region src/filters.d.ts
|
|
4
4
|
interface DecodedStream {
|
|
5
5
|
readonly bytes: Uint8Array<ArrayBuffer>;
|
package/dist/filters.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PdfDiagnosticSink } from "./diagnostics.js";
|
|
2
|
-
import { PdfDict, PdfObject } from "./objects.js";
|
|
2
|
+
import { n as PdfDict, r as PdfObject } from "./objects-B7HdMeWS.js";
|
|
3
3
|
//#region src/filters.d.ts
|
|
4
4
|
interface DecodedStream {
|
|
5
5
|
readonly bytes: Uint8Array<ArrayBuffer>;
|
package/dist/font-read.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PdfDiagnosticSink } from "./diagnostics.cjs";
|
|
2
|
-
import { PdfDict } from "./objects.cjs";
|
|
2
|
+
import { n as PdfDict } from "./objects-B7HdMeWS.cjs";
|
|
3
3
|
import { FontMetricsPort, PdfObjectResolver } from "./interpret.cjs";
|
|
4
4
|
//#region src/font-read.d.ts
|
|
5
5
|
interface PdfFont {
|
package/dist/font-read.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PdfDiagnosticSink } from "./diagnostics.js";
|
|
2
|
-
import { PdfDict } from "./objects.js";
|
|
2
|
+
import { n as PdfDict } from "./objects-B7HdMeWS.js";
|
|
3
3
|
import { FontMetricsPort, PdfObjectResolver } from "./interpret.js";
|
|
4
4
|
//#region src/font-read.d.ts
|
|
5
5
|
interface PdfFont {
|
package/dist/form.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PdfDiagnosticSink } from "./diagnostics.cjs";
|
|
2
|
-
import { PdfDict } from "./objects.cjs";
|
|
2
|
+
import { n as PdfDict } from "./objects-B7HdMeWS.cjs";
|
|
3
3
|
import { PdfObjectResolver } from "./interpret.cjs";
|
|
4
4
|
import { LayoutFormField } from "./layout.cjs";
|
|
5
5
|
import { PageIndexLookup } from "./navigation.cjs";
|
package/dist/form.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PdfDiagnosticSink } from "./diagnostics.js";
|
|
2
|
-
import { PdfDict } from "./objects.js";
|
|
2
|
+
import { n as PdfDict } from "./objects-B7HdMeWS.js";
|
|
3
3
|
import { PdfObjectResolver } from "./interpret.js";
|
|
4
4
|
import { LayoutFormField } from "./layout.js";
|
|
5
5
|
import { PageIndexLookup } from "./navigation.js";
|
package/dist/images-read.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PdfDiagnosticSink } from "./diagnostics.cjs";
|
|
2
|
-
import { PdfDict } from "./objects.cjs";
|
|
2
|
+
import { n as PdfDict } from "./objects-B7HdMeWS.cjs";
|
|
3
3
|
import { PdfObjectResolver } from "./interpret.cjs";
|
|
4
4
|
//#region src/images-read.d.ts
|
|
5
5
|
interface ExtractedPdfImage {
|
package/dist/images-read.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PdfDiagnosticSink } from "./diagnostics.js";
|
|
2
|
-
import { PdfDict } from "./objects.js";
|
|
2
|
+
import { n as PdfDict } from "./objects-B7HdMeWS.js";
|
|
3
3
|
import { PdfObjectResolver } from "./interpret.js";
|
|
4
4
|
//#region src/images-read.d.ts
|
|
5
5
|
interface ExtractedPdfImage {
|
package/dist/index.cjs
CHANGED
|
@@ -11,6 +11,7 @@ const require_image_jpeg2000_errors = require("./image/jpeg2000-errors.cjs");
|
|
|
11
11
|
const require_image_jp2_boxes = require("./image/jp2-boxes.cjs");
|
|
12
12
|
const require_image_jpeg2000 = require("./image/jpeg2000.cjs");
|
|
13
13
|
const require_read = require("./read.cjs");
|
|
14
|
+
const require_encrypt_write = require("./encrypt-write.cjs");
|
|
14
15
|
const require_font_registry = require("./font-registry.cjs");
|
|
15
16
|
const require_math_stretch = require("./math-stretch.cjs");
|
|
16
17
|
const require_math_font = require("./math-font.cjs");
|
|
@@ -52,6 +53,7 @@ exports.LayoutTextSchema = require_layout.LayoutTextSchema;
|
|
|
52
53
|
exports.NOOP_DIAGNOSTIC_SINK = require_diagnostics.NOOP_DIAGNOSTIC_SINK;
|
|
53
54
|
exports.PdfBytesSchema = require_codec.PdfBytesSchema;
|
|
54
55
|
exports.PdfEncryptedError = require_diagnostics.PdfEncryptedError;
|
|
56
|
+
exports.PdfEncryptionError = require_encrypt_write.PdfEncryptionError;
|
|
55
57
|
exports.PdfParseError = require_diagnostics.PdfParseError;
|
|
56
58
|
exports.PdfPasswordRequiredError = require_diagnostics.PdfPasswordRequiredError;
|
|
57
59
|
exports.STANDARD_METRICS = require_afm_widths.STANDARD_METRICS;
|