1use crate::object::{Dict, Object};
18
19const PAD: [u8; 32] = [
21 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
22 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A,
23];
24
25#[derive(Clone, Copy, PartialEq)]
27enum Cipher {
28 Rc4,
30 Aesv2,
32 Aesv3,
34}
35
36#[derive(Clone)]
38pub struct Decryptor {
39 key: Vec<u8>,
41 cipher: Cipher,
42}
43
44impl Decryptor {
45 pub fn from_standard(enc: &Dict, id0: &[u8]) -> Option<Decryptor> {
61 Decryptor::from_standard_with_password(enc, id0, b"")
62 }
63
64 pub fn from_standard_with_password_str(
69 enc: &Dict,
70 id0: &[u8],
71 password: &str,
72 ) -> Option<Decryptor> {
73 let dec = Decryptor::from_standard_with_password(enc, id0, password.as_bytes());
74 if dec.is_some() || password.is_ascii() || password.chars().any(|c| (c as u32) > 255) {
75 return dec;
76 }
77 let latin1: Vec<u8> = password.chars().map(|c| c as u8).collect();
78 Decryptor::from_standard_with_password(enc, id0, &latin1)
79 }
80
81 pub fn from_standard_with_password(
87 enc: &Dict,
88 id0: &[u8],
89 password: &[u8],
90 ) -> Option<Decryptor> {
91 if enc.get_name("Filter").map(|n| n.0.as_str()) != Some("Standard") {
92 return None;
93 }
94 let v = enc.get_int("V").unwrap_or(0);
95 let r = enc.get_int("R").unwrap_or(0);
96 match (v, r) {
97 (1 | 2, 2 | 3) => {
99 let n = if v == 1 {
100 5
101 } else {
102 (enc.get_int("Length").unwrap_or(40) / 8).clamp(5, 16) as usize
103 };
104 let key = rc4_family_key(enc, id0, r, n, password)?;
105 Some(Decryptor {
106 key,
107 cipher: Cipher::Rc4,
108 })
109 }
110 (4, 4) => {
112 let key = rc4_family_key(enc, id0, r, 16, password)?;
113 let cipher = match crypt_filter_method(enc)?.as_str() {
114 "AESV2" => Cipher::Aesv2,
115 "V2" => Cipher::Rc4,
116 _ => return None, };
118 Some(Decryptor { key, cipher })
119 }
120 (5, 5 | 6) => aesv3_key(enc, r, password).map(|key| Decryptor {
122 key,
123 cipher: Cipher::Aesv3,
124 }),
125 _ => None,
126 }
127 }
128
129 pub fn decrypt_object(&self, obj: &mut Object, num: u32, gen: u16) {
146 let key = match self.cipher {
147 Cipher::Aesv3 => self.key.clone(), Cipher::Rc4 | Cipher::Aesv2 => self.object_key(num, gen),
149 };
150 decrypt_in_place(obj, &key, self.cipher);
151 }
152
153 fn object_key(&self, num: u32, gen: u16) -> Vec<u8> {
157 let mut input = Vec::with_capacity(self.key.len() + 9);
158 input.extend_from_slice(&self.key);
159 input.extend_from_slice(&num.to_le_bytes()[..3]);
160 input.extend_from_slice(&gen.to_le_bytes()[..2]);
161 if self.cipher == Cipher::Aesv2 {
162 input.extend_from_slice(b"sAlT");
163 }
164 let digest = md5(&input);
165 let n = (self.key.len() + 5).min(16);
166 digest[..n].to_vec()
167 }
168}
169
170fn decrypt_in_place(obj: &mut Object, key: &[u8], cipher: Cipher) {
173 match obj {
174 Object::String(bytes) => *bytes = decrypt_bytes(cipher, key, bytes),
175 Object::Array(items) => items
176 .iter_mut()
177 .for_each(|it| decrypt_in_place(it, key, cipher)),
178 Object::Dict(dict) => dict
179 .values_mut()
180 .for_each(|v| decrypt_in_place(v, key, cipher)),
181 Object::Stream(stream) => {
182 stream
183 .dict
184 .values_mut()
185 .for_each(|v| decrypt_in_place(v, key, cipher));
186 stream.data = decrypt_bytes(cipher, key, &stream.data);
187 }
188 _ => {}
189 }
190}
191
192fn decrypt_bytes(cipher: Cipher, key: &[u8], data: &[u8]) -> Vec<u8> {
194 match cipher {
195 Cipher::Rc4 => rc4(key, data),
196 Cipher::Aesv2 | Cipher::Aesv3 => aes_cbc_decrypt(key, data),
197 }
198}
199
200fn crypt_filter_method(enc: &Dict) -> Option<String> {
203 let stmf = enc
204 .get_name("StmF")
205 .map(|n| n.0.as_str())
206 .unwrap_or("StdCF");
207 let filter = enc.get_dict("CF")?.get_dict(stmf)?;
208 Some(filter.get_name("CFM")?.0.clone())
209}
210
211fn pad_password(password: &[u8]) -> [u8; 32] {
215 let mut out = [0u8; 32];
216 let n = password.len().min(32);
217 out[..n].copy_from_slice(&password[..n]);
218 out[n..].copy_from_slice(&PAD[..32 - n]);
219 out
220}
221
222fn rc4_family_key(enc: &Dict, id0: &[u8], r: i64, n: usize, password: &[u8]) -> Option<Vec<u8>> {
227 let u = enc.get("U").and_then(Object::as_str_bytes)?;
228 if let Some(key) = md5_file_key(enc, id0, r, n, &pad_password(password)) {
229 if verify_user_password(&key, r, id0, u) {
230 return Some(key);
231 }
232 }
233 let o = enc.get("O").and_then(Object::as_str_bytes)?;
237 if o.len() < 32 {
238 return None;
239 }
240 let mut d = md5(&pad_password(password));
241 if r >= 3 {
242 for _ in 0..50 {
243 d = md5(&d[..n]);
244 }
245 }
246 let okey = &d[..n];
247 let recovered = if r == 2 {
248 rc4(okey, &o[..32])
249 } else {
250 let mut x = o[..32].to_vec();
251 for i in (1u8..=19).rev() {
252 let keyed: Vec<u8> = okey.iter().map(|b| b ^ i).collect();
253 x = rc4(&keyed, &x);
254 }
255 rc4(okey, &x)
256 };
257 let padded: [u8; 32] = recovered.get(..32)?.try_into().ok()?;
258 let key = md5_file_key(enc, id0, r, n, &padded)?;
259 verify_user_password(&key, r, id0, u).then_some(key)
260}
261
262fn md5_file_key(enc: &Dict, id0: &[u8], r: i64, n: usize, padded: &[u8; 32]) -> Option<Vec<u8>> {
264 let o = enc.get("O").and_then(Object::as_str_bytes)?;
265 if o.len() < 32 {
266 return None;
267 }
268 let p = enc.get_int("P")?;
269 let mut input = Vec::with_capacity(32 + 32 + 4 + id0.len() + 4);
270 input.extend_from_slice(padded);
271 input.extend_from_slice(&o[..32]);
272 input.extend_from_slice(&(p as i32 as u32).to_le_bytes()); input.extend_from_slice(id0);
274 if r >= 4 && enc.get("EncryptMetadata").and_then(Object::as_bool) == Some(false) {
276 input.extend_from_slice(&[0xFF, 0xFF, 0xFF, 0xFF]);
277 }
278 let mut digest = md5(&input);
279 if r >= 3 {
280 for _ in 0..50 {
281 digest = md5(&digest[..n]);
282 }
283 }
284 Some(digest[..n].to_vec())
285}
286
287fn verify_user_password(key: &[u8], r: i64, id0: &[u8], u: &[u8]) -> bool {
289 if r == 2 {
290 let computed = rc4(key, &PAD);
292 u.len() >= 32 && computed == u[..32]
293 } else {
294 let mut input = Vec::with_capacity(32 + id0.len());
296 input.extend_from_slice(&PAD);
297 input.extend_from_slice(id0);
298 let mut x = md5(&input).to_vec();
299 x = rc4(key, &x);
300 for i in 1u8..=19 {
301 let keyed: Vec<u8> = key.iter().map(|b| b ^ i).collect();
302 x = rc4(&keyed, &x);
303 }
304 u.len() >= 16 && x[..16] == u[..16]
306 }
307}
308
309fn rc4(key: &[u8], data: &[u8]) -> Vec<u8> {
311 debug_assert!(!key.is_empty());
312 let mut s: [u8; 256] = core::array::from_fn(|i| i as u8);
313 let mut j = 0u8;
314 for i in 0..256 {
315 j = j.wrapping_add(s[i]).wrapping_add(key[i % key.len()]);
316 s.swap(i, j as usize);
317 }
318 let mut out = Vec::with_capacity(data.len());
319 let (mut i, mut j) = (0u8, 0u8);
320 for &byte in data {
321 i = i.wrapping_add(1);
322 j = j.wrapping_add(s[i as usize]);
323 s.swap(i as usize, j as usize);
324 let k = s[s[i as usize].wrapping_add(s[j as usize]) as usize];
325 out.push(byte ^ k);
326 }
327 out
328}
329
330#[rustfmt::skip]
334const AES_SBOX: [u8; 256] = [
335 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
336 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
337 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
338 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
339 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
340 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
341 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
342 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
343 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
344 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
345 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
346 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
347 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
348 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
349 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
350 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16,
351];
352
353const AES_RCON: [u8; 11] = [
355 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
356];
357
358fn aes_inv_sbox() -> [u8; 256] {
360 let mut inv = [0u8; 256];
361 for (i, &s) in AES_SBOX.iter().enumerate() {
362 inv[s as usize] = i as u8;
363 }
364 inv
365}
366
367fn gmul(mut a: u8, mut b: u8) -> u8 {
369 let mut p = 0u8;
370 for _ in 0..8 {
371 if b & 1 != 0 {
372 p ^= a;
373 }
374 let hi = a & 0x80;
375 a <<= 1;
376 if hi != 0 {
377 a ^= 0x1b;
378 }
379 b >>= 1;
380 }
381 p
382}
383
384fn aes_expand_key(key: &[u8]) -> Vec<[u8; 16]> {
387 let nk = key.len() / 4; let nr = nk + 6;
389 let total = 4 * (nr + 1);
390 let mut w: Vec<[u8; 4]> = Vec::with_capacity(total);
391 for i in 0..nk {
392 w.push([key[4 * i], key[4 * i + 1], key[4 * i + 2], key[4 * i + 3]]);
393 }
394 for i in nk..total {
395 let mut t = w[i - 1];
396 if i.is_multiple_of(nk) {
397 t = [t[1], t[2], t[3], t[0]]; for b in &mut t {
399 *b = AES_SBOX[*b as usize]; }
401 t[0] ^= AES_RCON[i / nk];
402 } else if nk > 6 && i % nk == 4 {
403 for b in &mut t {
404 *b = AES_SBOX[*b as usize];
405 }
406 }
407 let prev = w[i - nk];
408 w.push([
409 prev[0] ^ t[0],
410 prev[1] ^ t[1],
411 prev[2] ^ t[2],
412 prev[3] ^ t[3],
413 ]);
414 }
415 (0..=nr)
416 .map(|round| {
417 let mut rk = [0u8; 16];
418 for c in 0..4 {
419 rk[4 * c..4 * c + 4].copy_from_slice(&w[4 * round + c]);
420 }
421 rk
422 })
423 .collect()
424}
425
426fn add_round_key(s: &mut [u8; 16], rk: &[u8; 16]) {
427 for (b, k) in s.iter_mut().zip(rk) {
428 *b ^= k;
429 }
430}
431
432fn shift_rows(s: &mut [u8; 16]) {
433 let o = *s;
434 for r in 1..4 {
435 for c in 0..4 {
436 s[r + 4 * c] = o[r + 4 * ((c + r) % 4)];
437 }
438 }
439}
440
441fn inv_shift_rows(s: &mut [u8; 16]) {
442 let o = *s;
443 for r in 1..4 {
444 for c in 0..4 {
445 s[r + 4 * c] = o[r + 4 * ((c + 4 - r) % 4)];
446 }
447 }
448}
449
450fn mix_columns(s: &mut [u8; 16]) {
451 for c in 0..4 {
452 let i = 4 * c;
453 let (a0, a1, a2, a3) = (s[i], s[i + 1], s[i + 2], s[i + 3]);
454 s[i] = gmul(a0, 2) ^ gmul(a1, 3) ^ a2 ^ a3;
455 s[i + 1] = a0 ^ gmul(a1, 2) ^ gmul(a2, 3) ^ a3;
456 s[i + 2] = a0 ^ a1 ^ gmul(a2, 2) ^ gmul(a3, 3);
457 s[i + 3] = gmul(a0, 3) ^ a1 ^ a2 ^ gmul(a3, 2);
458 }
459}
460
461fn inv_mix_columns(s: &mut [u8; 16]) {
462 for c in 0..4 {
463 let i = 4 * c;
464 let (a0, a1, a2, a3) = (s[i], s[i + 1], s[i + 2], s[i + 3]);
465 s[i] = gmul(a0, 14) ^ gmul(a1, 11) ^ gmul(a2, 13) ^ gmul(a3, 9);
466 s[i + 1] = gmul(a0, 9) ^ gmul(a1, 14) ^ gmul(a2, 11) ^ gmul(a3, 13);
467 s[i + 2] = gmul(a0, 13) ^ gmul(a1, 9) ^ gmul(a2, 14) ^ gmul(a3, 11);
468 s[i + 3] = gmul(a0, 11) ^ gmul(a1, 13) ^ gmul(a2, 9) ^ gmul(a3, 14);
469 }
470}
471
472fn aes_encrypt_block(s: &mut [u8; 16], rks: &[[u8; 16]]) {
473 #[cfg(target_arch = "aarch64")]
474 if std::arch::is_aarch64_feature_detected!("aes") {
475 unsafe { aes_hw::encrypt_block(s, rks) };
477 return;
478 }
479 #[cfg(target_arch = "x86_64")]
480 if std::arch::is_x86_feature_detected!("aes") {
481 unsafe { aes_hw::encrypt_block(s, rks) };
483 return;
484 }
485 aes_encrypt_block_soft(s, rks);
486}
487
488fn aes_encrypt_block_soft(s: &mut [u8; 16], rks: &[[u8; 16]]) {
490 let nr = rks.len() - 1;
491 add_round_key(s, &rks[0]);
492 for rk in &rks[1..nr] {
493 s.iter_mut().for_each(|b| *b = AES_SBOX[*b as usize]);
494 shift_rows(s);
495 mix_columns(s);
496 add_round_key(s, rk);
497 }
498 s.iter_mut().for_each(|b| *b = AES_SBOX[*b as usize]);
499 shift_rows(s);
500 add_round_key(s, &rks[nr]);
501}
502
503fn aes_decrypt_block(s: &mut [u8; 16], rks: &[[u8; 16]], inv_sbox: &[u8; 256]) {
504 #[cfg(target_arch = "aarch64")]
505 if std::arch::is_aarch64_feature_detected!("aes") {
506 unsafe { aes_hw::decrypt_block(s, rks) };
508 return;
509 }
510 #[cfg(target_arch = "x86_64")]
511 if std::arch::is_x86_feature_detected!("aes") {
512 unsafe { aes_hw::decrypt_block(s, rks) };
514 return;
515 }
516 aes_decrypt_block_soft(s, rks, inv_sbox);
517}
518
519fn aes_decrypt_block_soft(s: &mut [u8; 16], rks: &[[u8; 16]], inv_sbox: &[u8; 256]) {
521 let nr = rks.len() - 1;
522 add_round_key(s, &rks[nr]);
523 for rk in rks[1..nr].iter().rev() {
524 inv_shift_rows(s);
525 s.iter_mut().for_each(|b| *b = inv_sbox[*b as usize]);
526 add_round_key(s, rk);
527 inv_mix_columns(s);
528 }
529 inv_shift_rows(s);
530 s.iter_mut().for_each(|b| *b = inv_sbox[*b as usize]);
531 add_round_key(s, &rks[0]);
532}
533
534#[cfg(target_arch = "aarch64")]
542mod aes_hw {
543 use core::arch::aarch64::{
544 vaesdq_u8, vaeseq_u8, vaesimcq_u8, vaesmcq_u8, veorq_u8, vld1q_u8, vmovq_n_u8, vst1q_u8,
545 };
546
547 #[target_feature(enable = "aes")]
550 pub unsafe fn encrypt_block(s: &mut [u8; 16], rks: &[[u8; 16]]) {
551 let nr = rks.len() - 1;
552 let mut x = vld1q_u8(s.as_ptr());
556 for rk in &rks[..nr - 1] {
557 x = vaesmcq_u8(vaeseq_u8(x, vld1q_u8(rk.as_ptr())));
558 }
559 x = vaeseq_u8(x, vld1q_u8(rks[nr - 1].as_ptr()));
560 x = veorq_u8(x, vld1q_u8(rks[nr].as_ptr()));
561 vst1q_u8(s.as_mut_ptr(), x);
562 }
563
564 #[target_feature(enable = "aes")]
567 pub unsafe fn decrypt_block(s: &mut [u8; 16], rks: &[[u8; 16]]) {
568 let nr = rks.len() - 1;
569 let zero = vmovq_n_u8(0);
573 let mut x = vld1q_u8(s.as_ptr());
574 x = veorq_u8(x, vld1q_u8(rks[nr].as_ptr()));
575 for rk in rks[1..nr].iter().rev() {
576 x = vaesdq_u8(x, zero);
577 x = veorq_u8(x, vld1q_u8(rk.as_ptr()));
578 x = vaesimcq_u8(x);
579 }
580 x = vaesdq_u8(x, zero);
581 x = veorq_u8(x, vld1q_u8(rks[0].as_ptr()));
582 vst1q_u8(s.as_mut_ptr(), x);
583 }
584}
585
586#[cfg(target_arch = "x86_64")]
588mod aes_hw {
589 use core::arch::x86_64::{
590 __m128i, _mm_aesdec_si128, _mm_aesdeclast_si128, _mm_aesenc_si128, _mm_aesenclast_si128,
591 _mm_aesimc_si128, _mm_loadu_si128, _mm_storeu_si128, _mm_xor_si128,
592 };
593
594 #[target_feature(enable = "aes")]
597 pub unsafe fn encrypt_block(s: &mut [u8; 16], rks: &[[u8; 16]]) {
598 let nr = rks.len() - 1;
599 let mut x = _mm_loadu_si128(s.as_ptr().cast::<__m128i>());
600 x = _mm_xor_si128(x, _mm_loadu_si128(rks[0].as_ptr().cast::<__m128i>()));
601 for rk in &rks[1..nr] {
602 x = _mm_aesenc_si128(x, _mm_loadu_si128(rk.as_ptr().cast::<__m128i>()));
603 }
604 x = _mm_aesenclast_si128(x, _mm_loadu_si128(rks[nr].as_ptr().cast::<__m128i>()));
605 _mm_storeu_si128(s.as_mut_ptr().cast::<__m128i>(), x);
606 }
607
608 #[target_feature(enable = "aes")]
611 pub unsafe fn decrypt_block(s: &mut [u8; 16], rks: &[[u8; 16]]) {
612 let nr = rks.len() - 1;
613 let mut x = _mm_loadu_si128(s.as_ptr().cast::<__m128i>());
616 x = _mm_xor_si128(x, _mm_loadu_si128(rks[nr].as_ptr().cast::<__m128i>()));
617 for rk in rks[1..nr].iter().rev() {
618 let dk = _mm_aesimc_si128(_mm_loadu_si128(rk.as_ptr().cast::<__m128i>()));
619 x = _mm_aesdec_si128(x, dk);
620 }
621 x = _mm_aesdeclast_si128(x, _mm_loadu_si128(rks[0].as_ptr().cast::<__m128i>()));
622 _mm_storeu_si128(s.as_mut_ptr().cast::<__m128i>(), x);
623 }
624}
625
626fn aes_cbc_decrypt_blocks(key: &[u8], iv: &[u8], data: &[u8]) -> Vec<u8> {
629 if data.is_empty() || !data.len().is_multiple_of(16) || iv.len() < 16 {
630 return Vec::new();
631 }
632 let rks = aes_expand_key(key);
633 let inv_sbox = aes_inv_sbox();
634 let mut prev = [0u8; 16];
635 prev.copy_from_slice(&iv[..16]);
636 let mut out = Vec::with_capacity(data.len());
637 for chunk in data.as_chunks::<16>().0 {
638 let mut block = [0u8; 16];
639 block.copy_from_slice(chunk);
640 let cipher = block;
641 aes_decrypt_block(&mut block, &rks, &inv_sbox);
642 for (b, p) in block.iter_mut().zip(&prev) {
643 *b ^= p;
644 }
645 out.extend_from_slice(&block);
646 prev = cipher;
647 }
648 out
649}
650
651fn aes_cbc_encrypt_blocks(key: &[u8], iv: &[u8], data: &[u8]) -> Vec<u8> {
654 let rks = aes_expand_key(key);
655 let mut prev = [0u8; 16];
656 prev.copy_from_slice(&iv[..16]);
657 let mut out = Vec::with_capacity(data.len());
658 for chunk in data.as_chunks::<16>().0 {
659 let mut block = [0u8; 16];
660 for ((b, c), p) in block.iter_mut().zip(chunk).zip(&prev) {
661 *b = c ^ p;
662 }
663 aes_encrypt_block(&mut block, &rks);
664 out.extend_from_slice(&block);
665 prev = block;
666 }
667 out
668}
669
670fn aes_cbc_decrypt(key: &[u8], data: &[u8]) -> Vec<u8> {
674 if data.len() < 16 {
675 return Vec::new();
676 }
677 let (iv, ct) = data.split_at(16);
678 let mut out = aes_cbc_decrypt_blocks(key, iv, ct);
679 strip_pkcs7(&mut out);
680 out
681}
682
683fn strip_pkcs7(data: &mut Vec<u8>) {
685 let Some(&pad) = data.last() else {
686 return;
687 };
688 let pad = pad as usize;
689 if (1..=16).contains(&pad) && pad <= data.len() {
690 let start = data.len() - pad;
691 if data[start..].iter().all(|&b| b as usize == pad) {
692 data.truncate(start);
693 }
694 }
695}
696
697#[rustfmt::skip]
700const SHA256_K: [u32; 64] = [
701 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
702 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
703 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
704 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
705 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
706 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
707 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
708 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
709];
710
711#[derive(Debug, Clone)]
716pub struct Sha256 {
717 h: [u32; 8],
718 tail: [u8; 64],
719 tail_len: usize,
720 total: u64,
721}
722
723impl Default for Sha256 {
724 fn default() -> Sha256 {
725 Sha256::new()
726 }
727}
728
729impl Sha256 {
730 pub fn new() -> Sha256 {
732 Sha256 {
733 h: [
734 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
735 0x5be0cd19,
736 ],
737 tail: [0u8; 64],
738 tail_len: 0,
739 total: 0,
740 }
741 }
742
743 pub fn update(&mut self, input: &[u8]) {
748 self.total = self.total.wrapping_add(input.len() as u64);
749 let mut input = input;
750 if self.tail_len > 0 {
751 let take = input.len().min(64 - self.tail_len);
752 self.tail[self.tail_len..self.tail_len + take].copy_from_slice(&input[..take]);
753 self.tail_len += take;
754 input = &input[take..];
755 if self.tail_len < 64 {
756 return;
757 }
758 let block = self.tail;
759 sha256_compress(&mut self.h, &block);
760 self.tail_len = 0;
761 }
762 let (blocks, rest) = input.as_chunks::<64>();
763 for block in blocks {
764 sha256_compress(&mut self.h, block);
765 }
766 self.tail[..rest.len()].copy_from_slice(rest);
767 self.tail_len = rest.len();
768 }
769
770 pub fn finalize(mut self) -> [u8; 32] {
772 let mut pad = [0u8; 128];
775 pad[..self.tail_len].copy_from_slice(&self.tail[..self.tail_len]);
776 pad[self.tail_len] = 0x80;
777 let padded = if self.tail_len < 56 { 64 } else { 128 };
778 let bitlen = self.total.wrapping_mul(8);
779 pad[padded - 8..padded].copy_from_slice(&bitlen.to_be_bytes());
780 for block in pad[..padded].as_chunks::<64>().0 {
781 sha256_compress(&mut self.h, block);
782 }
783 let mut out = [0u8; 32];
784 for (i, word) in self.h.iter().enumerate() {
785 out[4 * i..4 * i + 4].copy_from_slice(&word.to_be_bytes());
786 }
787 out
788 }
789}
790
791pub fn sha256(input: &[u8]) -> [u8; 32] {
793 let mut hasher = Sha256::new();
794 hasher.update(input);
795 hasher.finalize()
796}
797
798fn sha256_compress(h: &mut [u32; 8], block: &[u8; 64]) {
799 #[cfg(target_arch = "aarch64")]
800 if std::arch::is_aarch64_feature_detected!("sha2") {
801 unsafe { sha_hw::compress256(h, block) };
803 return;
804 }
805 sha256_compress_soft(h, block);
806}
807
808fn sha256_compress_soft(h: &mut [u32; 8], block: &[u8; 64]) {
810 let mut w = [0u32; 64];
811 for (word, bytes) in w.iter_mut().zip(block.as_chunks::<4>().0) {
812 *word = u32::from_be_bytes(*bytes);
813 }
814 for i in 16..64 {
815 let s0 = w[i - 15].rotate_right(7) ^ w[i - 15].rotate_right(18) ^ (w[i - 15] >> 3);
816 let s1 = w[i - 2].rotate_right(17) ^ w[i - 2].rotate_right(19) ^ (w[i - 2] >> 10);
817 w[i] = w[i - 16]
818 .wrapping_add(s0)
819 .wrapping_add(w[i - 7])
820 .wrapping_add(s1);
821 }
822 let [mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut hh] = *h;
823 for (k, wi) in SHA256_K.iter().zip(&w) {
824 let s1 = e.rotate_right(6) ^ e.rotate_right(11) ^ e.rotate_right(25);
825 let ch = (e & f) ^ ((!e) & g);
826 let t1 = hh
827 .wrapping_add(s1)
828 .wrapping_add(ch)
829 .wrapping_add(*k)
830 .wrapping_add(*wi);
831 let s0 = a.rotate_right(2) ^ a.rotate_right(13) ^ a.rotate_right(22);
832 let maj = (a & b) ^ (a & c) ^ (b & c);
833 let t2 = s0.wrapping_add(maj);
834 hh = g;
835 g = f;
836 f = e;
837 e = d.wrapping_add(t1);
838 d = c;
839 c = b;
840 b = a;
841 a = t1.wrapping_add(t2);
842 }
843 for (hv, v) in h.iter_mut().zip([a, b, c, d, e, f, g, hh]) {
844 *hv = hv.wrapping_add(v);
845 }
846}
847
848#[rustfmt::skip]
849const SHA512_K: [u64; 80] = [
850 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
851 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
852 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
853 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
854 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
855 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
856 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
857 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
858 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
859 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
860 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
861 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
862 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
863 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
864 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
865 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
866 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
867 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
868 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
869 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
870];
871
872fn sha512_core(input: &[u8], mut h: [u64; 8]) -> [u64; 8] {
873 let (blocks, tail) = input.as_chunks::<128>();
874 for block in blocks {
875 sha512_compress(&mut h, block);
876 }
877 let mut pad = [0u8; 256];
881 pad[..tail.len()].copy_from_slice(tail);
882 pad[tail.len()] = 0x80;
883 let padded = if tail.len() < 112 { 128 } else { 256 };
884 let bitlen = (input.len() as u128).wrapping_mul(8);
885 pad[padded - 16..padded].copy_from_slice(&bitlen.to_be_bytes());
886 for block in pad[..padded].as_chunks::<128>().0 {
887 sha512_compress(&mut h, block);
888 }
889 h
890}
891
892fn sha512_compress(h: &mut [u64; 8], block: &[u8; 128]) {
893 #[cfg(target_arch = "aarch64")]
894 if std::arch::is_aarch64_feature_detected!("sha3") {
895 unsafe { sha_hw::compress512(h, block) };
898 return;
899 }
900 sha512_compress_soft(h, block);
901}
902
903fn sha512_compress_soft(h: &mut [u64; 8], block: &[u8; 128]) {
905 let mut w = [0u64; 80];
906 for (word, bytes) in w.iter_mut().zip(block.as_chunks::<8>().0) {
907 *word = u64::from_be_bytes(*bytes);
908 }
909 for i in 16..80 {
910 let s0 = w[i - 15].rotate_right(1) ^ w[i - 15].rotate_right(8) ^ (w[i - 15] >> 7);
911 let s1 = w[i - 2].rotate_right(19) ^ w[i - 2].rotate_right(61) ^ (w[i - 2] >> 6);
912 w[i] = w[i - 16]
913 .wrapping_add(s0)
914 .wrapping_add(w[i - 7])
915 .wrapping_add(s1);
916 }
917 let [mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut hh] = *h;
918 for (k, wi) in SHA512_K.iter().zip(&w) {
919 let s1 = e.rotate_right(14) ^ e.rotate_right(18) ^ e.rotate_right(41);
920 let ch = (e & f) ^ ((!e) & g);
921 let t1 = hh
922 .wrapping_add(s1)
923 .wrapping_add(ch)
924 .wrapping_add(*k)
925 .wrapping_add(*wi);
926 let s0 = a.rotate_right(28) ^ a.rotate_right(34) ^ a.rotate_right(39);
927 let maj = (a & b) ^ (a & c) ^ (b & c);
928 let t2 = s0.wrapping_add(maj);
929 hh = g;
930 g = f;
931 f = e;
932 e = d.wrapping_add(t1);
933 d = c;
934 c = b;
935 b = a;
936 a = t1.wrapping_add(t2);
937 }
938 for (hv, v) in h.iter_mut().zip([a, b, c, d, e, f, g, hh]) {
939 *hv = hv.wrapping_add(v);
940 }
941}
942
943#[cfg(target_arch = "aarch64")]
952mod sha_hw {
953 use core::arch::aarch64::{
954 uint32x4_t, uint64x2_t, vaddq_u32, vaddq_u64, vextq_u64, vld1q_u32, vld1q_u64, vld1q_u8,
955 vreinterpretq_u32_u8, vreinterpretq_u64_u8, vrev32q_u8, vrev64q_u8, vsha256h2q_u32,
956 vsha256hq_u32, vsha256su0q_u32, vsha256su1q_u32, vsha512h2q_u64, vsha512hq_u64,
957 vsha512su0q_u64, vsha512su1q_u64, vst1q_u32,
958 };
959
960 use super::{SHA256_K, SHA512_K};
961
962 #[target_feature(enable = "sha2")]
965 pub unsafe fn compress256(h: &mut [u32; 8], block: &[u8; 64]) {
966 let mut abcd = vld1q_u32(h.as_ptr());
967 let mut efgh = vld1q_u32(h.as_ptr().add(4));
968 let saved = (abcd, efgh);
969 let mut w: [uint32x4_t; 4] = [
970 vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(block.as_ptr()))),
971 vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(block.as_ptr().add(16)))),
972 vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(block.as_ptr().add(32)))),
973 vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(block.as_ptr().add(48)))),
974 ];
975 for step in 0..16 {
976 let wk = vaddq_u32(w[step % 4], vld1q_u32(SHA256_K.as_ptr().add(4 * step)));
977 if step < 12 {
979 w[step % 4] = vsha256su1q_u32(
980 vsha256su0q_u32(w[step % 4], w[(step + 1) % 4]),
981 w[(step + 2) % 4],
982 w[(step + 3) % 4],
983 );
984 }
985 let prev = abcd;
986 abcd = vsha256hq_u32(abcd, efgh, wk);
987 efgh = vsha256h2q_u32(efgh, prev, wk);
988 }
989 vst1q_u32(h.as_mut_ptr(), vaddq_u32(abcd, saved.0));
990 vst1q_u32(h.as_mut_ptr().add(4), vaddq_u32(efgh, saved.1));
991 }
992
993 #[target_feature(enable = "sha2,sha3")]
996 pub unsafe fn compress512(h: &mut [u64; 8], block: &[u8; 128]) {
997 let mut s: [uint64x2_t; 4] = [
1001 vld1q_u64(h.as_ptr()),
1002 vld1q_u64(h.as_ptr().add(2)),
1003 vld1q_u64(h.as_ptr().add(4)),
1004 vld1q_u64(h.as_ptr().add(6)),
1005 ];
1006 let saved = s;
1007 let mut w: [uint64x2_t; 8] = [core::mem::zeroed(); 8];
1008 for (pair, bytes) in w.iter_mut().zip(block.as_chunks::<16>().0) {
1009 *pair = vreinterpretq_u64_u8(vrev64q_u8(vld1q_u8(bytes.as_ptr())));
1010 }
1011 for step in 0..40 {
1012 let r = 3 - (step % 4);
1013 let wk = vaddq_u64(w[step % 8], vld1q_u64(SHA512_K.as_ptr().add(2 * step)));
1014 let sum = vaddq_u64(vextq_u64::<1>(wk, wk), s[r]);
1015 let im = vsha512hq_u64(
1016 sum,
1017 vextq_u64::<1>(s[(r + 3) % 4], s[r]),
1018 vextq_u64::<1>(s[(r + 2) % 4], s[(r + 3) % 4]),
1019 );
1020 let updated = vsha512h2q_u64(im, s[(r + 2) % 4], s[(r + 1) % 4]);
1021 s[(r + 2) % 4] = vaddq_u64(s[(r + 2) % 4], im);
1022 s[r] = updated;
1023 if step < 32 {
1025 let i = step % 8;
1026 w[i] = vsha512su1q_u64(
1027 vsha512su0q_u64(w[i], w[(i + 1) % 8]),
1028 w[(i + 7) % 8],
1029 vextq_u64::<1>(w[(i + 4) % 8], w[(i + 5) % 8]),
1030 );
1031 }
1032 }
1033 for (i, (out, kept)) in s.iter().zip(saved).enumerate() {
1034 let summed = vaddq_u64(*out, kept);
1035 core::arch::aarch64::vst1q_u64(h.as_mut_ptr().add(2 * i), summed);
1036 }
1037 }
1038}
1039
1040fn sha512(input: &[u8]) -> Vec<u8> {
1041 let h = sha512_core(
1042 input,
1043 [
1044 0x6a09e667f3bcc908,
1045 0xbb67ae8584caa73b,
1046 0x3c6ef372fe94f82b,
1047 0xa54ff53a5f1d36f1,
1048 0x510e527fade682d1,
1049 0x9b05688c2b3e6c1f,
1050 0x1f83d9abfb41bd6b,
1051 0x5be0cd19137e2179,
1052 ],
1053 );
1054 h.iter().flat_map(|w| w.to_be_bytes()).collect()
1055}
1056
1057fn sha384(input: &[u8]) -> Vec<u8> {
1058 let h = sha512_core(
1059 input,
1060 [
1061 0xcbbb9d5dc1059ed8,
1062 0x629a292a367cd507,
1063 0x9159015a3070dd17,
1064 0x152fecd8f70e5939,
1065 0x67332667ffc00b31,
1066 0x8eb44a8768581511,
1067 0xdb0c2e0d64f98fa7,
1068 0x47b5481dbefa4fa4,
1069 ],
1070 );
1071 h.iter().take(6).flat_map(|w| w.to_be_bytes()).collect()
1072}
1073
1074fn aesv3_key(enc: &Dict, r: i64, password: &[u8]) -> Option<Vec<u8>> {
1080 let pw = &password[..password.len().min(127)];
1081 let u = enc.get("U").and_then(Object::as_str_bytes)?;
1082 if u.len() < 48 {
1083 return None;
1084 }
1085 let perms = enc.get("Perms").and_then(Object::as_str_bytes);
1093 let o = enc.get("O").and_then(Object::as_str_bytes);
1094 if let Some(perms) = perms.filter(|p| p.len() >= 16) {
1095 if let Some(ue) = enc.get("UE").and_then(Object::as_str_bytes) {
1096 if ue.len() >= 32 {
1097 let intermediate = hash_2b(r, pw, &u[40..48], &[]);
1098 let file_key = aes_cbc_decrypt_blocks(&intermediate, &[0u8; 16], &ue[..32]);
1099 if file_key.len() == 32 && perms_marker_valid(&file_key, perms) {
1100 return Some(file_key);
1101 }
1102 }
1103 }
1104 if let (Some(o), Some(oe)) = (o, enc.get("OE").and_then(Object::as_str_bytes)) {
1105 if o.len() >= 48 && oe.len() >= 32 {
1106 let intermediate = hash_2b(r, pw, &o[40..48], &u[..48]);
1107 let file_key = aes_cbc_decrypt_blocks(&intermediate, &[0u8; 16], &oe[..32]);
1108 if file_key.len() == 32 && perms_marker_valid(&file_key, perms) {
1109 return Some(file_key);
1110 }
1111 }
1112 }
1113 }
1114 if let Some(ue) = enc.get("UE").and_then(Object::as_str_bytes) {
1115 if ue.len() >= 32 && hash_2b(r, pw, &u[32..40], &[])[..32] == u[..32] {
1116 let intermediate = hash_2b(r, pw, &u[40..48], &[]);
1117 let file_key = aes_cbc_decrypt_blocks(&intermediate, &[0u8; 16], &ue[..32]);
1118 if file_key.len() == 32 {
1119 return Some(file_key);
1120 }
1121 }
1122 }
1123 let o = o?;
1124 let oe = enc.get("OE").and_then(Object::as_str_bytes)?;
1125 if o.len() < 48 || oe.len() < 32 {
1126 return None;
1127 }
1128 if hash_2b(r, pw, &o[32..40], &u[..48])[..32] != o[..32] {
1129 return None;
1130 }
1131 let intermediate = hash_2b(r, pw, &o[40..48], &u[..48]);
1132 let file_key = aes_cbc_decrypt_blocks(&intermediate, &[0u8; 16], &oe[..32]);
1133 (file_key.len() == 32).then_some(file_key)
1134}
1135
1136fn perms_marker_valid(file_key: &[u8], perms: &[u8]) -> bool {
1139 let rks = aes_expand_key(file_key);
1140 let inv_sbox = aes_inv_sbox();
1141 let mut block = [0u8; 16];
1142 block.copy_from_slice(&perms[..16]);
1143 aes_decrypt_block(&mut block, &rks, &inv_sbox);
1144 &block[9..12] == b"adb"
1145}
1146
1147fn hash_2b(r: i64, password: &[u8], salt: &[u8], udata: &[u8]) -> Vec<u8> {
1150 let mut seed = Vec::with_capacity(password.len() + salt.len() + udata.len());
1151 seed.extend_from_slice(password);
1152 seed.extend_from_slice(salt);
1153 seed.extend_from_slice(udata);
1154 let mut k = sha256(&seed).to_vec();
1155 if r < 6 {
1156 return k; }
1158 let mut round = 0usize;
1159 let mut k1 = Vec::with_capacity(64 * (password.len() + 64 + udata.len()));
1160 loop {
1161 k1.clear();
1162 for _ in 0..64 {
1163 k1.extend_from_slice(password);
1164 k1.extend_from_slice(&k);
1165 k1.extend_from_slice(udata);
1166 }
1167 let e = aes_cbc_encrypt_blocks(&k[..16], &k[16..32], &k1);
1168 let modulus = e[..16].iter().map(|&b| u32::from(b)).sum::<u32>() % 3;
1169 k = match modulus {
1170 0 => sha256(&e).to_vec(),
1171 1 => sha384(&e),
1172 _ => sha512(&e),
1173 };
1174 round += 1;
1175 if round >= 64 && usize::from(*e.last().unwrap()) <= round - 32 {
1176 break;
1177 }
1178 }
1179 k.truncate(32);
1180 k
1181}
1182
1183#[rustfmt::skip]
1185const MD5_S: [u32; 64] = [
1186 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
1187 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
1188 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
1189 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
1190];
1191
1192#[rustfmt::skip]
1194const MD5_K: [u32; 64] = [
1195 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
1196 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
1197 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
1198 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
1199 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
1200 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
1201 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
1202 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
1203];
1204
1205fn md5(input: &[u8]) -> [u8; 16] {
1208 let (mut a0, mut b0, mut c0, mut d0) = (
1209 0x6745_2301u32,
1210 0xefcd_ab89u32,
1211 0x98ba_dcfeu32,
1212 0x1032_5476u32,
1213 );
1214
1215 let mut msg = input.to_vec();
1216 let bitlen = (input.len() as u64).wrapping_mul(8);
1217 msg.push(0x80);
1218 while msg.len() % 64 != 56 {
1219 msg.push(0);
1220 }
1221 msg.extend_from_slice(&bitlen.to_le_bytes());
1222
1223 for chunk in msg.as_chunks::<64>().0 {
1224 let mut m = [0u32; 16];
1225 for (word, bytes) in m.iter_mut().zip(chunk.as_chunks::<4>().0) {
1226 *word = u32::from_le_bytes(*bytes);
1227 }
1228 let (mut a, mut b, mut c, mut d) = (a0, b0, c0, d0);
1229 for i in 0..64 {
1230 let (f, g) = match i {
1231 0..=15 => ((b & c) | (!b & d), i),
1232 16..=31 => ((d & b) | (!d & c), (5 * i + 1) % 16),
1233 32..=47 => (b ^ c ^ d, (3 * i + 5) % 16),
1234 _ => (c ^ (b | !d), (7 * i) % 16),
1235 };
1236 let f = f.wrapping_add(a).wrapping_add(MD5_K[i]).wrapping_add(m[g]);
1237 a = d;
1238 d = c;
1239 c = b;
1240 b = b.wrapping_add(f.rotate_left(MD5_S[i]));
1241 }
1242 a0 = a0.wrapping_add(a);
1243 b0 = b0.wrapping_add(b);
1244 c0 = c0.wrapping_add(c);
1245 d0 = d0.wrapping_add(d);
1246 }
1247
1248 let mut out = [0u8; 16];
1249 out[0..4].copy_from_slice(&a0.to_le_bytes());
1250 out[4..8].copy_from_slice(&b0.to_le_bytes());
1251 out[8..12].copy_from_slice(&c0.to_le_bytes());
1252 out[12..16].copy_from_slice(&d0.to_le_bytes());
1253 out
1254}
1255
1256#[cfg(test)]
1257mod tests {
1258 use super::*;
1259 use crate::object::Name;
1260
1261 fn hex(bytes: &[u8]) -> String {
1262 bytes.iter().map(|b| format!("{b:02x}")).collect()
1263 }
1264
1265 #[test]
1266 fn md5_known_vectors() {
1267 assert_eq!(hex(&md5(b"")), "d41d8cd98f00b204e9800998ecf8427e");
1268 assert_eq!(hex(&md5(b"abc")), "900150983cd24fb0d6963f7d28e17f72");
1269 assert_eq!(
1270 hex(&md5(b"The quick brown fox jumps over the lazy dog")),
1271 "9e107d9d372bb6826bd81d3542a419d6"
1272 );
1273 }
1274
1275 #[test]
1276 fn md5_spans_block_boundary() {
1277 let input = [b'a'; 56];
1279 assert_eq!(hex(&md5(&input)), "3b0c8ac703f828b04c6c197006d17218");
1280 }
1281
1282 #[test]
1287 fn aes_block_known_vectors() {
1288 let plain: [u8; 16] = core::array::from_fn(|i| (i as u8) * 0x11);
1289 let key128: [u8; 16] = core::array::from_fn(|i| i as u8);
1290 let key256: [u8; 32] = core::array::from_fn(|i| i as u8);
1291
1292 type Encrypt = fn(&mut [u8; 16], &[[u8; 16]]);
1293 type Decrypt = fn(&mut [u8; 16], &[[u8; 16]], &[u8; 256]);
1294 let paths: [(Encrypt, Decrypt); 2] = [
1295 (aes_encrypt_block, aes_decrypt_block),
1296 (aes_encrypt_block_soft, aes_decrypt_block_soft),
1297 ];
1298 for (encrypt, decrypt) in paths {
1299 let mut s = plain;
1300 encrypt(&mut s, &aes_expand_key(&key128));
1301 assert_eq!(hex(&s), "69c4e0d86a7b0430d8cdb78070b4c55a");
1302 decrypt(&mut s, &aes_expand_key(&key128), &aes_inv_sbox());
1303 assert_eq!(s, plain);
1304
1305 let mut s = plain;
1306 encrypt(&mut s, &aes_expand_key(&key256));
1307 assert_eq!(hex(&s), "8ea2b7ca516745bfeafc49904b496089");
1308 decrypt(&mut s, &aes_expand_key(&key256), &aes_inv_sbox());
1309 assert_eq!(s, plain);
1310 }
1311 }
1312
1313 #[test]
1316 fn aes_cbc_round_trips_multiple_blocks() {
1317 let key: [u8; 16] = core::array::from_fn(|i| (i as u8).wrapping_mul(7));
1318 let iv: [u8; 16] = core::array::from_fn(|i| 0xa5 ^ (i as u8));
1319 let data: Vec<u8> = (0..64u8).collect();
1320 let ct = aes_cbc_encrypt_blocks(&key, &iv, &data);
1321 assert_eq!(ct.len(), data.len());
1322 assert_ne!(ct, data);
1323 assert_eq!(aes_cbc_decrypt_blocks(&key, &iv, &ct), data);
1324 }
1325
1326 #[test]
1330 fn sha2_known_vectors() {
1331 assert_eq!(
1332 hex(&sha256(b"")),
1333 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
1334 );
1335 assert_eq!(
1336 hex(&sha256(b"abc")),
1337 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
1338 );
1339 assert_eq!(
1340 hex(&sha256(&[b'a'; 200])),
1341 "c2a908d98f5df987ade41b5fce213067efbcc21ef2240212a41e54b5e7c28ae5"
1342 );
1343 assert_eq!(
1344 hex(&sha384(b"abc")),
1345 "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed\
1346 8086072ba1e7cc2358baeca134c825a7"
1347 );
1348 assert_eq!(
1349 hex(&sha512(b"abc")),
1350 "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a\
1351 2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
1352 );
1353 assert_eq!(
1354 hex(&sha512(&[b'a'; 300])),
1355 "a6a77010dd9696c23831e6549de51724df332c2075039b75fcfe6c2e6de42fbd\
1356 3c80ed4073267e00c8c320712c3cdd9d65a96f90a3fe4a58a6b70a103be08e83"
1357 );
1358 }
1359
1360 #[test]
1364 fn sha2_soft_compressions_match_the_dispatch() {
1365 let block64: [u8; 64] = core::array::from_fn(|i| (i as u8).wrapping_mul(31));
1366 let mut via_dispatch = [0x6a09e667u32; 8];
1367 let mut via_soft = via_dispatch;
1368 sha256_compress(&mut via_dispatch, &block64);
1369 sha256_compress_soft(&mut via_soft, &block64);
1370 assert_eq!(via_dispatch, via_soft);
1371
1372 let block128: [u8; 128] = core::array::from_fn(|i| (i as u8).wrapping_mul(29));
1373 let mut via_dispatch = [0x6a09e667f3bcc908u64; 8];
1374 let mut via_soft = via_dispatch;
1375 sha512_compress(&mut via_dispatch, &block128);
1376 sha512_compress_soft(&mut via_soft, &block128);
1377 assert_eq!(via_dispatch, via_soft);
1378 }
1379
1380 #[test]
1383 fn incremental_sha256_matches_the_one_shot() {
1384 let input: Vec<u8> = (0..300u16).map(|i| (i % 251) as u8).collect();
1385 for splits in [
1386 vec![0, 1, 3, 7, 60, 63, 64, 65, 37],
1387 vec![300],
1388 vec![128, 128, 44],
1389 vec![55, 9, 236],
1390 ] {
1391 let mut hasher = Sha256::new();
1392 let mut fed = 0usize;
1393 for len in splits {
1394 hasher.update(&input[fed..fed + len]);
1395 fed += len;
1396 }
1397 hasher.update(&input[fed..]);
1398 assert_eq!(hasher.finalize(), sha256(&input));
1399 }
1400 assert_eq!(Sha256::new().finalize(), sha256(b""));
1401 assert_eq!(Sha256::default().finalize(), sha256(b""));
1402 }
1403
1404 #[test]
1405 fn rc4_known_vector() {
1406 let ct = rc4(b"Key", b"Plaintext");
1408 assert_eq!(hex(&ct), "bbf316e8d940af0ad3");
1409 assert_eq!(rc4(b"Key", &ct), b"Plaintext");
1411 }
1412
1413 const N: usize = 16; const P: i32 = -44;
1420 const ID0: &[u8] = b"0123456789abcdef";
1421
1422 fn owner_entry(owner_pw: &[u8], user_pw: &[u8]) -> Vec<u8> {
1424 let mut d = md5(&pad_password(owner_pw));
1425 for _ in 0..50 {
1426 d = md5(&d[..N]);
1427 }
1428 let rc4key = d[..N].to_vec();
1429 let mut o = rc4(&rc4key, &pad_password(user_pw));
1430 for i in 1u8..=19 {
1431 let k: Vec<u8> = rc4key.iter().map(|b| b ^ i).collect();
1432 o = rc4(&k, &o);
1433 }
1434 o
1435 }
1436
1437 fn file_key(o: &[u8], user_pw: &[u8]) -> Vec<u8> {
1439 let mut input = Vec::new();
1440 input.extend_from_slice(&pad_password(user_pw));
1441 input.extend_from_slice(o);
1442 input.extend_from_slice(&(P as u32).to_le_bytes());
1443 input.extend_from_slice(ID0);
1444 let mut d = md5(&input);
1445 for _ in 0..50 {
1446 d = md5(&d[..N]);
1447 }
1448 d[..N].to_vec()
1449 }
1450
1451 fn user_entry(key: &[u8]) -> Vec<u8> {
1453 let mut input = Vec::new();
1454 input.extend_from_slice(&PAD);
1455 input.extend_from_slice(ID0);
1456 let mut x = md5(&input).to_vec();
1457 x = rc4(key, &x);
1458 for i in 1u8..=19 {
1459 let k: Vec<u8> = key.iter().map(|b| b ^ i).collect();
1460 x = rc4(&k, &x);
1461 }
1462 x.resize(32, 0); x
1464 }
1465
1466 fn obj_key(key: &[u8], num: u32, gen: u16) -> Vec<u8> {
1467 let mut input = key.to_vec();
1468 input.extend_from_slice(&num.to_le_bytes()[..3]);
1469 input.extend_from_slice(&gen.to_le_bytes()[..2]);
1470 md5(&input)[..(key.len() + 5).min(16)].to_vec()
1471 }
1472
1473 fn hexstr(b: &[u8]) -> String {
1474 let mut s = String::from("<");
1475 for x in b {
1476 s.push_str(&format!("{x:02x}"));
1477 }
1478 s.push('>');
1479 s
1480 }
1481
1482 fn encrypted_fixture(u_override: Option<Vec<u8>>) -> Vec<u8> {
1483 encrypted_fixture_with(b"", b"", u_override)
1484 }
1485
1486 fn encrypted_fixture_with(
1487 user_pw: &[u8],
1488 owner_pw: &[u8],
1489 u_override: Option<Vec<u8>>,
1490 ) -> Vec<u8> {
1491 use pdfboss_testkit::PdfBuilder;
1492 let o = owner_entry(owner_pw, user_pw);
1493 let key = file_key(&o, user_pw);
1494 let u = u_override.unwrap_or_else(|| user_entry(&key));
1495
1496 let msg = rc4(&obj_key(&key, 3, 0), b"Top secret message");
1497 let stream = rc4(&obj_key(&key, 4, 0), b"decrypted stream body");
1498
1499 let mut b = PdfBuilder::new().version(1, 4);
1500 b.object(1, "<< /Type /Catalog /Pages 2 0 R >>");
1501 b.object(2, "<< /Type /Pages /Kids [] /Count 0 >>");
1502 b.object(3, &format!("<< /Msg {} >>", hexstr(&msg)));
1503 b.stream(4, "", &stream);
1504 b.object(
1505 9,
1506 &format!(
1507 "<< /Filter /Standard /V 2 /R 3 /Length 128 /P {P} /O {} /U {} >>",
1508 hexstr(&o),
1509 hexstr(&u)
1510 ),
1511 );
1512 let trailer = format!("/Encrypt 9 0 R /ID [{}{}]", hexstr(ID0), hexstr(ID0));
1513 b.trailer_extra(&trailer).build(1)
1514 }
1515
1516 #[test]
1517 fn document_load_decrypts_standard_rc4() {
1518 use crate::object::ObjRef;
1519 use crate::Document;
1520
1521 let doc = Document::load(encrypted_fixture(None)).expect("empty password opens the file");
1522
1523 let obj3 = doc.get(ObjRef { num: 3, gen: 0 }).unwrap();
1524 let msg = obj3
1525 .as_dict()
1526 .unwrap()
1527 .get("Msg")
1528 .unwrap()
1529 .as_str_bytes()
1530 .unwrap();
1531 assert_eq!(msg, b"Top secret message", "string decrypted");
1532
1533 let obj4 = doc.get(ObjRef { num: 4, gen: 0 }).unwrap();
1534 let data = doc.stream_data(obj4.as_stream().unwrap()).unwrap();
1535 assert_eq!(data, b"decrypted stream body", "stream decrypted");
1536 }
1537
1538 #[test]
1539 fn document_load_rejects_when_password_does_not_verify() {
1540 use crate::error::Error;
1541 use crate::Document;
1542
1543 let bad_u = vec![0u8; 32];
1546 let err = Document::load(encrypted_fixture(Some(bad_u)));
1547 assert!(matches!(err, Err(Error::Encrypted)));
1548 }
1549
1550 #[test]
1551 fn real_user_password_opens_an_rc4_file() {
1552 use crate::error::Error;
1553 use crate::object::ObjRef;
1554 use crate::Document;
1555
1556 let bytes = encrypted_fixture_with(b"hunter2", b"owner-secret", None);
1557 assert!(
1558 matches!(Document::load(bytes.clone()), Err(Error::Encrypted)),
1559 "without the password the file stays closed"
1560 );
1561 let doc = Document::load_with_password(bytes, "hunter2").expect("user password opens");
1562 let obj3 = doc.get(ObjRef { num: 3, gen: 0 }).unwrap();
1563 let msg = obj3.as_dict().unwrap().get("Msg").unwrap();
1564 assert_eq!(msg.as_str_bytes().unwrap(), b"Top secret message");
1565 }
1566
1567 #[test]
1568 fn owner_password_opens_an_rc4_file() {
1569 use crate::object::ObjRef;
1570 use crate::Document;
1571
1572 let bytes = encrypted_fixture_with(b"hunter2", b"owner-secret", None);
1573 let doc =
1574 Document::load_with_password(bytes, "owner-secret").expect("owner password opens");
1575 let obj3 = doc.get(ObjRef { num: 3, gen: 0 }).unwrap();
1576 let msg = obj3.as_dict().unwrap().get("Msg").unwrap();
1577 assert_eq!(msg.as_str_bytes().unwrap(), b"Top secret message");
1578 }
1579
1580 #[test]
1581 fn wrong_password_stays_encrypted() {
1582 use crate::error::Error;
1583 use crate::Document;
1584
1585 let bytes = encrypted_fixture_with(b"hunter2", b"owner-secret", None);
1586 let err = Document::load_with_password(bytes, "letmein");
1587 assert!(matches!(err, Err(Error::Encrypted)));
1588 }
1589
1590 #[test]
1591 fn real_passwords_open_an_aes256_r6_file() {
1592 use crate::error::Error;
1593 use crate::object::ObjRef;
1594 use crate::Document;
1595
1596 let bytes = encrypted_fixture_aesv3_with(6, "pässword".as_bytes(), b"owner-secret");
1597 assert!(
1598 matches!(Document::load(bytes.clone()), Err(Error::Encrypted)),
1599 "without the password the file stays closed"
1600 );
1601 for pw in ["pässword", "owner-secret"] {
1602 let doc = Document::load_with_password(bytes.clone(), pw)
1603 .unwrap_or_else(|_| panic!("{pw:?} opens the file"));
1604 let obj3 = doc.get(ObjRef { num: 3, gen: 0 }).unwrap();
1605 let msg = obj3.as_dict().unwrap().get("Msg").unwrap();
1606 assert_eq!(msg.as_str_bytes().unwrap(), b"AES-256 secret");
1607 }
1608 assert!(matches!(
1609 Document::load_with_password(bytes, "letmein"),
1610 Err(Error::Encrypted)
1611 ));
1612 }
1613
1614 #[test]
1615 fn empty_password_files_still_open_through_the_password_api() {
1616 use crate::object::ObjRef;
1617 use crate::Document;
1618
1619 let doc = Document::load_with_password(encrypted_fixture(None), "")
1623 .expect("the empty password opens through the password API too");
1624 let obj3 = doc.get(ObjRef { num: 3, gen: 0 }).unwrap();
1625 let msg = obj3.as_dict().unwrap().get("Msg").unwrap();
1626 assert_eq!(msg.as_str_bytes().unwrap(), b"Top secret message");
1627 }
1628
1629 #[test]
1630 fn unsupported_handler_is_declined() {
1631 let mut enc = Dict::new();
1634 enc.insert(Name("Filter".into()), Object::Name(Name("Standard".into())));
1635 enc.insert(Name("V".into()), Object::Int(6));
1636 enc.insert(Name("R".into()), Object::Int(7));
1637 enc.insert(Name("O".into()), Object::String(vec![0; 48]));
1638 enc.insert(Name("U".into()), Object::String(vec![0; 48]));
1639 enc.insert(Name("P".into()), Object::Int(-4));
1640 assert!(Decryptor::from_standard(&enc, ID0).is_none());
1641 }
1642
1643 #[test]
1646 fn aes_fips197_block_vectors() {
1647 let pt: [u8; 16] = [
1649 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
1650 0xee, 0xff,
1651 ];
1652 let key128: Vec<u8> = (0u8..16).collect();
1653 let rks = aes_expand_key(&key128);
1654 let mut b = pt;
1655 aes_encrypt_block(&mut b, &rks);
1656 assert_eq!(hex(&b), "69c4e0d86a7b0430d8cdb78070b4c55a");
1657 aes_decrypt_block(&mut b, &rks, &aes_inv_sbox());
1658 assert_eq!(b, pt, "AES-128 decrypt inverts encrypt");
1659
1660 let key256: Vec<u8> = (0u8..32).collect();
1661 let rks = aes_expand_key(&key256);
1662 let mut b = pt;
1663 aes_encrypt_block(&mut b, &rks);
1664 assert_eq!(hex(&b), "8ea2b7ca516745bfeafc49904b496089");
1665 }
1666
1667 #[test]
1668 fn sha2_vectors() {
1669 assert_eq!(
1670 hex(&sha256(b"abc")),
1671 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
1672 );
1673 assert_eq!(
1674 hex(&sha512(b"abc")),
1675 "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a\
1676 2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
1677 );
1678 assert_eq!(
1679 hex(&sha384(b"abc")),
1680 "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed\
1681 8086072ba1e7cc2358baeca134c825a7"
1682 );
1683 }
1684
1685 fn pkcs7_pad(data: &[u8]) -> Vec<u8> {
1686 let pad = 16 - (data.len() % 16); let mut v = data.to_vec();
1688 v.resize(data.len() + pad, pad as u8);
1689 v
1690 }
1691
1692 #[test]
1693 fn aes_cbc_roundtrip() {
1694 let key: Vec<u8> = (0u8..16).collect();
1695 let iv = [0x24u8; 16];
1696 let pt = b"a message spanning several AES blocks exactly?!!";
1697 let ct = aes_cbc_encrypt_blocks(&key, &iv, &pkcs7_pad(pt));
1698 let mut val = iv.to_vec(); val.extend_from_slice(&ct);
1700 assert_eq!(aes_cbc_decrypt(&key, &val), pt);
1701 }
1702
1703 fn obj_key_aes(key: &[u8], num: u32, gen: u16) -> Vec<u8> {
1706 let mut input = key.to_vec();
1707 input.extend_from_slice(&num.to_le_bytes()[..3]);
1708 input.extend_from_slice(&gen.to_le_bytes()[..2]);
1709 input.extend_from_slice(b"sAlT");
1710 md5(&input)[..(key.len() + 5).min(16)].to_vec()
1711 }
1712
1713 fn aes_encrypt_pdf(key: &[u8], pt: &[u8], iv: &[u8; 16]) -> Vec<u8> {
1716 let mut out = iv.to_vec();
1717 out.extend_from_slice(&aes_cbc_encrypt_blocks(key, iv, &pkcs7_pad(pt)));
1718 out
1719 }
1720
1721 fn encrypted_fixture_aesv2() -> Vec<u8> {
1722 use pdfboss_testkit::PdfBuilder;
1723 let o = owner_entry(b"", b"");
1724 let key = file_key(&o, b""); let u = user_entry(&key);
1726 let iv = [0x11u8; 16];
1727 let msg = aes_encrypt_pdf(&obj_key_aes(&key, 3, 0), b"Top secret message", &iv);
1728 let stream = aes_encrypt_pdf(&obj_key_aes(&key, 4, 0), b"decrypted stream body", &iv);
1729
1730 let mut b = PdfBuilder::new().version(1, 5);
1731 b.object(1, "<< /Type /Catalog /Pages 2 0 R >>");
1732 b.object(2, "<< /Type /Pages /Kids [] /Count 0 >>");
1733 b.object(3, &format!("<< /Msg {} >>", hexstr(&msg)));
1734 b.stream(4, "", &stream);
1735 b.object(
1736 9,
1737 &format!(
1738 "<< /Filter /Standard /V 4 /R 4 /Length 128 /P {P} /O {} /U {} \
1739 /CF << /StdCF << /CFM /AESV2 /Length 16 >> >> /StmF /StdCF /StrF /StdCF >>",
1740 hexstr(&o),
1741 hexstr(&u)
1742 ),
1743 );
1744 let trailer = format!("/Encrypt 9 0 R /ID [{}{}]", hexstr(ID0), hexstr(ID0));
1745 b.trailer_extra(&trailer).build(1)
1746 }
1747
1748 #[test]
1749 fn document_load_decrypts_aesv2() {
1750 use crate::object::ObjRef;
1751 use crate::Document;
1752 let doc = Document::load(encrypted_fixture_aesv2()).expect("AESV2 empty password opens");
1753 let obj3 = doc.get(ObjRef { num: 3, gen: 0 }).unwrap();
1754 let msg = obj3
1755 .as_dict()
1756 .unwrap()
1757 .get("Msg")
1758 .unwrap()
1759 .as_str_bytes()
1760 .unwrap();
1761 assert_eq!(msg, b"Top secret message");
1762 let obj4 = doc.get(ObjRef { num: 4, gen: 0 }).unwrap();
1763 assert_eq!(
1764 doc.stream_data(obj4.as_stream().unwrap()).unwrap(),
1765 b"decrypted stream body"
1766 );
1767 }
1768
1769 fn encrypted_fixture_aesv3(r: i64) -> Vec<u8> {
1772 encrypted_fixture_aesv3_with(r, b"", b"")
1773 }
1774
1775 fn encrypted_fixture_aesv3_with(r: i64, user_pw: &[u8], owner_pw: &[u8]) -> Vec<u8> {
1776 use pdfboss_testkit::PdfBuilder;
1777 let key: Vec<u8> = (0u8..32).map(|i| i ^ 0x5a).collect(); let vsalt: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
1779 let ksalt: [u8; 8] = [9, 10, 11, 12, 13, 14, 15, 16];
1780 let mut u = hash_2b(r, user_pw, &vsalt, &[]); u.extend_from_slice(&vsalt);
1782 u.extend_from_slice(&ksalt);
1783 let intermediate = hash_2b(r, user_pw, &ksalt, &[]);
1784 let ue = aes_cbc_encrypt_blocks(&intermediate, &[0u8; 16], &key);
1785 let ovsalt: [u8; 8] = [21, 22, 23, 24, 25, 26, 27, 28];
1787 let oksalt: [u8; 8] = [31, 32, 33, 34, 35, 36, 37, 38];
1788 let mut o = hash_2b(r, owner_pw, &ovsalt, &u[..48]);
1789 o.extend_from_slice(&ovsalt);
1790 o.extend_from_slice(&oksalt);
1791 let ointermediate = hash_2b(r, owner_pw, &oksalt, &u[..48]);
1792 let oe = aes_cbc_encrypt_blocks(&ointermediate, &[0u8; 16], &key);
1793 let iv = [0x22u8; 16];
1794 let msg = aes_encrypt_pdf(&key, b"AES-256 secret", &iv);
1795 let stream = aes_encrypt_pdf(&key, b"AES-256 stream body", &iv);
1796
1797 let mut b = PdfBuilder::new().version(1, 7);
1798 b.object(1, "<< /Type /Catalog /Pages 2 0 R >>");
1799 b.object(2, "<< /Type /Pages /Kids [] /Count 0 >>");
1800 b.object(3, &format!("<< /Msg {} >>", hexstr(&msg)));
1801 b.stream(4, "", &stream);
1802 b.object(
1803 9,
1804 &format!(
1805 "<< /Filter /Standard /V 5 /R {r} /Length 256 /P {P} /U {} /UE {} \
1806 /O {} /OE {} \
1807 /CF << /StdCF << /CFM /AESV3 /Length 32 >> >> /StmF /StdCF /StrF /StdCF >>",
1808 hexstr(&u),
1809 hexstr(&ue),
1810 hexstr(&o),
1811 hexstr(&oe)
1812 ),
1813 );
1814 let trailer = format!("/Encrypt 9 0 R /ID [{}{}]", hexstr(ID0), hexstr(ID0));
1815 b.trailer_extra(&trailer).build(1)
1816 }
1817
1818 fn assert_aesv3_decrypts(r: i64) {
1819 use crate::object::ObjRef;
1820 use crate::Document;
1821 let doc = Document::load(encrypted_fixture_aesv3(r)).expect("AESV3 empty password opens");
1822 let obj3 = doc.get(ObjRef { num: 3, gen: 0 }).unwrap();
1823 let msg = obj3
1824 .as_dict()
1825 .unwrap()
1826 .get("Msg")
1827 .unwrap()
1828 .as_str_bytes()
1829 .unwrap();
1830 assert_eq!(msg, b"AES-256 secret", "R{r} string");
1831 let obj4 = doc.get(ObjRef { num: 4, gen: 0 }).unwrap();
1832 assert_eq!(
1833 doc.stream_data(obj4.as_stream().unwrap()).unwrap(),
1834 b"AES-256 stream body",
1835 "R{r} stream"
1836 );
1837 }
1838
1839 #[test]
1840 fn document_load_decrypts_aesv3_r5() {
1841 assert_aesv3_decrypts(5);
1842 }
1843
1844 #[test]
1845 fn document_load_decrypts_aesv3_r6() {
1846 assert_aesv3_decrypts(6); }
1848}