pdf-parser.js 4.8.5 → 4.8.6

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.
@@ -52,112 +52,175 @@ function expandKey(key) {
52
52
  const nk = key.length / 4;
53
53
  const rounds = nk + 6;
54
54
  const words = new Uint32Array(WORDS_PER_BLOCK * (rounds + 1));
55
- for (let i = 0; i < nk; i++) words[i] = (key[4 * i] << 24 | key[4 * i + 1] << 16 | key[4 * i + 2] << 8 | key[4 * i + 3]) >>> 0;
55
+ words.set(Array.from({ length: nk }, (_unused, i) => readWord(key, 4 * i)));
56
56
  let rcon = 1;
57
- for (let i = nk; i < words.length; i++) {
57
+ words.forEach((_word, i) => {
58
+ if (i < nk) return;
58
59
  let temp = words[i - 1];
59
60
  if (i % nk === 0) {
60
61
  temp = (subWord(rotWord(temp)) ^ rcon << 24) >>> 0;
61
62
  rcon = xtime(rcon);
62
63
  } else if (nk > 6 && i % nk === 4) temp = subWord(temp);
63
64
  words[i] = (words[i - nk] ^ temp) >>> 0;
64
- }
65
+ });
65
66
  return {
66
67
  words,
67
68
  rounds
68
69
  };
69
70
  }
70
- function addRoundKey(state, words, round) {
71
- for (let c = 0; c < WORDS_PER_BLOCK; c++) {
72
- const word = words[round * WORDS_PER_BLOCK + c];
73
- for (let r = 0; r < WORDS_PER_BLOCK; r++) state[4 * c + r] = state[4 * c + r] ^ word >>> 24 - r * 8 & 255;
74
- }
71
+ function packWord(row0, row1, row2, row3) {
72
+ return (row0 << 24 | row1 << 16 | row2 << 8 | row3) >>> 0;
73
+ }
74
+ function rotateRight8(word) {
75
+ return (word >>> 8 | word << 24) >>> 0;
75
76
  }
76
- function substituteBytes(state, table) {
77
- for (let i = 0; i < 16; i++) state[i] = table[state[i]];
78
- }
79
- function shiftRows(state, direction) {
80
- const source = Uint8Array.from(state);
81
- for (let r = 1; r < WORDS_PER_BLOCK; r++) for (let c = 0; c < WORDS_PER_BLOCK; c++) state[r + 4 * c] = source[r + 4 * (((c + direction * r) % WORDS_PER_BLOCK + WORDS_PER_BLOCK) % WORDS_PER_BLOCK)];
82
- }
83
- function mixColumns(state, coefficients) {
84
- const [k0, k1, k2, k3] = coefficients;
85
- for (let c = 0; c < WORDS_PER_BLOCK; c++) {
86
- const a0 = state[4 * c];
87
- const a1 = state[4 * c + 1];
88
- const a2 = state[4 * c + 2];
89
- const a3 = state[4 * c + 3];
90
- state[4 * c] = gmul(a0, k0) ^ gmul(a1, k1) ^ gmul(a2, k2) ^ gmul(a3, k3);
91
- state[4 * c + 1] = gmul(a0, k3) ^ gmul(a1, k0) ^ gmul(a2, k1) ^ gmul(a3, k2);
92
- state[4 * c + 2] = gmul(a0, k2) ^ gmul(a1, k3) ^ gmul(a2, k0) ^ gmul(a3, k1);
93
- state[4 * c + 3] = gmul(a0, k1) ^ gmul(a1, k2) ^ gmul(a2, k3) ^ gmul(a3, k0);
77
+ const { TE0, TE1, TE2, TE3, TD0, TD1, TD2, TD3 } = (() => {
78
+ const te0 = /* @__PURE__ */ new Uint32Array(256);
79
+ const te1 = /* @__PURE__ */ new Uint32Array(256);
80
+ const te2 = /* @__PURE__ */ new Uint32Array(256);
81
+ const te3 = /* @__PURE__ */ new Uint32Array(256);
82
+ const td0 = /* @__PURE__ */ new Uint32Array(256);
83
+ const td1 = /* @__PURE__ */ new Uint32Array(256);
84
+ const td2 = /* @__PURE__ */ new Uint32Array(256);
85
+ const td3 = /* @__PURE__ */ new Uint32Array(256);
86
+ for (let x = 0; x < 256; x++) {
87
+ const s = SBOX[x];
88
+ te0[x] = packWord(gmul(s, 2), s, s, gmul(s, 3));
89
+ te1[x] = rotateRight8(te0[x]);
90
+ te2[x] = rotateRight8(te1[x]);
91
+ te3[x] = rotateRight8(te2[x]);
92
+ const i = INV_SBOX[x];
93
+ td0[x] = packWord(gmul(i, 14), gmul(i, 9), gmul(i, 13), gmul(i, 11));
94
+ td1[x] = rotateRight8(td0[x]);
95
+ td2[x] = rotateRight8(td1[x]);
96
+ td3[x] = rotateRight8(td2[x]);
94
97
  }
98
+ return {
99
+ TE0: te0,
100
+ TE1: te1,
101
+ TE2: te2,
102
+ TE3: te3,
103
+ TD0: td0,
104
+ TD1: td1,
105
+ TD2: td2,
106
+ TD3: td3
107
+ };
108
+ })();
109
+ function inverseKeyWords(expanded) {
110
+ const { words, rounds } = expanded;
111
+ return Uint32Array.from(words, (_word, index) => {
112
+ const round = Math.floor(index / WORDS_PER_BLOCK);
113
+ const column = index % WORDS_PER_BLOCK;
114
+ const word = words[(rounds - round) * WORDS_PER_BLOCK + column];
115
+ return round === 0 || round === rounds ? word : TD0[SBOX[word >>> 24]] ^ TD1[SBOX[word >>> 16 & 255]] ^ TD2[SBOX[word >>> 8 & 255]] ^ TD3[SBOX[word & 255]];
116
+ });
95
117
  }
96
- const FORWARD_MIX = [
97
- 2,
98
- 3,
99
- 1,
100
- 1
101
- ];
102
- const INVERSE_MIX = [
103
- 14,
104
- 11,
105
- 13,
106
- 9
107
- ];
108
- function encryptBlock(state, key) {
109
- addRoundKey(state, key.words, 0);
118
+ function readWord(bytes, offset) {
119
+ return packWord(bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3]);
120
+ }
121
+ function writeWord(bytes, offset, word) {
122
+ bytes[offset] = word >>> 24;
123
+ bytes[offset + 1] = word >>> 16 & 255;
124
+ bytes[offset + 2] = word >>> 8 & 255;
125
+ bytes[offset + 3] = word & 255;
126
+ }
127
+ function encryptWords(key, a0, a1, a2, a3, out) {
128
+ const rk = key.words;
129
+ let s0 = a0 ^ rk[0];
130
+ let s1 = a1 ^ rk[1];
131
+ let s2 = a2 ^ rk[2];
132
+ let s3 = a3 ^ rk[3];
110
133
  for (let round = 1; round < key.rounds; round++) {
111
- substituteBytes(state, SBOX);
112
- shiftRows(state, 1);
113
- mixColumns(state, FORWARD_MIX);
114
- addRoundKey(state, key.words, round);
134
+ const at = round * WORDS_PER_BLOCK;
135
+ const t0 = TE0[s0 >>> 24] ^ TE1[s1 >>> 16 & 255] ^ TE2[s2 >>> 8 & 255] ^ TE3[s3 & 255] ^ rk[at];
136
+ const t1 = TE0[s1 >>> 24] ^ TE1[s2 >>> 16 & 255] ^ TE2[s3 >>> 8 & 255] ^ TE3[s0 & 255] ^ rk[at + 1];
137
+ const t2 = TE0[s2 >>> 24] ^ TE1[s3 >>> 16 & 255] ^ TE2[s0 >>> 8 & 255] ^ TE3[s1 & 255] ^ rk[at + 2];
138
+ const t3 = TE0[s3 >>> 24] ^ TE1[s0 >>> 16 & 255] ^ TE2[s1 >>> 8 & 255] ^ TE3[s2 & 255] ^ rk[at + 3];
139
+ s0 = t0;
140
+ s1 = t1;
141
+ s2 = t2;
142
+ s3 = t3;
115
143
  }
116
- substituteBytes(state, SBOX);
117
- shiftRows(state, 1);
118
- addRoundKey(state, key.words, key.rounds);
119
- }
120
- function decryptBlock(state, key) {
121
- addRoundKey(state, key.words, key.rounds);
122
- for (let round = key.rounds - 1; round >= 1; round--) {
123
- shiftRows(state, -1);
124
- substituteBytes(state, INV_SBOX);
125
- addRoundKey(state, key.words, round);
126
- mixColumns(state, INVERSE_MIX);
144
+ const at = key.rounds * WORDS_PER_BLOCK;
145
+ out[0] = packWord(SBOX[s0 >>> 24], SBOX[s1 >>> 16 & 255], SBOX[s2 >>> 8 & 255], SBOX[s3 & 255]) ^ rk[at];
146
+ out[1] = packWord(SBOX[s1 >>> 24], SBOX[s2 >>> 16 & 255], SBOX[s3 >>> 8 & 255], SBOX[s0 & 255]) ^ rk[at + 1];
147
+ out[2] = packWord(SBOX[s2 >>> 24], SBOX[s3 >>> 16 & 255], SBOX[s0 >>> 8 & 255], SBOX[s1 & 255]) ^ rk[at + 2];
148
+ out[3] = packWord(SBOX[s3 >>> 24], SBOX[s0 >>> 16 & 255], SBOX[s1 >>> 8 & 255], SBOX[s2 & 255]) ^ rk[at + 3];
149
+ }
150
+ function decryptWords(rk, rounds, a0, a1, a2, a3, out) {
151
+ let s0 = a0 ^ rk[0];
152
+ let s1 = a1 ^ rk[1];
153
+ let s2 = a2 ^ rk[2];
154
+ let s3 = a3 ^ rk[3];
155
+ for (let round = 1; round < rounds; round++) {
156
+ const at = round * WORDS_PER_BLOCK;
157
+ const t0 = TD0[s0 >>> 24] ^ TD1[s3 >>> 16 & 255] ^ TD2[s2 >>> 8 & 255] ^ TD3[s1 & 255] ^ rk[at];
158
+ const t1 = TD0[s1 >>> 24] ^ TD1[s0 >>> 16 & 255] ^ TD2[s3 >>> 8 & 255] ^ TD3[s2 & 255] ^ rk[at + 1];
159
+ const t2 = TD0[s2 >>> 24] ^ TD1[s1 >>> 16 & 255] ^ TD2[s0 >>> 8 & 255] ^ TD3[s3 & 255] ^ rk[at + 2];
160
+ const t3 = TD0[s3 >>> 24] ^ TD1[s2 >>> 16 & 255] ^ TD2[s1 >>> 8 & 255] ^ TD3[s0 & 255] ^ rk[at + 3];
161
+ s0 = t0;
162
+ s1 = t1;
163
+ s2 = t2;
164
+ s3 = t3;
127
165
  }
128
- shiftRows(state, -1);
129
- substituteBytes(state, INV_SBOX);
130
- addRoundKey(state, key.words, 0);
166
+ const at = rounds * WORDS_PER_BLOCK;
167
+ out[0] = packWord(INV_SBOX[s0 >>> 24], INV_SBOX[s3 >>> 16 & 255], INV_SBOX[s2 >>> 8 & 255], INV_SBOX[s1 & 255]) ^ rk[at];
168
+ out[1] = packWord(INV_SBOX[s1 >>> 24], INV_SBOX[s0 >>> 16 & 255], INV_SBOX[s3 >>> 8 & 255], INV_SBOX[s2 & 255]) ^ rk[at + 1];
169
+ out[2] = packWord(INV_SBOX[s2 >>> 24], INV_SBOX[s1 >>> 16 & 255], INV_SBOX[s0 >>> 8 & 255], INV_SBOX[s3 & 255]) ^ rk[at + 2];
170
+ out[3] = packWord(INV_SBOX[s3 >>> 24], INV_SBOX[s2 >>> 16 & 255], INV_SBOX[s1 >>> 8 & 255], INV_SBOX[s0 & 255]) ^ rk[at + 3];
131
171
  }
132
172
  function wholeBlockCount(byteLength) {
133
173
  return Math.floor(byteLength / 16);
134
174
  }
135
175
  function aesCbcDecrypt(key, iv, data) {
136
176
  const expanded = expandKey(key);
177
+ const inverseKey = inverseKeyWords(expanded);
137
178
  const blocks = wholeBlockCount(data.length);
138
179
  const out = new Uint8Array(blocks * 16);
139
- const chain = Uint8Array.from(iv.subarray(0, 16));
140
- for (let b = 0; b < blocks; b++) {
141
- const cipherBlock = data.subarray(b * 16, (b + 1) * 16);
142
- const state = Uint8Array.from(cipherBlock);
143
- decryptBlock(state, expanded);
144
- for (let i = 0; i < 16; i++) out[b * 16 + i] = state[i] ^ chain[i];
145
- chain.set(cipherBlock);
146
- }
180
+ const plain = new Uint32Array(WORDS_PER_BLOCK);
181
+ let c0 = readWord(iv, 0);
182
+ let c1 = readWord(iv, 4);
183
+ let c2 = readWord(iv, 8);
184
+ let c3 = readWord(iv, 12);
185
+ Array.from({ length: blocks }).forEach((_unused, b) => {
186
+ const at = b * 16;
187
+ const x0 = readWord(data, at);
188
+ const x1 = readWord(data, at + 4);
189
+ const x2 = readWord(data, at + 8);
190
+ const x3 = readWord(data, at + 12);
191
+ decryptWords(inverseKey, expanded.rounds, x0, x1, x2, x3, plain);
192
+ writeWord(out, at, plain[0] ^ c0);
193
+ writeWord(out, at + 4, plain[1] ^ c1);
194
+ writeWord(out, at + 8, plain[2] ^ c2);
195
+ writeWord(out, at + 12, plain[3] ^ c3);
196
+ c0 = x0;
197
+ c1 = x1;
198
+ c2 = x2;
199
+ c3 = x3;
200
+ });
147
201
  return out;
148
202
  }
149
203
  function aesCbcEncrypt(key, iv, data) {
150
204
  const expanded = expandKey(key);
151
205
  const blocks = wholeBlockCount(data.length);
152
206
  const out = new Uint8Array(blocks * 16);
153
- const chain = Uint8Array.from(iv.subarray(0, 16));
154
- for (let b = 0; b < blocks; b++) {
155
- const state = /* @__PURE__ */ new Uint8Array(16);
156
- for (let i = 0; i < 16; i++) state[i] = data[b * 16 + i] ^ chain[i];
157
- encryptBlock(state, expanded);
158
- out.set(state, b * 16);
159
- chain.set(state);
160
- }
207
+ const cipher = new Uint32Array(WORDS_PER_BLOCK);
208
+ let c0 = readWord(iv, 0);
209
+ let c1 = readWord(iv, 4);
210
+ let c2 = readWord(iv, 8);
211
+ let c3 = readWord(iv, 12);
212
+ Array.from({ length: blocks }).forEach((_unused, b) => {
213
+ const at = b * 16;
214
+ encryptWords(expanded, readWord(data, at) ^ c0, readWord(data, at + 4) ^ c1, readWord(data, at + 8) ^ c2, readWord(data, at + 12) ^ c3, cipher);
215
+ c0 = cipher[0];
216
+ c1 = cipher[1];
217
+ c2 = cipher[2];
218
+ c3 = cipher[3];
219
+ writeWord(out, at, c0);
220
+ writeWord(out, at + 4, c1);
221
+ writeWord(out, at + 8, c2);
222
+ writeWord(out, at + 12, c3);
223
+ });
161
224
  return out;
162
225
  }
163
226
  //#endregion
@@ -51,112 +51,175 @@ function expandKey(key) {
51
51
  const nk = key.length / 4;
52
52
  const rounds = nk + 6;
53
53
  const words = new Uint32Array(WORDS_PER_BLOCK * (rounds + 1));
54
- for (let i = 0; i < nk; i++) words[i] = (key[4 * i] << 24 | key[4 * i + 1] << 16 | key[4 * i + 2] << 8 | key[4 * i + 3]) >>> 0;
54
+ words.set(Array.from({ length: nk }, (_unused, i) => readWord(key, 4 * i)));
55
55
  let rcon = 1;
56
- for (let i = nk; i < words.length; i++) {
56
+ words.forEach((_word, i) => {
57
+ if (i < nk) return;
57
58
  let temp = words[i - 1];
58
59
  if (i % nk === 0) {
59
60
  temp = (subWord(rotWord(temp)) ^ rcon << 24) >>> 0;
60
61
  rcon = xtime(rcon);
61
62
  } else if (nk > 6 && i % nk === 4) temp = subWord(temp);
62
63
  words[i] = (words[i - nk] ^ temp) >>> 0;
63
- }
64
+ });
64
65
  return {
65
66
  words,
66
67
  rounds
67
68
  };
68
69
  }
69
- function addRoundKey(state, words, round) {
70
- for (let c = 0; c < WORDS_PER_BLOCK; c++) {
71
- const word = words[round * WORDS_PER_BLOCK + c];
72
- for (let r = 0; r < WORDS_PER_BLOCK; r++) state[4 * c + r] = state[4 * c + r] ^ word >>> 24 - r * 8 & 255;
73
- }
70
+ function packWord(row0, row1, row2, row3) {
71
+ return (row0 << 24 | row1 << 16 | row2 << 8 | row3) >>> 0;
72
+ }
73
+ function rotateRight8(word) {
74
+ return (word >>> 8 | word << 24) >>> 0;
74
75
  }
75
- function substituteBytes(state, table) {
76
- for (let i = 0; i < 16; i++) state[i] = table[state[i]];
77
- }
78
- function shiftRows(state, direction) {
79
- const source = Uint8Array.from(state);
80
- for (let r = 1; r < WORDS_PER_BLOCK; r++) for (let c = 0; c < WORDS_PER_BLOCK; c++) state[r + 4 * c] = source[r + 4 * (((c + direction * r) % WORDS_PER_BLOCK + WORDS_PER_BLOCK) % WORDS_PER_BLOCK)];
81
- }
82
- function mixColumns(state, coefficients) {
83
- const [k0, k1, k2, k3] = coefficients;
84
- for (let c = 0; c < WORDS_PER_BLOCK; c++) {
85
- const a0 = state[4 * c];
86
- const a1 = state[4 * c + 1];
87
- const a2 = state[4 * c + 2];
88
- const a3 = state[4 * c + 3];
89
- state[4 * c] = gmul(a0, k0) ^ gmul(a1, k1) ^ gmul(a2, k2) ^ gmul(a3, k3);
90
- state[4 * c + 1] = gmul(a0, k3) ^ gmul(a1, k0) ^ gmul(a2, k1) ^ gmul(a3, k2);
91
- state[4 * c + 2] = gmul(a0, k2) ^ gmul(a1, k3) ^ gmul(a2, k0) ^ gmul(a3, k1);
92
- state[4 * c + 3] = gmul(a0, k1) ^ gmul(a1, k2) ^ gmul(a2, k3) ^ gmul(a3, k0);
76
+ const { TE0, TE1, TE2, TE3, TD0, TD1, TD2, TD3 } = (() => {
77
+ const te0 = /* @__PURE__ */ new Uint32Array(256);
78
+ const te1 = /* @__PURE__ */ new Uint32Array(256);
79
+ const te2 = /* @__PURE__ */ new Uint32Array(256);
80
+ const te3 = /* @__PURE__ */ new Uint32Array(256);
81
+ const td0 = /* @__PURE__ */ new Uint32Array(256);
82
+ const td1 = /* @__PURE__ */ new Uint32Array(256);
83
+ const td2 = /* @__PURE__ */ new Uint32Array(256);
84
+ const td3 = /* @__PURE__ */ new Uint32Array(256);
85
+ for (let x = 0; x < 256; x++) {
86
+ const s = SBOX[x];
87
+ te0[x] = packWord(gmul(s, 2), s, s, gmul(s, 3));
88
+ te1[x] = rotateRight8(te0[x]);
89
+ te2[x] = rotateRight8(te1[x]);
90
+ te3[x] = rotateRight8(te2[x]);
91
+ const i = INV_SBOX[x];
92
+ td0[x] = packWord(gmul(i, 14), gmul(i, 9), gmul(i, 13), gmul(i, 11));
93
+ td1[x] = rotateRight8(td0[x]);
94
+ td2[x] = rotateRight8(td1[x]);
95
+ td3[x] = rotateRight8(td2[x]);
93
96
  }
97
+ return {
98
+ TE0: te0,
99
+ TE1: te1,
100
+ TE2: te2,
101
+ TE3: te3,
102
+ TD0: td0,
103
+ TD1: td1,
104
+ TD2: td2,
105
+ TD3: td3
106
+ };
107
+ })();
108
+ function inverseKeyWords(expanded) {
109
+ const { words, rounds } = expanded;
110
+ return Uint32Array.from(words, (_word, index) => {
111
+ const round = Math.floor(index / WORDS_PER_BLOCK);
112
+ const column = index % WORDS_PER_BLOCK;
113
+ const word = words[(rounds - round) * WORDS_PER_BLOCK + column];
114
+ return round === 0 || round === rounds ? word : TD0[SBOX[word >>> 24]] ^ TD1[SBOX[word >>> 16 & 255]] ^ TD2[SBOX[word >>> 8 & 255]] ^ TD3[SBOX[word & 255]];
115
+ });
94
116
  }
95
- const FORWARD_MIX = [
96
- 2,
97
- 3,
98
- 1,
99
- 1
100
- ];
101
- const INVERSE_MIX = [
102
- 14,
103
- 11,
104
- 13,
105
- 9
106
- ];
107
- function encryptBlock(state, key) {
108
- addRoundKey(state, key.words, 0);
117
+ function readWord(bytes, offset) {
118
+ return packWord(bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3]);
119
+ }
120
+ function writeWord(bytes, offset, word) {
121
+ bytes[offset] = word >>> 24;
122
+ bytes[offset + 1] = word >>> 16 & 255;
123
+ bytes[offset + 2] = word >>> 8 & 255;
124
+ bytes[offset + 3] = word & 255;
125
+ }
126
+ function encryptWords(key, a0, a1, a2, a3, out) {
127
+ const rk = key.words;
128
+ let s0 = a0 ^ rk[0];
129
+ let s1 = a1 ^ rk[1];
130
+ let s2 = a2 ^ rk[2];
131
+ let s3 = a3 ^ rk[3];
109
132
  for (let round = 1; round < key.rounds; round++) {
110
- substituteBytes(state, SBOX);
111
- shiftRows(state, 1);
112
- mixColumns(state, FORWARD_MIX);
113
- addRoundKey(state, key.words, round);
133
+ const at = round * WORDS_PER_BLOCK;
134
+ const t0 = TE0[s0 >>> 24] ^ TE1[s1 >>> 16 & 255] ^ TE2[s2 >>> 8 & 255] ^ TE3[s3 & 255] ^ rk[at];
135
+ const t1 = TE0[s1 >>> 24] ^ TE1[s2 >>> 16 & 255] ^ TE2[s3 >>> 8 & 255] ^ TE3[s0 & 255] ^ rk[at + 1];
136
+ const t2 = TE0[s2 >>> 24] ^ TE1[s3 >>> 16 & 255] ^ TE2[s0 >>> 8 & 255] ^ TE3[s1 & 255] ^ rk[at + 2];
137
+ const t3 = TE0[s3 >>> 24] ^ TE1[s0 >>> 16 & 255] ^ TE2[s1 >>> 8 & 255] ^ TE3[s2 & 255] ^ rk[at + 3];
138
+ s0 = t0;
139
+ s1 = t1;
140
+ s2 = t2;
141
+ s3 = t3;
114
142
  }
115
- substituteBytes(state, SBOX);
116
- shiftRows(state, 1);
117
- addRoundKey(state, key.words, key.rounds);
118
- }
119
- function decryptBlock(state, key) {
120
- addRoundKey(state, key.words, key.rounds);
121
- for (let round = key.rounds - 1; round >= 1; round--) {
122
- shiftRows(state, -1);
123
- substituteBytes(state, INV_SBOX);
124
- addRoundKey(state, key.words, round);
125
- mixColumns(state, INVERSE_MIX);
143
+ const at = key.rounds * WORDS_PER_BLOCK;
144
+ out[0] = packWord(SBOX[s0 >>> 24], SBOX[s1 >>> 16 & 255], SBOX[s2 >>> 8 & 255], SBOX[s3 & 255]) ^ rk[at];
145
+ out[1] = packWord(SBOX[s1 >>> 24], SBOX[s2 >>> 16 & 255], SBOX[s3 >>> 8 & 255], SBOX[s0 & 255]) ^ rk[at + 1];
146
+ out[2] = packWord(SBOX[s2 >>> 24], SBOX[s3 >>> 16 & 255], SBOX[s0 >>> 8 & 255], SBOX[s1 & 255]) ^ rk[at + 2];
147
+ out[3] = packWord(SBOX[s3 >>> 24], SBOX[s0 >>> 16 & 255], SBOX[s1 >>> 8 & 255], SBOX[s2 & 255]) ^ rk[at + 3];
148
+ }
149
+ function decryptWords(rk, rounds, a0, a1, a2, a3, out) {
150
+ let s0 = a0 ^ rk[0];
151
+ let s1 = a1 ^ rk[1];
152
+ let s2 = a2 ^ rk[2];
153
+ let s3 = a3 ^ rk[3];
154
+ for (let round = 1; round < rounds; round++) {
155
+ const at = round * WORDS_PER_BLOCK;
156
+ const t0 = TD0[s0 >>> 24] ^ TD1[s3 >>> 16 & 255] ^ TD2[s2 >>> 8 & 255] ^ TD3[s1 & 255] ^ rk[at];
157
+ const t1 = TD0[s1 >>> 24] ^ TD1[s0 >>> 16 & 255] ^ TD2[s3 >>> 8 & 255] ^ TD3[s2 & 255] ^ rk[at + 1];
158
+ const t2 = TD0[s2 >>> 24] ^ TD1[s1 >>> 16 & 255] ^ TD2[s0 >>> 8 & 255] ^ TD3[s3 & 255] ^ rk[at + 2];
159
+ const t3 = TD0[s3 >>> 24] ^ TD1[s2 >>> 16 & 255] ^ TD2[s1 >>> 8 & 255] ^ TD3[s0 & 255] ^ rk[at + 3];
160
+ s0 = t0;
161
+ s1 = t1;
162
+ s2 = t2;
163
+ s3 = t3;
126
164
  }
127
- shiftRows(state, -1);
128
- substituteBytes(state, INV_SBOX);
129
- addRoundKey(state, key.words, 0);
165
+ const at = rounds * WORDS_PER_BLOCK;
166
+ out[0] = packWord(INV_SBOX[s0 >>> 24], INV_SBOX[s3 >>> 16 & 255], INV_SBOX[s2 >>> 8 & 255], INV_SBOX[s1 & 255]) ^ rk[at];
167
+ out[1] = packWord(INV_SBOX[s1 >>> 24], INV_SBOX[s0 >>> 16 & 255], INV_SBOX[s3 >>> 8 & 255], INV_SBOX[s2 & 255]) ^ rk[at + 1];
168
+ out[2] = packWord(INV_SBOX[s2 >>> 24], INV_SBOX[s1 >>> 16 & 255], INV_SBOX[s0 >>> 8 & 255], INV_SBOX[s3 & 255]) ^ rk[at + 2];
169
+ out[3] = packWord(INV_SBOX[s3 >>> 24], INV_SBOX[s2 >>> 16 & 255], INV_SBOX[s1 >>> 8 & 255], INV_SBOX[s0 & 255]) ^ rk[at + 3];
130
170
  }
131
171
  function wholeBlockCount(byteLength) {
132
172
  return Math.floor(byteLength / 16);
133
173
  }
134
174
  function aesCbcDecrypt(key, iv, data) {
135
175
  const expanded = expandKey(key);
176
+ const inverseKey = inverseKeyWords(expanded);
136
177
  const blocks = wholeBlockCount(data.length);
137
178
  const out = new Uint8Array(blocks * 16);
138
- const chain = Uint8Array.from(iv.subarray(0, 16));
139
- for (let b = 0; b < blocks; b++) {
140
- const cipherBlock = data.subarray(b * 16, (b + 1) * 16);
141
- const state = Uint8Array.from(cipherBlock);
142
- decryptBlock(state, expanded);
143
- for (let i = 0; i < 16; i++) out[b * 16 + i] = state[i] ^ chain[i];
144
- chain.set(cipherBlock);
145
- }
179
+ const plain = new Uint32Array(WORDS_PER_BLOCK);
180
+ let c0 = readWord(iv, 0);
181
+ let c1 = readWord(iv, 4);
182
+ let c2 = readWord(iv, 8);
183
+ let c3 = readWord(iv, 12);
184
+ Array.from({ length: blocks }).forEach((_unused, b) => {
185
+ const at = b * 16;
186
+ const x0 = readWord(data, at);
187
+ const x1 = readWord(data, at + 4);
188
+ const x2 = readWord(data, at + 8);
189
+ const x3 = readWord(data, at + 12);
190
+ decryptWords(inverseKey, expanded.rounds, x0, x1, x2, x3, plain);
191
+ writeWord(out, at, plain[0] ^ c0);
192
+ writeWord(out, at + 4, plain[1] ^ c1);
193
+ writeWord(out, at + 8, plain[2] ^ c2);
194
+ writeWord(out, at + 12, plain[3] ^ c3);
195
+ c0 = x0;
196
+ c1 = x1;
197
+ c2 = x2;
198
+ c3 = x3;
199
+ });
146
200
  return out;
147
201
  }
148
202
  function aesCbcEncrypt(key, iv, data) {
149
203
  const expanded = expandKey(key);
150
204
  const blocks = wholeBlockCount(data.length);
151
205
  const out = new Uint8Array(blocks * 16);
152
- const chain = Uint8Array.from(iv.subarray(0, 16));
153
- for (let b = 0; b < blocks; b++) {
154
- const state = /* @__PURE__ */ new Uint8Array(16);
155
- for (let i = 0; i < 16; i++) state[i] = data[b * 16 + i] ^ chain[i];
156
- encryptBlock(state, expanded);
157
- out.set(state, b * 16);
158
- chain.set(state);
159
- }
206
+ const cipher = new Uint32Array(WORDS_PER_BLOCK);
207
+ let c0 = readWord(iv, 0);
208
+ let c1 = readWord(iv, 4);
209
+ let c2 = readWord(iv, 8);
210
+ let c3 = readWord(iv, 12);
211
+ Array.from({ length: blocks }).forEach((_unused, b) => {
212
+ const at = b * 16;
213
+ encryptWords(expanded, readWord(data, at) ^ c0, readWord(data, at + 4) ^ c1, readWord(data, at + 8) ^ c2, readWord(data, at + 12) ^ c3, cipher);
214
+ c0 = cipher[0];
215
+ c1 = cipher[1];
216
+ c2 = cipher[2];
217
+ c3 = cipher[3];
218
+ writeWord(out, at, c0);
219
+ writeWord(out, at + 4, c1);
220
+ writeWord(out, at + 8, c2);
221
+ writeWord(out, at + 12, c3);
222
+ });
160
223
  return out;
161
224
  }
162
225
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pdf-parser.js",
3
- "version": "4.8.5",
3
+ "version": "4.8.6",
4
4
  "description": "Hand-written, dependency-minimal PDF codec: parses arbitrary real-world PDFs and generates new ones, built on its own codec-owned LayoutDocument item model and Zod 4 codecs.",
5
5
  "type": "module",
6
6
  "repository": {