1use crate::object::{Dict, Name, ObjRef, Object};
25
26const PAD: [u8; 32] = [
28 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
29 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A,
30];
31
32#[derive(Clone, Copy, PartialEq, Debug)]
34enum Cipher {
35 Identity,
38 Rc4,
40 Aesv2,
42 Aesv3,
44}
45
46#[derive(Clone)]
48pub struct Decryptor {
49 key: Vec<u8>,
51 filters: CryptFilters,
53 encrypt_metadata: bool,
57}
58
59#[derive(Clone)]
64struct CryptFilters {
65 named: Vec<(String, Cipher)>,
69 stream: Cipher,
71 string: Cipher,
73 embedded_file: Cipher,
75}
76
77impl CryptFilters {
78 fn uniform(cipher: Cipher) -> CryptFilters {
80 CryptFilters {
81 named: Vec::new(),
82 stream: cipher,
83 string: cipher,
84 embedded_file: cipher,
85 }
86 }
87
88 fn parse(enc: &Dict) -> Option<CryptFilters> {
97 let named: Vec<(String, Cipher)> = enc
98 .get_dict("CF")
99 .into_iter()
100 .flat_map(Dict::iter)
101 .filter(|(name, _)| name.0 != "Identity")
102 .filter_map(|(name, filter)| Some((name.0.clone(), cipher_method(filter.as_dict()?)?)))
103 .collect();
104 let filters = CryptFilters {
105 named,
106 stream: Cipher::Identity,
107 string: Cipher::Identity,
108 embedded_file: Cipher::Identity,
109 };
110 let pick = |key: &str, default: Cipher| match enc.get_name(key) {
111 None => Some(default),
112 Some(n) => filters.named(&n.0),
113 };
114 let stream = pick("StmF", Cipher::Identity)?;
115 let string = pick("StrF", Cipher::Identity)?;
116 let embedded_file = pick("EFF", stream)?;
117 Some(CryptFilters {
118 stream,
119 string,
120 embedded_file,
121 ..filters
122 })
123 }
124
125 fn named(&self, name: &str) -> Option<Cipher> {
129 if name == "Identity" {
130 return Some(Cipher::Identity);
131 }
132 self.named
133 .iter()
134 .find(|(n, _)| n == name)
135 .map(|(_, cipher)| *cipher)
136 }
137}
138
139fn stream_crypt_filter(dict: &Dict) -> Option<String> {
148 let first = match dict.get("Filter")? {
149 Object::Name(n) => n,
150 Object::Array(items) => items.first()?.as_name()?,
151 _ => return None,
152 };
153 if first.0 != "Crypt" {
154 return None;
155 }
156 let parms = match dict.get("DecodeParms") {
157 Some(Object::Dict(d)) => Some(d),
158 Some(Object::Array(items)) => items.first().and_then(Object::as_dict),
159 _ => None,
160 };
161 let name = parms
162 .and_then(|p| p.get_name("Name"))
163 .map_or("Identity", |n| n.0.as_str());
164 Some(name.to_string())
165}
166
167pub fn crypt_filter_refs(enc: &Dict) -> Vec<ObjRef> {
185 match enc.get("CF") {
186 Some(Object::Ref(r)) => vec![*r],
187 Some(Object::Dict(cf)) => cf.iter().filter_map(|(_, v)| v.as_ref()).collect(),
188 _ => Vec::new(),
189 }
190}
191
192pub fn direct_crypt_filters(enc: &Dict, mut lookup: impl FnMut(ObjRef) -> Option<Object>) -> Dict {
207 let mut out = enc.clone();
208 let cf = match out.get("CF") {
209 Some(Object::Ref(r)) => lookup(*r),
210 Some(Object::Dict(cf)) => Some(Object::Dict(cf.clone())),
211 _ => None,
212 };
213 let Some(Object::Dict(mut cf)) = cf else {
214 return out;
215 };
216 for value in cf.values_mut() {
217 if let Object::Ref(r) = *value {
218 if let Some(direct) = lookup(r) {
219 *value = direct;
220 }
221 }
222 }
223 out.insert(Name("CF".to_string()), Object::Dict(cf));
224 out
225}
226
227fn cipher_method(filter: &Dict) -> Option<Cipher> {
233 match filter.get_name("CFM")?.0.as_str() {
234 "V2" => Some(Cipher::Rc4),
235 "AESV2" => Some(Cipher::Aesv2),
236 "AESV3" => Some(Cipher::Aesv3),
237 _ => None,
238 }
239}
240
241fn v4_key_length(enc: &Dict) -> usize {
248 let filter_length = ["StmF", "StrF"].iter().find_map(|key| {
249 let name = enc.get_name(key)?;
250 enc.get_dict("CF")?.get_dict(&name.0)?.get_int("Length")
251 });
252 let bytes = match (enc.get_int("Length"), filter_length) {
253 (Some(bits), _) => bits / 8,
254 (None, Some(len)) if len >= 40 => len / 8,
255 (None, Some(len)) => len,
256 (None, None) => 16,
257 };
258 bytes.clamp(5, 16) as usize
259}
260
261fn encrypt_metadata_flag(enc: &Dict) -> bool {
266 enc.get("EncryptMetadata")
267 .and_then(Object::as_bool)
268 .unwrap_or(true)
269}
270
271impl Decryptor {
272 pub fn from_standard(enc: &Dict, id0: &[u8]) -> Option<Decryptor> {
290 Decryptor::from_standard_with_password(enc, id0, b"")
291 }
292
293 pub fn from_standard_with_password_str(
298 enc: &Dict,
299 id0: &[u8],
300 password: &str,
301 ) -> Option<Decryptor> {
302 let dec = Decryptor::from_standard_with_password(enc, id0, password.as_bytes());
303 if dec.is_some() || password.is_ascii() || password.chars().any(|c| (c as u32) > 255) {
304 return dec;
305 }
306 let latin1: Vec<u8> = password.chars().map(|c| c as u8).collect();
307 Decryptor::from_standard_with_password(enc, id0, &latin1)
308 }
309
310 pub fn from_standard_with_password(
318 enc: &Dict,
319 id0: &[u8],
320 password: &[u8],
321 ) -> Option<Decryptor> {
322 if enc.get_name("Filter").map(|n| n.0.as_str()) != Some("Standard") {
323 return None;
324 }
325 let v = enc.get_int("V").unwrap_or(0);
326 let r = enc.get_int("R").unwrap_or(0);
327 let encrypt_metadata = encrypt_metadata_flag(enc);
328 let (key, filters) = match (v, r) {
329 (1 | 2, 2 | 3) => {
331 let n = if v == 1 {
332 5
333 } else {
334 (enc.get_int("Length").unwrap_or(40) / 8).clamp(5, 16) as usize
335 };
336 let key = rc4_family_key(enc, id0, r, n, password)?;
337 (key, CryptFilters::uniform(Cipher::Rc4))
338 }
339 (4, 4) => {
342 let filters = CryptFilters::parse(enc)?;
343 let key = rc4_family_key(enc, id0, r, v4_key_length(enc), password)?;
344 (key, filters)
345 }
346 (5, 5 | 6) => {
349 let filters = CryptFilters::parse(enc)?;
350 let key = aesv3_key(enc, r, password)?;
351 (key, filters)
352 }
353 _ => return None,
354 };
355 Some(Decryptor {
356 key,
357 filters,
358 encrypt_metadata,
359 })
360 }
361
362 pub fn decrypt_object(&self, obj: &mut Object, num: u32, gen: u16) {
379 self.decrypt_in_place(obj, num, gen);
380 }
381
382 fn decrypt_in_place(&self, obj: &mut Object, num: u32, gen: u16) {
395 match obj {
396 Object::String(bytes) => self.apply(self.filters.string, num, gen, bytes),
397 Object::Array(items) => items
398 .iter_mut()
399 .for_each(|it| self.decrypt_in_place(it, num, gen)),
400 Object::Dict(dict) => dict
401 .values_mut()
402 .for_each(|v| self.decrypt_in_place(v, num, gen)),
403 Object::Stream(stream) => {
404 stream
405 .dict
406 .values_mut()
407 .for_each(|v| self.decrypt_in_place(v, num, gen));
408 if !self.encrypt_metadata && is_metadata_stream(&stream.dict) {
409 return;
410 }
411 if let Some(name) = stream_crypt_filter(&stream.dict) {
412 match self.filters.named(&name) {
413 Some(Cipher::Identity) | None => {}
414 Some(cipher) => {
415 stream.data = decrypt_bytes(cipher, &self.key, &stream.data)
416 }
417 }
418 return;
419 }
420 let cipher = if is_embedded_file_stream(&stream.dict) {
421 self.filters.embedded_file
422 } else {
423 self.filters.stream
424 };
425 self.apply(cipher, num, gen, &mut stream.data);
426 }
427 _ => {}
428 }
429 }
430
431 fn apply(&self, cipher: Cipher, num: u32, gen: u16, data: &mut Vec<u8>) {
435 let key = match cipher {
436 Cipher::Identity => return,
437 Cipher::Aesv3 => self.key.clone(), Cipher::Rc4 | Cipher::Aesv2 => self.object_key(cipher, num, gen),
439 };
440 *data = decrypt_bytes(cipher, &key, data);
441 }
442
443 fn object_key(&self, cipher: Cipher, num: u32, gen: u16) -> Vec<u8> {
450 let mut input = Vec::with_capacity(self.key.len() + 9);
451 input.extend_from_slice(&self.key);
452 input.extend_from_slice(&num.to_le_bytes()[..3]);
453 input.extend_from_slice(&gen.to_le_bytes()[..2]);
454 if cipher == Cipher::Aesv2 {
455 input.extend_from_slice(b"sAlT");
456 }
457 let digest = md5(&input);
458 let n = match cipher {
459 Cipher::Aesv2 => 16,
460 _ => (self.key.len() + 5).min(16),
461 };
462 digest[..n].to_vec()
463 }
464}
465
466fn is_metadata_stream(dict: &Dict) -> bool {
468 dict.get_name("Type").map(|n| n.0.as_str()) == Some("Metadata")
469}
470
471fn is_embedded_file_stream(dict: &Dict) -> bool {
473 dict.get_name("Type").map(|n| n.0.as_str()) == Some("EmbeddedFile")
474}
475
476fn decrypt_bytes(cipher: Cipher, key: &[u8], data: &[u8]) -> Vec<u8> {
478 match cipher {
479 Cipher::Identity => data.to_vec(),
480 Cipher::Rc4 => rc4(key, data),
481 Cipher::Aesv2 | Cipher::Aesv3 => aes_cbc_decrypt(key, data),
482 }
483}
484
485fn pad_password(password: &[u8]) -> [u8; 32] {
491 let mut out = [0u8; 32];
492 let n = password.len().min(32);
493 out[..n].copy_from_slice(&password[..n]);
494 out[n..].copy_from_slice(&PAD[..32 - n]);
495 out
496}
497
498fn rc4_family_key(enc: &Dict, id0: &[u8], r: i64, n: usize, password: &[u8]) -> Option<Vec<u8>> {
505 let u = enc.get("U").and_then(Object::as_str_bytes)?;
506 if let Some(key) = md5_file_key(enc, id0, r, n, &pad_password(password)) {
507 if verify_user_password(&key, r, id0, u) {
508 return Some(key);
509 }
510 }
511 let o = enc.get("O").and_then(Object::as_str_bytes)?;
515 if o.len() < 32 {
516 return None;
517 }
518 let mut d = md5(&pad_password(password));
519 if r >= 3 {
520 for _ in 0..50 {
521 d = md5(&d[..n]);
522 }
523 }
524 let okey = &d[..n];
525 let recovered = if r == 2 {
526 rc4(okey, &o[..32])
527 } else {
528 let mut x = o[..32].to_vec();
529 for i in (1u8..=19).rev() {
530 let keyed: Vec<u8> = okey.iter().map(|b| b ^ i).collect();
531 x = rc4(&keyed, &x);
532 }
533 rc4(okey, &x)
534 };
535 let padded: [u8; 32] = recovered.get(..32)?.try_into().ok()?;
536 let key = md5_file_key(enc, id0, r, n, &padded)?;
537 verify_user_password(&key, r, id0, u).then_some(key)
538}
539
540fn md5_file_key(enc: &Dict, id0: &[u8], r: i64, n: usize, padded: &[u8; 32]) -> Option<Vec<u8>> {
544 let o = enc.get("O").and_then(Object::as_str_bytes)?;
545 if o.len() < 32 {
546 return None;
547 }
548 let p = enc.get_int("P")?;
549 let mut input = Vec::with_capacity(32 + 32 + 4 + id0.len() + 4);
550 input.extend_from_slice(padded);
551 input.extend_from_slice(&o[..32]);
552 input.extend_from_slice(&(p as i32 as u32).to_le_bytes()); input.extend_from_slice(id0);
554 if r >= 4 && !encrypt_metadata_flag(enc) {
556 input.extend_from_slice(&[0xFF, 0xFF, 0xFF, 0xFF]);
557 }
558 let mut digest = md5(&input);
559 if r >= 3 {
560 for _ in 0..50 {
561 digest = md5(&digest[..n]);
562 }
563 }
564 Some(digest[..n].to_vec())
565}
566
567fn verify_user_password(key: &[u8], r: i64, id0: &[u8], u: &[u8]) -> bool {
571 if r == 2 {
572 let computed = rc4(key, &PAD);
574 u.len() >= 32 && computed == u[..32]
575 } else {
576 let mut input = Vec::with_capacity(32 + id0.len());
578 input.extend_from_slice(&PAD);
579 input.extend_from_slice(id0);
580 let mut x = md5(&input).to_vec();
581 x = rc4(key, &x);
582 for i in 1u8..=19 {
583 let keyed: Vec<u8> = key.iter().map(|b| b ^ i).collect();
584 x = rc4(&keyed, &x);
585 }
586 u.len() >= 16 && x[..16] == u[..16]
588 }
589}
590
591fn rc4(key: &[u8], data: &[u8]) -> Vec<u8> {
593 debug_assert!(!key.is_empty());
594 let mut s: [u8; 256] = core::array::from_fn(|i| i as u8);
595 let mut j = 0u8;
596 for i in 0..256 {
597 j = j.wrapping_add(s[i]).wrapping_add(key[i % key.len()]);
598 s.swap(i, j as usize);
599 }
600 let mut out = Vec::with_capacity(data.len());
601 let (mut i, mut j) = (0u8, 0u8);
602 for &byte in data {
603 i = i.wrapping_add(1);
604 j = j.wrapping_add(s[i as usize]);
605 s.swap(i as usize, j as usize);
606 let k = s[s[i as usize].wrapping_add(s[j as usize]) as usize];
607 out.push(byte ^ k);
608 }
609 out
610}
611
612#[rustfmt::skip]
616const AES_SBOX: [u8; 256] = [
617 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
618 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
619 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
620 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
621 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
622 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
623 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
624 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
625 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
626 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
627 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
628 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
629 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
630 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
631 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
632 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16,
633];
634
635const AES_RCON: [u8; 11] = [
637 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
638];
639
640fn aes_inv_sbox() -> [u8; 256] {
642 let mut inv = [0u8; 256];
643 for (i, &s) in AES_SBOX.iter().enumerate() {
644 inv[s as usize] = i as u8;
645 }
646 inv
647}
648
649fn gmul(mut a: u8, mut b: u8) -> u8 {
651 let mut p = 0u8;
652 for _ in 0..8 {
653 if b & 1 != 0 {
654 p ^= a;
655 }
656 let hi = a & 0x80;
657 a <<= 1;
658 if hi != 0 {
659 a ^= 0x1b;
660 }
661 b >>= 1;
662 }
663 p
664}
665
666fn aes_expand_key(key: &[u8]) -> Vec<[u8; 16]> {
669 let nk = key.len() / 4; let nr = nk + 6;
671 let total = 4 * (nr + 1);
672 let mut w: Vec<[u8; 4]> = Vec::with_capacity(total);
673 for i in 0..nk {
674 w.push([key[4 * i], key[4 * i + 1], key[4 * i + 2], key[4 * i + 3]]);
675 }
676 for i in nk..total {
677 let mut t = w[i - 1];
678 if i.is_multiple_of(nk) {
679 t = [t[1], t[2], t[3], t[0]]; for b in &mut t {
681 *b = AES_SBOX[*b as usize]; }
683 t[0] ^= AES_RCON[i / nk];
684 } else if nk > 6 && i % nk == 4 {
685 for b in &mut t {
686 *b = AES_SBOX[*b as usize];
687 }
688 }
689 let prev = w[i - nk];
690 w.push([
691 prev[0] ^ t[0],
692 prev[1] ^ t[1],
693 prev[2] ^ t[2],
694 prev[3] ^ t[3],
695 ]);
696 }
697 (0..=nr)
698 .map(|round| {
699 let mut rk = [0u8; 16];
700 for c in 0..4 {
701 rk[4 * c..4 * c + 4].copy_from_slice(&w[4 * round + c]);
702 }
703 rk
704 })
705 .collect()
706}
707
708fn add_round_key(s: &mut [u8; 16], rk: &[u8; 16]) {
709 for (b, k) in s.iter_mut().zip(rk) {
710 *b ^= k;
711 }
712}
713
714fn shift_rows(s: &mut [u8; 16]) {
715 let o = *s;
716 for r in 1..4 {
717 for c in 0..4 {
718 s[r + 4 * c] = o[r + 4 * ((c + r) % 4)];
719 }
720 }
721}
722
723fn inv_shift_rows(s: &mut [u8; 16]) {
724 let o = *s;
725 for r in 1..4 {
726 for c in 0..4 {
727 s[r + 4 * c] = o[r + 4 * ((c + 4 - r) % 4)];
728 }
729 }
730}
731
732fn mix_columns(s: &mut [u8; 16]) {
733 for c in 0..4 {
734 let i = 4 * c;
735 let (a0, a1, a2, a3) = (s[i], s[i + 1], s[i + 2], s[i + 3]);
736 s[i] = gmul(a0, 2) ^ gmul(a1, 3) ^ a2 ^ a3;
737 s[i + 1] = a0 ^ gmul(a1, 2) ^ gmul(a2, 3) ^ a3;
738 s[i + 2] = a0 ^ a1 ^ gmul(a2, 2) ^ gmul(a3, 3);
739 s[i + 3] = gmul(a0, 3) ^ a1 ^ a2 ^ gmul(a3, 2);
740 }
741}
742
743fn inv_mix_columns(s: &mut [u8; 16]) {
744 for c in 0..4 {
745 let i = 4 * c;
746 let (a0, a1, a2, a3) = (s[i], s[i + 1], s[i + 2], s[i + 3]);
747 s[i] = gmul(a0, 14) ^ gmul(a1, 11) ^ gmul(a2, 13) ^ gmul(a3, 9);
748 s[i + 1] = gmul(a0, 9) ^ gmul(a1, 14) ^ gmul(a2, 11) ^ gmul(a3, 13);
749 s[i + 2] = gmul(a0, 13) ^ gmul(a1, 9) ^ gmul(a2, 14) ^ gmul(a3, 11);
750 s[i + 3] = gmul(a0, 11) ^ gmul(a1, 13) ^ gmul(a2, 9) ^ gmul(a3, 14);
751 }
752}
753
754fn aes_encrypt_block(s: &mut [u8; 16], rks: &[[u8; 16]]) {
755 #[cfg(target_arch = "aarch64")]
756 if std::arch::is_aarch64_feature_detected!("aes") {
757 unsafe { aes_hw::encrypt_block(s, rks) };
759 return;
760 }
761 #[cfg(target_arch = "x86_64")]
762 if std::arch::is_x86_feature_detected!("aes") {
763 unsafe { aes_hw::encrypt_block(s, rks) };
765 return;
766 }
767 aes_encrypt_block_soft(s, rks);
768}
769
770fn aes_encrypt_block_soft(s: &mut [u8; 16], rks: &[[u8; 16]]) {
772 let nr = rks.len() - 1;
773 add_round_key(s, &rks[0]);
774 for rk in &rks[1..nr] {
775 s.iter_mut().for_each(|b| *b = AES_SBOX[*b as usize]);
776 shift_rows(s);
777 mix_columns(s);
778 add_round_key(s, rk);
779 }
780 s.iter_mut().for_each(|b| *b = AES_SBOX[*b as usize]);
781 shift_rows(s);
782 add_round_key(s, &rks[nr]);
783}
784
785fn aes_decrypt_block(s: &mut [u8; 16], rks: &[[u8; 16]], inv_sbox: &[u8; 256]) {
786 #[cfg(target_arch = "aarch64")]
787 if std::arch::is_aarch64_feature_detected!("aes") {
788 unsafe { aes_hw::decrypt_block(s, rks) };
790 return;
791 }
792 #[cfg(target_arch = "x86_64")]
793 if std::arch::is_x86_feature_detected!("aes") {
794 unsafe { aes_hw::decrypt_block(s, rks) };
796 return;
797 }
798 aes_decrypt_block_soft(s, rks, inv_sbox);
799}
800
801fn aes_decrypt_block_soft(s: &mut [u8; 16], rks: &[[u8; 16]], inv_sbox: &[u8; 256]) {
803 let nr = rks.len() - 1;
804 add_round_key(s, &rks[nr]);
805 for rk in rks[1..nr].iter().rev() {
806 inv_shift_rows(s);
807 s.iter_mut().for_each(|b| *b = inv_sbox[*b as usize]);
808 add_round_key(s, rk);
809 inv_mix_columns(s);
810 }
811 inv_shift_rows(s);
812 s.iter_mut().for_each(|b| *b = inv_sbox[*b as usize]);
813 add_round_key(s, &rks[0]);
814}
815
816#[cfg(target_arch = "aarch64")]
824mod aes_hw {
825 use core::arch::aarch64::{
826 vaesdq_u8, vaeseq_u8, vaesimcq_u8, vaesmcq_u8, veorq_u8, vld1q_u8, vmovq_n_u8, vst1q_u8,
827 };
828
829 #[target_feature(enable = "aes")]
832 pub unsafe fn encrypt_block(s: &mut [u8; 16], rks: &[[u8; 16]]) {
833 let nr = rks.len() - 1;
834 let mut x = vld1q_u8(s.as_ptr());
838 for rk in &rks[..nr - 1] {
839 x = vaesmcq_u8(vaeseq_u8(x, vld1q_u8(rk.as_ptr())));
840 }
841 x = vaeseq_u8(x, vld1q_u8(rks[nr - 1].as_ptr()));
842 x = veorq_u8(x, vld1q_u8(rks[nr].as_ptr()));
843 vst1q_u8(s.as_mut_ptr(), x);
844 }
845
846 #[target_feature(enable = "aes")]
849 pub unsafe fn decrypt_block(s: &mut [u8; 16], rks: &[[u8; 16]]) {
850 let nr = rks.len() - 1;
851 let zero = vmovq_n_u8(0);
855 let mut x = vld1q_u8(s.as_ptr());
856 x = veorq_u8(x, vld1q_u8(rks[nr].as_ptr()));
857 for rk in rks[1..nr].iter().rev() {
858 x = vaesdq_u8(x, zero);
859 x = veorq_u8(x, vld1q_u8(rk.as_ptr()));
860 x = vaesimcq_u8(x);
861 }
862 x = vaesdq_u8(x, zero);
863 x = veorq_u8(x, vld1q_u8(rks[0].as_ptr()));
864 vst1q_u8(s.as_mut_ptr(), x);
865 }
866}
867
868#[cfg(target_arch = "x86_64")]
870mod aes_hw {
871 use core::arch::x86_64::{
872 __m128i, _mm_aesdec_si128, _mm_aesdeclast_si128, _mm_aesenc_si128, _mm_aesenclast_si128,
873 _mm_aesimc_si128, _mm_loadu_si128, _mm_storeu_si128, _mm_xor_si128,
874 };
875
876 #[target_feature(enable = "aes")]
879 pub unsafe fn encrypt_block(s: &mut [u8; 16], rks: &[[u8; 16]]) {
880 let nr = rks.len() - 1;
881 let mut x = _mm_loadu_si128(s.as_ptr().cast::<__m128i>());
882 x = _mm_xor_si128(x, _mm_loadu_si128(rks[0].as_ptr().cast::<__m128i>()));
883 for rk in &rks[1..nr] {
884 x = _mm_aesenc_si128(x, _mm_loadu_si128(rk.as_ptr().cast::<__m128i>()));
885 }
886 x = _mm_aesenclast_si128(x, _mm_loadu_si128(rks[nr].as_ptr().cast::<__m128i>()));
887 _mm_storeu_si128(s.as_mut_ptr().cast::<__m128i>(), x);
888 }
889
890 #[target_feature(enable = "aes")]
893 pub unsafe fn decrypt_block(s: &mut [u8; 16], rks: &[[u8; 16]]) {
894 let nr = rks.len() - 1;
895 let mut x = _mm_loadu_si128(s.as_ptr().cast::<__m128i>());
898 x = _mm_xor_si128(x, _mm_loadu_si128(rks[nr].as_ptr().cast::<__m128i>()));
899 for rk in rks[1..nr].iter().rev() {
900 let dk = _mm_aesimc_si128(_mm_loadu_si128(rk.as_ptr().cast::<__m128i>()));
901 x = _mm_aesdec_si128(x, dk);
902 }
903 x = _mm_aesdeclast_si128(x, _mm_loadu_si128(rks[0].as_ptr().cast::<__m128i>()));
904 _mm_storeu_si128(s.as_mut_ptr().cast::<__m128i>(), x);
905 }
906}
907
908fn aes_cbc_decrypt_blocks(key: &[u8], iv: &[u8], data: &[u8]) -> Vec<u8> {
911 if !matches!(key.len(), 16 | 32) {
914 return Vec::new();
915 }
916 if data.is_empty() || !data.len().is_multiple_of(16) || iv.len() < 16 {
917 return Vec::new();
918 }
919 let rks = aes_expand_key(key);
920 let inv_sbox = aes_inv_sbox();
921 let mut prev = [0u8; 16];
922 prev.copy_from_slice(&iv[..16]);
923 let mut out = Vec::with_capacity(data.len());
924 for chunk in data.as_chunks::<16>().0 {
925 let mut block = [0u8; 16];
926 block.copy_from_slice(chunk);
927 let cipher = block;
928 aes_decrypt_block(&mut block, &rks, &inv_sbox);
929 for (b, p) in block.iter_mut().zip(&prev) {
930 *b ^= p;
931 }
932 out.extend_from_slice(&block);
933 prev = cipher;
934 }
935 out
936}
937
938fn aes_cbc_encrypt_blocks(key: &[u8], iv: &[u8], data: &[u8]) -> Vec<u8> {
941 let rks = aes_expand_key(key);
942 let mut prev = [0u8; 16];
943 prev.copy_from_slice(&iv[..16]);
944 let mut out = Vec::with_capacity(data.len());
945 for chunk in data.as_chunks::<16>().0 {
946 let mut block = [0u8; 16];
947 for ((b, c), p) in block.iter_mut().zip(chunk).zip(&prev) {
948 *b = c ^ p;
949 }
950 aes_encrypt_block(&mut block, &rks);
951 out.extend_from_slice(&block);
952 prev = block;
953 }
954 out
955}
956
957fn aes_cbc_decrypt(key: &[u8], data: &[u8]) -> Vec<u8> {
961 if data.len() < 16 {
962 return Vec::new();
963 }
964 let (iv, ct) = data.split_at(16);
965 let mut out = aes_cbc_decrypt_blocks(key, iv, ct);
966 strip_pkcs7(&mut out);
967 out
968}
969
970fn strip_pkcs7(data: &mut Vec<u8>) {
972 let Some(&pad) = data.last() else {
973 return;
974 };
975 let pad = pad as usize;
976 if (1..=16).contains(&pad) && pad <= data.len() {
977 let start = data.len() - pad;
978 if data[start..].iter().all(|&b| b as usize == pad) {
979 data.truncate(start);
980 }
981 }
982}
983
984fn pkcs7_pad(data: &[u8]) -> Vec<u8> {
988 let pad = 16 - data.len() % 16;
989 let mut out = data.to_vec();
990 out.resize(data.len() + pad, pad as u8);
991 out
992}
993
994fn aes_cbc_encrypt(key: &[u8], rng: &mut dyn FnMut(&mut [u8]), data: &[u8]) -> Vec<u8> {
998 let mut iv = [0u8; 16];
999 rng(&mut iv);
1000 let mut out = iv.to_vec();
1001 out.extend_from_slice(&aes_cbc_encrypt_blocks(key, &iv, &pkcs7_pad(data)));
1002 out
1003}
1004
1005#[rustfmt::skip]
1008const SHA256_K: [u32; 64] = [
1009 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
1010 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
1011 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
1012 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
1013 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
1014 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
1015 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
1016 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
1017];
1018
1019#[derive(Debug, Clone)]
1024pub struct Sha256 {
1025 h: [u32; 8],
1026 tail: [u8; 64],
1027 tail_len: usize,
1028 total: u64,
1029}
1030
1031impl Default for Sha256 {
1032 fn default() -> Sha256 {
1033 Sha256::new()
1034 }
1035}
1036
1037impl Sha256 {
1038 pub fn new() -> Sha256 {
1040 Sha256 {
1041 h: [
1042 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
1043 0x5be0cd19,
1044 ],
1045 tail: [0u8; 64],
1046 tail_len: 0,
1047 total: 0,
1048 }
1049 }
1050
1051 pub fn update(&mut self, input: &[u8]) {
1056 self.total = self.total.wrapping_add(input.len() as u64);
1057 let mut input = input;
1058 if self.tail_len > 0 {
1059 let take = input.len().min(64 - self.tail_len);
1060 self.tail[self.tail_len..self.tail_len + take].copy_from_slice(&input[..take]);
1061 self.tail_len += take;
1062 input = &input[take..];
1063 if self.tail_len < 64 {
1064 return;
1065 }
1066 let block = self.tail;
1067 sha256_compress(&mut self.h, &block);
1068 self.tail_len = 0;
1069 }
1070 let (blocks, rest) = input.as_chunks::<64>();
1071 for block in blocks {
1072 sha256_compress(&mut self.h, block);
1073 }
1074 self.tail[..rest.len()].copy_from_slice(rest);
1075 self.tail_len = rest.len();
1076 }
1077
1078 pub fn finalize(mut self) -> [u8; 32] {
1080 let mut pad = [0u8; 128];
1083 pad[..self.tail_len].copy_from_slice(&self.tail[..self.tail_len]);
1084 pad[self.tail_len] = 0x80;
1085 let padded = if self.tail_len < 56 { 64 } else { 128 };
1086 let bitlen = self.total.wrapping_mul(8);
1087 pad[padded - 8..padded].copy_from_slice(&bitlen.to_be_bytes());
1088 for block in pad[..padded].as_chunks::<64>().0 {
1089 sha256_compress(&mut self.h, block);
1090 }
1091 let mut out = [0u8; 32];
1092 for (i, word) in self.h.iter().enumerate() {
1093 out[4 * i..4 * i + 4].copy_from_slice(&word.to_be_bytes());
1094 }
1095 out
1096 }
1097}
1098
1099pub fn sha256(input: &[u8]) -> [u8; 32] {
1101 let mut hasher = Sha256::new();
1102 hasher.update(input);
1103 hasher.finalize()
1104}
1105
1106fn sha256_compress(h: &mut [u32; 8], block: &[u8; 64]) {
1107 #[cfg(target_arch = "aarch64")]
1108 if std::arch::is_aarch64_feature_detected!("sha2") {
1109 unsafe { sha_hw::compress256(h, block) };
1111 return;
1112 }
1113 sha256_compress_soft(h, block);
1114}
1115
1116fn sha256_compress_soft(h: &mut [u32; 8], block: &[u8; 64]) {
1118 let mut w = [0u32; 64];
1119 for (word, bytes) in w.iter_mut().zip(block.as_chunks::<4>().0) {
1120 *word = u32::from_be_bytes(*bytes);
1121 }
1122 for i in 16..64 {
1123 let s0 = w[i - 15].rotate_right(7) ^ w[i - 15].rotate_right(18) ^ (w[i - 15] >> 3);
1124 let s1 = w[i - 2].rotate_right(17) ^ w[i - 2].rotate_right(19) ^ (w[i - 2] >> 10);
1125 w[i] = w[i - 16]
1126 .wrapping_add(s0)
1127 .wrapping_add(w[i - 7])
1128 .wrapping_add(s1);
1129 }
1130 let [mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut hh] = *h;
1131 for (k, wi) in SHA256_K.iter().zip(&w) {
1132 let s1 = e.rotate_right(6) ^ e.rotate_right(11) ^ e.rotate_right(25);
1133 let ch = (e & f) ^ ((!e) & g);
1134 let t1 = hh
1135 .wrapping_add(s1)
1136 .wrapping_add(ch)
1137 .wrapping_add(*k)
1138 .wrapping_add(*wi);
1139 let s0 = a.rotate_right(2) ^ a.rotate_right(13) ^ a.rotate_right(22);
1140 let maj = (a & b) ^ (a & c) ^ (b & c);
1141 let t2 = s0.wrapping_add(maj);
1142 hh = g;
1143 g = f;
1144 f = e;
1145 e = d.wrapping_add(t1);
1146 d = c;
1147 c = b;
1148 b = a;
1149 a = t1.wrapping_add(t2);
1150 }
1151 for (hv, v) in h.iter_mut().zip([a, b, c, d, e, f, g, hh]) {
1152 *hv = hv.wrapping_add(v);
1153 }
1154}
1155
1156#[rustfmt::skip]
1157const SHA512_K: [u64; 80] = [
1158 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
1159 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
1160 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
1161 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
1162 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
1163 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
1164 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
1165 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
1166 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
1167 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
1168 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
1169 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
1170 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
1171 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
1172 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
1173 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
1174 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
1175 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
1176 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
1177 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
1178];
1179
1180fn sha512_core(input: &[u8], mut h: [u64; 8]) -> [u64; 8] {
1181 let (blocks, tail) = input.as_chunks::<128>();
1182 for block in blocks {
1183 sha512_compress(&mut h, block);
1184 }
1185 let mut pad = [0u8; 256];
1189 pad[..tail.len()].copy_from_slice(tail);
1190 pad[tail.len()] = 0x80;
1191 let padded = if tail.len() < 112 { 128 } else { 256 };
1192 let bitlen = (input.len() as u128).wrapping_mul(8);
1193 pad[padded - 16..padded].copy_from_slice(&bitlen.to_be_bytes());
1194 for block in pad[..padded].as_chunks::<128>().0 {
1195 sha512_compress(&mut h, block);
1196 }
1197 h
1198}
1199
1200fn sha512_compress(h: &mut [u64; 8], block: &[u8; 128]) {
1201 #[cfg(target_arch = "aarch64")]
1202 if std::arch::is_aarch64_feature_detected!("sha3") {
1203 unsafe { sha_hw::compress512(h, block) };
1206 return;
1207 }
1208 sha512_compress_soft(h, block);
1209}
1210
1211fn sha512_compress_soft(h: &mut [u64; 8], block: &[u8; 128]) {
1213 let mut w = [0u64; 80];
1214 for (word, bytes) in w.iter_mut().zip(block.as_chunks::<8>().0) {
1215 *word = u64::from_be_bytes(*bytes);
1216 }
1217 for i in 16..80 {
1218 let s0 = w[i - 15].rotate_right(1) ^ w[i - 15].rotate_right(8) ^ (w[i - 15] >> 7);
1219 let s1 = w[i - 2].rotate_right(19) ^ w[i - 2].rotate_right(61) ^ (w[i - 2] >> 6);
1220 w[i] = w[i - 16]
1221 .wrapping_add(s0)
1222 .wrapping_add(w[i - 7])
1223 .wrapping_add(s1);
1224 }
1225 let [mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut hh] = *h;
1226 for (k, wi) in SHA512_K.iter().zip(&w) {
1227 let s1 = e.rotate_right(14) ^ e.rotate_right(18) ^ e.rotate_right(41);
1228 let ch = (e & f) ^ ((!e) & g);
1229 let t1 = hh
1230 .wrapping_add(s1)
1231 .wrapping_add(ch)
1232 .wrapping_add(*k)
1233 .wrapping_add(*wi);
1234 let s0 = a.rotate_right(28) ^ a.rotate_right(34) ^ a.rotate_right(39);
1235 let maj = (a & b) ^ (a & c) ^ (b & c);
1236 let t2 = s0.wrapping_add(maj);
1237 hh = g;
1238 g = f;
1239 f = e;
1240 e = d.wrapping_add(t1);
1241 d = c;
1242 c = b;
1243 b = a;
1244 a = t1.wrapping_add(t2);
1245 }
1246 for (hv, v) in h.iter_mut().zip([a, b, c, d, e, f, g, hh]) {
1247 *hv = hv.wrapping_add(v);
1248 }
1249}
1250
1251#[cfg(target_arch = "aarch64")]
1260mod sha_hw {
1261 use core::arch::aarch64::{
1262 uint32x4_t, uint64x2_t, vaddq_u32, vaddq_u64, vextq_u64, vld1q_u32, vld1q_u64, vld1q_u8,
1263 vreinterpretq_u32_u8, vreinterpretq_u64_u8, vrev32q_u8, vrev64q_u8, vsha256h2q_u32,
1264 vsha256hq_u32, vsha256su0q_u32, vsha256su1q_u32, vsha512h2q_u64, vsha512hq_u64,
1265 vsha512su0q_u64, vsha512su1q_u64, vst1q_u32,
1266 };
1267
1268 use super::{SHA256_K, SHA512_K};
1269
1270 #[target_feature(enable = "sha2")]
1273 pub unsafe fn compress256(h: &mut [u32; 8], block: &[u8; 64]) {
1274 let mut abcd = vld1q_u32(h.as_ptr());
1275 let mut efgh = vld1q_u32(h.as_ptr().add(4));
1276 let saved = (abcd, efgh);
1277 let mut w: [uint32x4_t; 4] = [
1278 vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(block.as_ptr()))),
1279 vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(block.as_ptr().add(16)))),
1280 vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(block.as_ptr().add(32)))),
1281 vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(block.as_ptr().add(48)))),
1282 ];
1283 for step in 0..16 {
1284 let wk = vaddq_u32(w[step % 4], vld1q_u32(SHA256_K.as_ptr().add(4 * step)));
1285 if step < 12 {
1287 w[step % 4] = vsha256su1q_u32(
1288 vsha256su0q_u32(w[step % 4], w[(step + 1) % 4]),
1289 w[(step + 2) % 4],
1290 w[(step + 3) % 4],
1291 );
1292 }
1293 let prev = abcd;
1294 abcd = vsha256hq_u32(abcd, efgh, wk);
1295 efgh = vsha256h2q_u32(efgh, prev, wk);
1296 }
1297 vst1q_u32(h.as_mut_ptr(), vaddq_u32(abcd, saved.0));
1298 vst1q_u32(h.as_mut_ptr().add(4), vaddq_u32(efgh, saved.1));
1299 }
1300
1301 #[target_feature(enable = "sha2,sha3")]
1304 pub unsafe fn compress512(h: &mut [u64; 8], block: &[u8; 128]) {
1305 let mut s: [uint64x2_t; 4] = [
1309 vld1q_u64(h.as_ptr()),
1310 vld1q_u64(h.as_ptr().add(2)),
1311 vld1q_u64(h.as_ptr().add(4)),
1312 vld1q_u64(h.as_ptr().add(6)),
1313 ];
1314 let saved = s;
1315 let mut w: [uint64x2_t; 8] = [core::mem::zeroed(); 8];
1316 for (pair, bytes) in w.iter_mut().zip(block.as_chunks::<16>().0) {
1317 *pair = vreinterpretq_u64_u8(vrev64q_u8(vld1q_u8(bytes.as_ptr())));
1318 }
1319 for step in 0..40 {
1320 let r = 3 - (step % 4);
1321 let wk = vaddq_u64(w[step % 8], vld1q_u64(SHA512_K.as_ptr().add(2 * step)));
1322 let sum = vaddq_u64(vextq_u64::<1>(wk, wk), s[r]);
1323 let im = vsha512hq_u64(
1324 sum,
1325 vextq_u64::<1>(s[(r + 3) % 4], s[r]),
1326 vextq_u64::<1>(s[(r + 2) % 4], s[(r + 3) % 4]),
1327 );
1328 let updated = vsha512h2q_u64(im, s[(r + 2) % 4], s[(r + 1) % 4]);
1329 s[(r + 2) % 4] = vaddq_u64(s[(r + 2) % 4], im);
1330 s[r] = updated;
1331 if step < 32 {
1333 let i = step % 8;
1334 w[i] = vsha512su1q_u64(
1335 vsha512su0q_u64(w[i], w[(i + 1) % 8]),
1336 w[(i + 7) % 8],
1337 vextq_u64::<1>(w[(i + 4) % 8], w[(i + 5) % 8]),
1338 );
1339 }
1340 }
1341 for (i, (out, kept)) in s.iter().zip(saved).enumerate() {
1342 let summed = vaddq_u64(*out, kept);
1343 core::arch::aarch64::vst1q_u64(h.as_mut_ptr().add(2 * i), summed);
1344 }
1345 }
1346}
1347
1348fn sha512(input: &[u8]) -> Vec<u8> {
1349 let h = sha512_core(
1350 input,
1351 [
1352 0x6a09e667f3bcc908,
1353 0xbb67ae8584caa73b,
1354 0x3c6ef372fe94f82b,
1355 0xa54ff53a5f1d36f1,
1356 0x510e527fade682d1,
1357 0x9b05688c2b3e6c1f,
1358 0x1f83d9abfb41bd6b,
1359 0x5be0cd19137e2179,
1360 ],
1361 );
1362 h.iter().flat_map(|w| w.to_be_bytes()).collect()
1363}
1364
1365fn sha384(input: &[u8]) -> Vec<u8> {
1366 let h = sha512_core(
1367 input,
1368 [
1369 0xcbbb9d5dc1059ed8,
1370 0x629a292a367cd507,
1371 0x9159015a3070dd17,
1372 0x152fecd8f70e5939,
1373 0x67332667ffc00b31,
1374 0x8eb44a8768581511,
1375 0xdb0c2e0d64f98fa7,
1376 0x47b5481dbefa4fa4,
1377 ],
1378 );
1379 h.iter().take(6).flat_map(|w| w.to_be_bytes()).collect()
1380}
1381
1382fn aesv3_key(enc: &Dict, r: i64, password: &[u8]) -> Option<Vec<u8>> {
1388 let pw = &password[..password.len().min(127)];
1389 let u = enc.get("U").and_then(Object::as_str_bytes)?;
1390 if u.len() < 48 {
1391 return None;
1392 }
1393 let perms = enc.get("Perms").and_then(Object::as_str_bytes);
1401 let o = enc.get("O").and_then(Object::as_str_bytes);
1402 if let Some(perms) = perms.filter(|p| p.len() >= 16) {
1403 if let Some(ue) = enc.get("UE").and_then(Object::as_str_bytes) {
1404 if ue.len() >= 32 {
1405 let intermediate = hash_2b(r, pw, &u[40..48], &[]);
1406 let file_key = aes_cbc_decrypt_blocks(&intermediate, &[0u8; 16], &ue[..32]);
1407 if file_key.len() == 32 && perms_marker_valid(&file_key, perms) {
1408 return Some(file_key);
1409 }
1410 }
1411 }
1412 if let (Some(o), Some(oe)) = (o, enc.get("OE").and_then(Object::as_str_bytes)) {
1413 if o.len() >= 48 && oe.len() >= 32 {
1414 let intermediate = hash_2b(r, pw, &o[40..48], &u[..48]);
1415 let file_key = aes_cbc_decrypt_blocks(&intermediate, &[0u8; 16], &oe[..32]);
1416 if file_key.len() == 32 && perms_marker_valid(&file_key, perms) {
1417 return Some(file_key);
1418 }
1419 }
1420 }
1421 }
1422 if let Some(ue) = enc.get("UE").and_then(Object::as_str_bytes) {
1423 if ue.len() >= 32 && hash_2b(r, pw, &u[32..40], &[])[..32] == u[..32] {
1424 let intermediate = hash_2b(r, pw, &u[40..48], &[]);
1425 let file_key = aes_cbc_decrypt_blocks(&intermediate, &[0u8; 16], &ue[..32]);
1426 if file_key.len() == 32 {
1427 return Some(file_key);
1428 }
1429 }
1430 }
1431 let o = o?;
1432 let oe = enc.get("OE").and_then(Object::as_str_bytes)?;
1433 if o.len() < 48 || oe.len() < 32 {
1434 return None;
1435 }
1436 if hash_2b(r, pw, &o[32..40], &u[..48])[..32] != o[..32] {
1437 return None;
1438 }
1439 let intermediate = hash_2b(r, pw, &o[40..48], &u[..48]);
1440 let file_key = aes_cbc_decrypt_blocks(&intermediate, &[0u8; 16], &oe[..32]);
1441 (file_key.len() == 32).then_some(file_key)
1442}
1443
1444fn perms_marker_valid(file_key: &[u8], perms: &[u8]) -> bool {
1447 let rks = aes_expand_key(file_key);
1448 let inv_sbox = aes_inv_sbox();
1449 let mut block = [0u8; 16];
1450 block.copy_from_slice(&perms[..16]);
1451 aes_decrypt_block(&mut block, &rks, &inv_sbox);
1452 &block[9..12] == b"adb"
1453}
1454
1455fn hash_2b(r: i64, password: &[u8], salt: &[u8], udata: &[u8]) -> Vec<u8> {
1458 let mut seed = Vec::with_capacity(password.len() + salt.len() + udata.len());
1459 seed.extend_from_slice(password);
1460 seed.extend_from_slice(salt);
1461 seed.extend_from_slice(udata);
1462 let mut k = sha256(&seed).to_vec();
1463 if r < 6 {
1464 return k; }
1466 let mut round = 0usize;
1467 let mut k1 = Vec::with_capacity(64 * (password.len() + 64 + udata.len()));
1468 loop {
1469 k1.clear();
1470 for _ in 0..64 {
1471 k1.extend_from_slice(password);
1472 k1.extend_from_slice(&k);
1473 k1.extend_from_slice(udata);
1474 }
1475 let e = aes_cbc_encrypt_blocks(&k[..16], &k[16..32], &k1);
1476 let modulus = e[..16].iter().map(|&b| u32::from(b)).sum::<u32>() % 3;
1477 k = match modulus {
1478 0 => sha256(&e).to_vec(),
1479 1 => sha384(&e),
1480 _ => sha512(&e),
1481 };
1482 round += 1;
1483 if round >= 64 && usize::from(*e.last().unwrap()) <= round - 32 {
1484 break;
1485 }
1486 }
1487 k.truncate(32);
1488 k
1489}
1490
1491pub(crate) struct KeyMaterial {
1495 file_key: [u8; 32],
1496 u: Vec<u8>,
1497 ue: Vec<u8>,
1498 o: Vec<u8>,
1499 oe: Vec<u8>,
1500 perms: Vec<u8>,
1501}
1502
1503pub(crate) fn r6_key_material(
1510 user_pw: &[u8],
1511 owner_pw: &[u8],
1512 p: i32,
1513 encrypt_metadata: bool,
1514 rng: &mut dyn FnMut(&mut [u8]),
1515) -> KeyMaterial {
1516 let user_pw = &user_pw[..user_pw.len().min(127)];
1517 let owner_pw = &owner_pw[..owner_pw.len().min(127)];
1518
1519 let mut file_key = [0u8; 32];
1520 rng(&mut file_key);
1521
1522 let mut user_salt = [0u8; 16];
1525 rng(&mut user_salt);
1526 let mut u = hash_2b(6, user_pw, &user_salt[..8], &[]);
1527 u.extend_from_slice(&user_salt);
1528 let user_intermediate = hash_2b(6, user_pw, &user_salt[8..], &[]);
1529 let ue = aes_cbc_encrypt_blocks(&user_intermediate, &[0u8; 16], &file_key);
1530
1531 let mut owner_salt = [0u8; 16];
1534 rng(&mut owner_salt);
1535 let mut o = hash_2b(6, owner_pw, &owner_salt[..8], &u[..48]);
1536 o.extend_from_slice(&owner_salt);
1537 let owner_intermediate = hash_2b(6, owner_pw, &owner_salt[8..], &u[..48]);
1538 let oe = aes_cbc_encrypt_blocks(&owner_intermediate, &[0u8; 16], &file_key);
1539
1540 let mut perms_block = [0u8; 16];
1543 perms_block[..4].copy_from_slice(&p.to_le_bytes());
1544 perms_block[4..8].copy_from_slice(&[0xff; 4]);
1545 perms_block[8] = if encrypt_metadata { b'T' } else { b'F' };
1546 perms_block[9..12].copy_from_slice(b"adb");
1547 rng(&mut perms_block[12..]);
1548 aes_encrypt_block(&mut perms_block, &aes_expand_key(&file_key));
1549
1550 KeyMaterial {
1551 file_key,
1552 u,
1553 ue,
1554 o,
1555 oe,
1556 perms: perms_block.to_vec(),
1557 }
1558}
1559
1560#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
1564pub(crate) fn fill_os_random(buf: &mut [u8]) {
1565 getrandom::fill(buf).expect("OS random number generator unavailable");
1566}
1567
1568#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1573pub struct Permissions {
1574 pub print: bool,
1577 pub modify: bool,
1580 pub copy: bool,
1582 pub annotate: bool,
1585 pub fill_forms: bool,
1588 pub accessibility: bool,
1590 pub assemble: bool,
1593 pub print_hires: bool,
1596}
1597
1598pub const PERMISSION_NAMES: [&str; 8] = [
1603 "print",
1604 "modify",
1605 "copy",
1606 "annotate",
1607 "fill-forms",
1608 "accessibility",
1609 "assemble",
1610 "print-hires",
1611];
1612
1613impl Permissions {
1614 pub fn all() -> Permissions {
1616 Permissions {
1617 print: true,
1618 modify: true,
1619 copy: true,
1620 annotate: true,
1621 fill_forms: true,
1622 accessibility: true,
1623 assemble: true,
1624 print_hires: true,
1625 }
1626 }
1627
1628 pub fn from_names<'a>(names: impl IntoIterator<Item = &'a str>) -> Result<Permissions, String> {
1633 let mut permissions = Permissions {
1634 print: false,
1635 modify: false,
1636 copy: false,
1637 annotate: false,
1638 fill_forms: false,
1639 accessibility: false,
1640 assemble: false,
1641 print_hires: false,
1642 };
1643 for name in names {
1644 match name {
1645 "print" => permissions.print = true,
1646 "modify" => permissions.modify = true,
1647 "copy" => permissions.copy = true,
1648 "annotate" => permissions.annotate = true,
1649 "fill-forms" => permissions.fill_forms = true,
1650 "accessibility" => permissions.accessibility = true,
1651 "assemble" => permissions.assemble = true,
1652 "print-hires" => permissions.print_hires = true,
1653 other => return Err(other.to_string()),
1654 }
1655 }
1656 Ok(permissions)
1657 }
1658
1659 pub(crate) fn p_value(&self) -> i32 {
1666 let flags: [(u32, bool); 8] = [
1667 (3, self.print),
1668 (4, self.modify),
1669 (5, self.copy),
1670 (6, self.annotate),
1671 (9, self.fill_forms),
1672 (10, self.accessibility),
1673 (11, self.assemble),
1674 (12, self.print_hires),
1675 ];
1676 let mut bits: u32 = !0b11; for (bit, granted) in flags {
1678 if !granted {
1679 bits &= !(1u32 << (bit - 1));
1680 }
1681 }
1682 bits as i32
1683 }
1684}
1685
1686impl Default for Permissions {
1687 fn default() -> Permissions {
1689 Permissions::all()
1690 }
1691}
1692
1693fn aes256_encrypt_dict(material: &KeyMaterial, p: i32) -> Dict {
1699 let mut std_cf = Dict::new();
1700 std_cf.insert(
1701 Name("CFM".to_string()),
1702 Object::Name(Name("AESV3".to_string())),
1703 );
1704 std_cf.insert(Name("Length".to_string()), Object::Int(32));
1705 let mut cf = Dict::new();
1706 cf.insert(Name("StdCF".to_string()), Object::Dict(std_cf));
1707
1708 let mut dict = Dict::new();
1709 dict.insert(
1710 Name("Filter".to_string()),
1711 Object::Name(Name("Standard".to_string())),
1712 );
1713 dict.insert(Name("V".to_string()), Object::Int(5));
1714 dict.insert(Name("R".to_string()), Object::Int(6));
1715 dict.insert(Name("Length".to_string()), Object::Int(256));
1716 dict.insert(Name("CF".to_string()), Object::Dict(cf));
1717 dict.insert(
1718 Name("StmF".to_string()),
1719 Object::Name(Name("StdCF".to_string())),
1720 );
1721 dict.insert(
1722 Name("StrF".to_string()),
1723 Object::Name(Name("StdCF".to_string())),
1724 );
1725 dict.insert(Name("P".to_string()), Object::Int(i64::from(p)));
1726 dict.insert(Name("U".to_string()), Object::String(material.u.clone()));
1727 dict.insert(Name("UE".to_string()), Object::String(material.ue.clone()));
1728 dict.insert(Name("O".to_string()), Object::String(material.o.clone()));
1729 dict.insert(Name("OE".to_string()), Object::String(material.oe.clone()));
1730 dict.insert(
1731 Name("Perms".to_string()),
1732 Object::String(material.perms.clone()),
1733 );
1734 dict
1735}
1736
1737#[allow(
1742 clippy::type_complexity,
1743 reason = "Box<dyn FnMut(&mut [u8]) + Send> names the one random-byte source the write path takes; a type alias would only rename it"
1744)]
1745pub struct Encryptor {
1746 file_key: [u8; 32],
1747 rng: Box<dyn FnMut(&mut [u8]) + Send>,
1748}
1749
1750impl Encryptor {
1751 #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
1761 pub fn aes256(
1762 user_password: &str,
1763 owner_password: &str,
1764 permissions: Permissions,
1765 ) -> (Encryptor, Dict) {
1766 Encryptor::aes256_with_rng(
1767 user_password,
1768 owner_password,
1769 permissions,
1770 Box::new(fill_os_random),
1771 )
1772 }
1773
1774 #[allow(clippy::type_complexity, reason = "see Encryptor's rng field")]
1777 pub fn aes256_with_rng(
1778 user_password: &str,
1779 owner_password: &str,
1780 permissions: Permissions,
1781 rng: Box<dyn FnMut(&mut [u8]) + Send>,
1782 ) -> (Encryptor, Dict) {
1783 let mut rng = rng;
1784 let p = permissions.p_value();
1785 let material = r6_key_material(
1786 user_password.as_bytes(),
1787 owner_password.as_bytes(),
1788 p,
1789 true,
1790 &mut *rng,
1791 );
1792 let dict = aes256_encrypt_dict(&material, p);
1793 let encryptor = Encryptor {
1794 file_key: material.file_key,
1795 rng,
1796 };
1797 (encryptor, dict)
1798 }
1799
1800 pub fn encrypt_object(&mut self, obj: &mut Object, num: u32, gen: u16) {
1809 let _ = (num, gen);
1810 encrypt_in_place(obj, &self.file_key, &mut *self.rng);
1811 }
1812}
1813
1814fn encrypt_in_place(obj: &mut Object, key: &[u8], rng: &mut dyn FnMut(&mut [u8])) {
1819 match obj {
1820 Object::String(bytes) => *bytes = aes_cbc_encrypt(key, rng, bytes),
1821 Object::Array(items) => {
1822 for it in items {
1823 encrypt_in_place(it, key, &mut *rng);
1824 }
1825 }
1826 Object::Dict(dict) => {
1827 for v in dict.values_mut() {
1828 encrypt_in_place(v, key, &mut *rng);
1829 }
1830 }
1831 Object::Stream(stream) => {
1832 for v in stream.dict.values_mut() {
1833 encrypt_in_place(v, key, &mut *rng);
1834 }
1835 if stream_crypt_filter(&stream.dict).as_deref() == Some("Identity") {
1839 return;
1840 }
1841 stream.data = aes_cbc_encrypt(key, rng, &stream.data);
1842 }
1843 _ => {}
1844 }
1845}
1846
1847#[rustfmt::skip]
1849const MD5_S: [u32; 64] = [
1850 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
1851 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
1852 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
1853 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
1854];
1855
1856#[rustfmt::skip]
1858const MD5_K: [u32; 64] = [
1859 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
1860 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
1861 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
1862 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
1863 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
1864 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
1865 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
1866 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
1867];
1868
1869fn md5(input: &[u8]) -> [u8; 16] {
1872 let (mut a0, mut b0, mut c0, mut d0) = (
1873 0x6745_2301u32,
1874 0xefcd_ab89u32,
1875 0x98ba_dcfeu32,
1876 0x1032_5476u32,
1877 );
1878
1879 let mut msg = input.to_vec();
1880 let bitlen = (input.len() as u64).wrapping_mul(8);
1881 msg.push(0x80);
1882 while msg.len() % 64 != 56 {
1883 msg.push(0);
1884 }
1885 msg.extend_from_slice(&bitlen.to_le_bytes());
1886
1887 for chunk in msg.as_chunks::<64>().0 {
1888 let mut m = [0u32; 16];
1889 for (word, bytes) in m.iter_mut().zip(chunk.as_chunks::<4>().0) {
1890 *word = u32::from_le_bytes(*bytes);
1891 }
1892 let (mut a, mut b, mut c, mut d) = (a0, b0, c0, d0);
1893 for i in 0..64 {
1894 let (f, g) = match i {
1895 0..=15 => ((b & c) | (!b & d), i),
1896 16..=31 => ((d & b) | (!d & c), (5 * i + 1) % 16),
1897 32..=47 => (b ^ c ^ d, (3 * i + 5) % 16),
1898 _ => (c ^ (b | !d), (7 * i) % 16),
1899 };
1900 let f = f.wrapping_add(a).wrapping_add(MD5_K[i]).wrapping_add(m[g]);
1901 a = d;
1902 d = c;
1903 c = b;
1904 b = b.wrapping_add(f.rotate_left(MD5_S[i]));
1905 }
1906 a0 = a0.wrapping_add(a);
1907 b0 = b0.wrapping_add(b);
1908 c0 = c0.wrapping_add(c);
1909 d0 = d0.wrapping_add(d);
1910 }
1911
1912 let mut out = [0u8; 16];
1913 out[0..4].copy_from_slice(&a0.to_le_bytes());
1914 out[4..8].copy_from_slice(&b0.to_le_bytes());
1915 out[8..12].copy_from_slice(&c0.to_le_bytes());
1916 out[12..16].copy_from_slice(&d0.to_le_bytes());
1917 out
1918}
1919
1920#[cfg(test)]
1921mod tests {
1922 use super::*;
1923 use crate::object::Name;
1924
1925 fn hex(bytes: &[u8]) -> String {
1926 bytes.iter().map(|b| format!("{b:02x}")).collect()
1927 }
1928
1929 #[test]
1930 fn md5_known_vectors() {
1931 assert_eq!(hex(&md5(b"")), "d41d8cd98f00b204e9800998ecf8427e");
1932 assert_eq!(hex(&md5(b"abc")), "900150983cd24fb0d6963f7d28e17f72");
1933 assert_eq!(
1934 hex(&md5(b"The quick brown fox jumps over the lazy dog")),
1935 "9e107d9d372bb6826bd81d3542a419d6"
1936 );
1937 }
1938
1939 #[test]
1940 fn md5_spans_block_boundary() {
1941 let input = [b'a'; 56];
1943 assert_eq!(hex(&md5(&input)), "3b0c8ac703f828b04c6c197006d17218");
1944 }
1945
1946 #[test]
1951 fn aes_block_known_vectors() {
1952 let plain: [u8; 16] = core::array::from_fn(|i| (i as u8) * 0x11);
1953 let key128: [u8; 16] = core::array::from_fn(|i| i as u8);
1954 let key256: [u8; 32] = core::array::from_fn(|i| i as u8);
1955
1956 type Encrypt = fn(&mut [u8; 16], &[[u8; 16]]);
1957 type Decrypt = fn(&mut [u8; 16], &[[u8; 16]], &[u8; 256]);
1958 let paths: [(Encrypt, Decrypt); 2] = [
1959 (aes_encrypt_block, aes_decrypt_block),
1960 (aes_encrypt_block_soft, aes_decrypt_block_soft),
1961 ];
1962 for (encrypt, decrypt) in paths {
1963 let mut s = plain;
1964 encrypt(&mut s, &aes_expand_key(&key128));
1965 assert_eq!(hex(&s), "69c4e0d86a7b0430d8cdb78070b4c55a");
1966 decrypt(&mut s, &aes_expand_key(&key128), &aes_inv_sbox());
1967 assert_eq!(s, plain);
1968
1969 let mut s = plain;
1970 encrypt(&mut s, &aes_expand_key(&key256));
1971 assert_eq!(hex(&s), "8ea2b7ca516745bfeafc49904b496089");
1972 decrypt(&mut s, &aes_expand_key(&key256), &aes_inv_sbox());
1973 assert_eq!(s, plain);
1974 }
1975 }
1976
1977 #[test]
1980 fn aes_cbc_round_trips_multiple_blocks() {
1981 let key: [u8; 16] = core::array::from_fn(|i| (i as u8).wrapping_mul(7));
1982 let iv: [u8; 16] = core::array::from_fn(|i| 0xa5 ^ (i as u8));
1983 let data: Vec<u8> = (0..64u8).collect();
1984 let ct = aes_cbc_encrypt_blocks(&key, &iv, &data);
1985 assert_eq!(ct.len(), data.len());
1986 assert_ne!(ct, data);
1987 assert_eq!(aes_cbc_decrypt_blocks(&key, &iv, &ct), data);
1988 }
1989
1990 #[test]
1994 fn sha2_known_vectors() {
1995 assert_eq!(
1996 hex(&sha256(b"")),
1997 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
1998 );
1999 assert_eq!(
2000 hex(&sha256(b"abc")),
2001 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
2002 );
2003 assert_eq!(
2004 hex(&sha256(&[b'a'; 200])),
2005 "c2a908d98f5df987ade41b5fce213067efbcc21ef2240212a41e54b5e7c28ae5"
2006 );
2007 assert_eq!(
2008 hex(&sha384(b"abc")),
2009 "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed\
2010 8086072ba1e7cc2358baeca134c825a7"
2011 );
2012 assert_eq!(
2013 hex(&sha512(b"abc")),
2014 "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a\
2015 2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
2016 );
2017 assert_eq!(
2018 hex(&sha512(&[b'a'; 300])),
2019 "a6a77010dd9696c23831e6549de51724df332c2075039b75fcfe6c2e6de42fbd\
2020 3c80ed4073267e00c8c320712c3cdd9d65a96f90a3fe4a58a6b70a103be08e83"
2021 );
2022 }
2023
2024 #[test]
2028 fn sha2_soft_compressions_match_the_dispatch() {
2029 let block64: [u8; 64] = core::array::from_fn(|i| (i as u8).wrapping_mul(31));
2030 let mut via_dispatch = [0x6a09e667u32; 8];
2031 let mut via_soft = via_dispatch;
2032 sha256_compress(&mut via_dispatch, &block64);
2033 sha256_compress_soft(&mut via_soft, &block64);
2034 assert_eq!(via_dispatch, via_soft);
2035
2036 let block128: [u8; 128] = core::array::from_fn(|i| (i as u8).wrapping_mul(29));
2037 let mut via_dispatch = [0x6a09e667f3bcc908u64; 8];
2038 let mut via_soft = via_dispatch;
2039 sha512_compress(&mut via_dispatch, &block128);
2040 sha512_compress_soft(&mut via_soft, &block128);
2041 assert_eq!(via_dispatch, via_soft);
2042 }
2043
2044 #[test]
2047 fn incremental_sha256_matches_the_one_shot() {
2048 let input: Vec<u8> = (0..300u16).map(|i| (i % 251) as u8).collect();
2049 for splits in [
2050 vec![0, 1, 3, 7, 60, 63, 64, 65, 37],
2051 vec![300],
2052 vec![128, 128, 44],
2053 vec![55, 9, 236],
2054 ] {
2055 let mut hasher = Sha256::new();
2056 let mut fed = 0usize;
2057 for len in splits {
2058 hasher.update(&input[fed..fed + len]);
2059 fed += len;
2060 }
2061 hasher.update(&input[fed..]);
2062 assert_eq!(hasher.finalize(), sha256(&input));
2063 }
2064 assert_eq!(Sha256::new().finalize(), sha256(b""));
2065 assert_eq!(Sha256::default().finalize(), sha256(b""));
2066 }
2067
2068 #[test]
2069 fn rc4_known_vector() {
2070 let ct = rc4(b"Key", b"Plaintext");
2072 assert_eq!(hex(&ct), "bbf316e8d940af0ad3");
2073 assert_eq!(rc4(b"Key", &ct), b"Plaintext");
2075 }
2076
2077 const N: usize = 16; const P: i32 = -44;
2084 const ID0: &[u8] = b"0123456789abcdef";
2085
2086 fn owner_entry(owner_pw: &[u8], user_pw: &[u8]) -> Vec<u8> {
2088 owner_entry_with(N, owner_pw, user_pw)
2089 }
2090
2091 fn owner_entry_with(n: usize, owner_pw: &[u8], user_pw: &[u8]) -> Vec<u8> {
2093 let mut d = md5(&pad_password(owner_pw));
2094 for _ in 0..50 {
2095 d = md5(&d[..n]);
2096 }
2097 let rc4key = d[..n].to_vec();
2098 let mut o = rc4(&rc4key, &pad_password(user_pw));
2099 for i in 1u8..=19 {
2100 let k: Vec<u8> = rc4key.iter().map(|b| b ^ i).collect();
2101 o = rc4(&k, &o);
2102 }
2103 o
2104 }
2105
2106 fn file_key(o: &[u8], user_pw: &[u8]) -> Vec<u8> {
2108 file_key_with(N, o, user_pw)
2109 }
2110
2111 fn file_key_with(n: usize, o: &[u8], user_pw: &[u8]) -> Vec<u8> {
2113 let mut input = Vec::new();
2114 input.extend_from_slice(&pad_password(user_pw));
2115 input.extend_from_slice(o);
2116 input.extend_from_slice(&(P as u32).to_le_bytes());
2117 input.extend_from_slice(ID0);
2118 let mut d = md5(&input);
2119 for _ in 0..50 {
2120 d = md5(&d[..n]);
2121 }
2122 d[..n].to_vec()
2123 }
2124
2125 fn msg_of(doc: &crate::Document, num: u32) -> Vec<u8> {
2127 use crate::object::ObjRef;
2128 let obj = doc.get(ObjRef { num, gen: 0 }).unwrap();
2129 obj.as_dict()
2130 .unwrap()
2131 .get("Msg")
2132 .unwrap()
2133 .as_str_bytes()
2134 .unwrap()
2135 .to_vec()
2136 }
2137
2138 fn body_of(doc: &crate::Document, num: u32) -> Vec<u8> {
2140 use crate::object::ObjRef;
2141 let obj = doc.get(ObjRef { num, gen: 0 }).unwrap();
2142 doc.stream_data(obj.as_stream().unwrap()).unwrap()
2143 }
2144
2145 fn user_entry(key: &[u8]) -> Vec<u8> {
2147 let mut input = Vec::new();
2148 input.extend_from_slice(&PAD);
2149 input.extend_from_slice(ID0);
2150 let mut x = md5(&input).to_vec();
2151 x = rc4(key, &x);
2152 for i in 1u8..=19 {
2153 let k: Vec<u8> = key.iter().map(|b| b ^ i).collect();
2154 x = rc4(&k, &x);
2155 }
2156 x.resize(32, 0); x
2158 }
2159
2160 fn obj_key(key: &[u8], num: u32, gen: u16) -> Vec<u8> {
2161 let mut input = key.to_vec();
2162 input.extend_from_slice(&num.to_le_bytes()[..3]);
2163 input.extend_from_slice(&gen.to_le_bytes()[..2]);
2164 md5(&input)[..(key.len() + 5).min(16)].to_vec()
2165 }
2166
2167 fn hexstr(b: &[u8]) -> String {
2168 let mut s = String::from("<");
2169 for x in b {
2170 s.push_str(&format!("{x:02x}"));
2171 }
2172 s.push('>');
2173 s
2174 }
2175
2176 fn encrypted_fixture(u_override: Option<Vec<u8>>) -> Vec<u8> {
2177 encrypted_fixture_with(b"", b"", u_override)
2178 }
2179
2180 fn encrypted_fixture_with(
2181 user_pw: &[u8],
2182 owner_pw: &[u8],
2183 u_override: Option<Vec<u8>>,
2184 ) -> Vec<u8> {
2185 use pdfboss_testkit::PdfBuilder;
2186 let o = owner_entry(owner_pw, user_pw);
2187 let key = file_key(&o, user_pw);
2188 let u = u_override.unwrap_or_else(|| user_entry(&key));
2189
2190 let msg = rc4(&obj_key(&key, 3, 0), b"Top secret message");
2191 let stream = rc4(&obj_key(&key, 4, 0), b"decrypted stream body");
2192
2193 let mut b = PdfBuilder::new().version(1, 4);
2194 b.object(1, "<< /Type /Catalog /Pages 2 0 R >>");
2195 b.object(2, "<< /Type /Pages /Kids [] /Count 0 >>");
2196 b.object(3, &format!("<< /Msg {} >>", hexstr(&msg)));
2197 b.stream(4, "", &stream);
2198 b.object(
2199 9,
2200 &format!(
2201 "<< /Filter /Standard /V 2 /R 3 /Length 128 /P {P} /O {} /U {} >>",
2202 hexstr(&o),
2203 hexstr(&u)
2204 ),
2205 );
2206 let trailer = format!("/Encrypt 9 0 R /ID [{}{}]", hexstr(ID0), hexstr(ID0));
2207 b.trailer_extra(&trailer).build(1)
2208 }
2209
2210 #[test]
2212 fn document_load_decrypts_standard_rc4() {
2213 use crate::object::ObjRef;
2214 use crate::Document;
2215
2216 let doc = Document::load(encrypted_fixture(None)).expect("empty password opens the file");
2217
2218 let obj3 = doc.get(ObjRef { num: 3, gen: 0 }).unwrap();
2219 let msg = obj3
2220 .as_dict()
2221 .unwrap()
2222 .get("Msg")
2223 .unwrap()
2224 .as_str_bytes()
2225 .unwrap();
2226 assert_eq!(msg, b"Top secret message", "string decrypted");
2227
2228 let obj4 = doc.get(ObjRef { num: 4, gen: 0 }).unwrap();
2229 let data = doc.stream_data(obj4.as_stream().unwrap()).unwrap();
2230 assert_eq!(data, b"decrypted stream body", "stream decrypted");
2231 }
2232
2233 #[test]
2235 fn document_load_rejects_when_password_does_not_verify() {
2236 use crate::error::Error;
2237 use crate::Document;
2238
2239 let bad_u = vec![0u8; 32];
2242 let err = Document::load(encrypted_fixture(Some(bad_u)));
2243 assert!(matches!(err, Err(Error::Encrypted)));
2244 }
2245
2246 #[test]
2248 fn real_user_password_opens_an_rc4_file() {
2249 use crate::error::Error;
2250 use crate::object::ObjRef;
2251 use crate::Document;
2252
2253 let bytes = encrypted_fixture_with(b"hunter2", b"owner-secret", None);
2254 assert!(
2255 matches!(Document::load(bytes.clone()), Err(Error::Encrypted)),
2256 "without the password the file stays closed"
2257 );
2258 let doc = Document::load_with_password(bytes, "hunter2").expect("user password opens");
2259 let obj3 = doc.get(ObjRef { num: 3, gen: 0 }).unwrap();
2260 let msg = obj3.as_dict().unwrap().get("Msg").unwrap();
2261 assert_eq!(msg.as_str_bytes().unwrap(), b"Top secret message");
2262 }
2263
2264 #[test]
2266 fn owner_password_opens_an_rc4_file() {
2267 use crate::object::ObjRef;
2268 use crate::Document;
2269
2270 let bytes = encrypted_fixture_with(b"hunter2", b"owner-secret", None);
2271 let doc =
2272 Document::load_with_password(bytes, "owner-secret").expect("owner password opens");
2273 let obj3 = doc.get(ObjRef { num: 3, gen: 0 }).unwrap();
2274 let msg = obj3.as_dict().unwrap().get("Msg").unwrap();
2275 assert_eq!(msg.as_str_bytes().unwrap(), b"Top secret message");
2276 }
2277
2278 #[test]
2280 fn wrong_password_stays_encrypted() {
2281 use crate::error::Error;
2282 use crate::Document;
2283
2284 let bytes = encrypted_fixture_with(b"hunter2", b"owner-secret", None);
2285 let err = Document::load_with_password(bytes, "letmein");
2286 assert!(matches!(err, Err(Error::Encrypted)));
2287 }
2288
2289 #[test]
2291 fn real_passwords_open_an_aes256_r6_file() {
2292 use crate::error::Error;
2293 use crate::object::ObjRef;
2294 use crate::Document;
2295
2296 let bytes = encrypted_fixture_aesv3_with(6, "pässword".as_bytes(), b"owner-secret");
2297 assert!(
2298 matches!(Document::load(bytes.clone()), Err(Error::Encrypted)),
2299 "without the password the file stays closed"
2300 );
2301 for pw in ["pässword", "owner-secret"] {
2302 let doc = Document::load_with_password(bytes.clone(), pw)
2303 .unwrap_or_else(|_| panic!("{pw:?} opens the file"));
2304 let obj3 = doc.get(ObjRef { num: 3, gen: 0 }).unwrap();
2305 let msg = obj3.as_dict().unwrap().get("Msg").unwrap();
2306 assert_eq!(msg.as_str_bytes().unwrap(), b"AES-256 secret");
2307 }
2308 assert!(matches!(
2309 Document::load_with_password(bytes, "letmein"),
2310 Err(Error::Encrypted)
2311 ));
2312 }
2313
2314 #[test]
2316 fn empty_password_files_still_open_through_the_password_api() {
2317 use crate::object::ObjRef;
2318 use crate::Document;
2319
2320 let doc = Document::load_with_password(encrypted_fixture(None), "")
2324 .expect("the empty password opens through the password API too");
2325 let obj3 = doc.get(ObjRef { num: 3, gen: 0 }).unwrap();
2326 let msg = obj3.as_dict().unwrap().get("Msg").unwrap();
2327 assert_eq!(msg.as_str_bytes().unwrap(), b"Top secret message");
2328 }
2329
2330 #[test]
2332 fn unsupported_handler_is_declined() {
2333 let mut enc = Dict::new();
2336 enc.insert(Name("Filter".into()), Object::Name(Name("Standard".into())));
2337 enc.insert(Name("V".into()), Object::Int(6));
2338 enc.insert(Name("R".into()), Object::Int(7));
2339 enc.insert(Name("O".into()), Object::String(vec![0; 48]));
2340 enc.insert(Name("U".into()), Object::String(vec![0; 48]));
2341 enc.insert(Name("P".into()), Object::Int(-4));
2342 assert!(Decryptor::from_standard(&enc, ID0).is_none());
2343 }
2344
2345 #[test]
2348 fn aes_fips197_block_vectors() {
2349 let pt: [u8; 16] = [
2351 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
2352 0xee, 0xff,
2353 ];
2354 let key128: Vec<u8> = (0u8..16).collect();
2355 let rks = aes_expand_key(&key128);
2356 let mut b = pt;
2357 aes_encrypt_block(&mut b, &rks);
2358 assert_eq!(hex(&b), "69c4e0d86a7b0430d8cdb78070b4c55a");
2359 aes_decrypt_block(&mut b, &rks, &aes_inv_sbox());
2360 assert_eq!(b, pt, "AES-128 decrypt inverts encrypt");
2361
2362 let key256: Vec<u8> = (0u8..32).collect();
2363 let rks = aes_expand_key(&key256);
2364 let mut b = pt;
2365 aes_encrypt_block(&mut b, &rks);
2366 assert_eq!(hex(&b), "8ea2b7ca516745bfeafc49904b496089");
2367 }
2368
2369 #[test]
2370 fn sha2_vectors() {
2371 assert_eq!(
2372 hex(&sha256(b"abc")),
2373 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
2374 );
2375 assert_eq!(
2376 hex(&sha512(b"abc")),
2377 "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a\
2378 2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
2379 );
2380 assert_eq!(
2381 hex(&sha384(b"abc")),
2382 "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed\
2383 8086072ba1e7cc2358baeca134c825a7"
2384 );
2385 }
2386
2387 #[test]
2388 fn aes_cbc_roundtrip() {
2389 let key: Vec<u8> = (0u8..16).collect();
2390 let iv = [0x24u8; 16];
2391 let pt = b"a message spanning several AES blocks exactly?!!";
2392 let ct = aes_cbc_encrypt_blocks(&key, &iv, &pkcs7_pad(pt));
2393 let mut val = iv.to_vec(); val.extend_from_slice(&ct);
2395 assert_eq!(aes_cbc_decrypt(&key, &val), pt);
2396 }
2397
2398 fn obj_key_aes(key: &[u8], num: u32, gen: u16) -> Vec<u8> {
2401 let mut input = key.to_vec();
2402 input.extend_from_slice(&num.to_le_bytes()[..3]);
2403 input.extend_from_slice(&gen.to_le_bytes()[..2]);
2404 input.extend_from_slice(b"sAlT");
2405 md5(&input)[..(key.len() + 5).min(16)].to_vec()
2406 }
2407
2408 fn aes_encrypt_pdf(key: &[u8], pt: &[u8], iv: &[u8; 16]) -> Vec<u8> {
2411 let mut out = iv.to_vec();
2412 out.extend_from_slice(&aes_cbc_encrypt_blocks(key, iv, &pkcs7_pad(pt)));
2413 out
2414 }
2415
2416 fn encrypted_fixture_aesv2() -> Vec<u8> {
2417 use pdfboss_testkit::PdfBuilder;
2418 let o = owner_entry(b"", b"");
2419 let key = file_key(&o, b""); let u = user_entry(&key);
2421 let iv = [0x11u8; 16];
2422 let msg = aes_encrypt_pdf(&obj_key_aes(&key, 3, 0), b"Top secret message", &iv);
2423 let stream = aes_encrypt_pdf(&obj_key_aes(&key, 4, 0), b"decrypted stream body", &iv);
2424
2425 let mut b = PdfBuilder::new().version(1, 5);
2426 b.object(1, "<< /Type /Catalog /Pages 2 0 R >>");
2427 b.object(2, "<< /Type /Pages /Kids [] /Count 0 >>");
2428 b.object(3, &format!("<< /Msg {} >>", hexstr(&msg)));
2429 b.stream(4, "", &stream);
2430 b.object(
2431 9,
2432 &format!(
2433 "<< /Filter /Standard /V 4 /R 4 /Length 128 /P {P} /O {} /U {} \
2434 /CF << /StdCF << /CFM /AESV2 /Length 16 >> >> /StmF /StdCF /StrF /StdCF >>",
2435 hexstr(&o),
2436 hexstr(&u)
2437 ),
2438 );
2439 let trailer = format!("/Encrypt 9 0 R /ID [{}{}]", hexstr(ID0), hexstr(ID0));
2440 b.trailer_extra(&trailer).build(1)
2441 }
2442
2443 #[test]
2445 fn document_load_decrypts_aesv2() {
2446 use crate::object::ObjRef;
2447 use crate::Document;
2448 let doc = Document::load(encrypted_fixture_aesv2()).expect("AESV2 empty password opens");
2449 let obj3 = doc.get(ObjRef { num: 3, gen: 0 }).unwrap();
2450 let msg = obj3
2451 .as_dict()
2452 .unwrap()
2453 .get("Msg")
2454 .unwrap()
2455 .as_str_bytes()
2456 .unwrap();
2457 assert_eq!(msg, b"Top secret message");
2458 let obj4 = doc.get(ObjRef { num: 4, gen: 0 }).unwrap();
2459 assert_eq!(
2460 doc.stream_data(obj4.as_stream().unwrap()).unwrap(),
2461 b"decrypted stream body"
2462 );
2463 }
2464
2465 fn v4_fixture(
2473 n: usize,
2474 encrypt_entries: &str,
2475 body: impl FnOnce(&mut pdfboss_testkit::PdfBuilder, &[u8]),
2476 ) -> Vec<u8> {
2477 use pdfboss_testkit::PdfBuilder;
2478 let o = owner_entry_with(n, b"", b"");
2479 let key = file_key_with(n, &o, b"");
2480 let u = user_entry(&key);
2481 let mut b = PdfBuilder::new().version(1, 5);
2482 b.object(1, "<< /Type /Catalog /Pages 2 0 R >>");
2483 b.object(2, "<< /Type /Pages /Kids [] /Count 0 >>");
2484 body(&mut b, &key);
2485 b.object(
2486 9,
2487 &format!(
2488 "<< /Filter /Standard /V 4 /R 4 /P {P} /O {} /U {} {encrypt_entries} >>",
2489 hexstr(&o),
2490 hexstr(&u)
2491 ),
2492 );
2493 let trailer = format!("/Encrypt 9 0 R /ID [{}{}]", hexstr(ID0), hexstr(ID0));
2494 b.trailer_extra(&trailer).build(1)
2495 }
2496
2497 const AESV2_CF: &str = "/CF << /StdCF << /CFM /AESV2 /Length 16 >> >>";
2498 const TWO_CF: &str =
2499 "/CF << /StdCF << /CFM /AESV2 /Length 16 >> /RcCF << /CFM /V2 /Length 16 >> >>";
2500 const IV: [u8; 16] = [0x11; 16];
2501
2502 #[test]
2506 fn identity_stream_filter_leaves_streams_as_stored() {
2507 use crate::Document;
2508 let data = v4_fixture(
2509 16,
2510 &format!("/Length 128 {AESV2_CF} /StmF /Identity /StrF /StdCF"),
2511 |b, key| {
2512 let msg = aes_encrypt_pdf(&obj_key_aes(key, 3, 0), b"Top secret message", &IV);
2513 b.object(3, &format!("<< /Msg {} >>", hexstr(&msg)));
2514 b.stream(4, "", b"stored in the clear");
2515 },
2516 );
2517 let doc = Document::load(data).expect("an Identity stream filter is a valid V4 file");
2518 assert_eq!(msg_of(&doc, 3), b"Top secret message");
2519 assert_eq!(body_of(&doc, 4), b"stored in the clear");
2520 }
2521
2522 #[test]
2525 fn string_filter_is_chosen_independently_of_the_stream_filter() {
2526 use crate::Document;
2527 let data = v4_fixture(
2528 16,
2529 &format!("/Length 128 {TWO_CF} /StmF /StdCF /StrF /RcCF"),
2530 |b, key| {
2531 let msg = rc4(&obj_key(key, 3, 0), b"Top secret message");
2532 b.object(3, &format!("<< /Msg {} >>", hexstr(&msg)));
2533 let stream =
2534 aes_encrypt_pdf(&obj_key_aes(key, 4, 0), b"decrypted stream body", &IV);
2535 b.stream(4, "", &stream);
2536 },
2537 );
2538 let doc = Document::load(data).expect("two crypt filters open");
2539 assert_eq!(msg_of(&doc, 3), b"Top secret message");
2540 assert_eq!(body_of(&doc, 4), b"decrypted stream body");
2541 }
2542
2543 #[test]
2546 fn embedded_file_filter_applies_to_embedded_file_streams() {
2547 use crate::Document;
2548 let data = v4_fixture(
2549 16,
2550 &format!("/Length 128 {TWO_CF} /StmF /StdCF /StrF /StdCF /EFF /RcCF"),
2551 |b, key| {
2552 let attached = rc4(&obj_key(key, 4, 0), b"attached file bytes");
2553 b.stream(4, "/Type /EmbeddedFile", &attached);
2554 let stream =
2555 aes_encrypt_pdf(&obj_key_aes(key, 5, 0), b"decrypted stream body", &IV);
2556 b.stream(5, "", &stream);
2557 },
2558 );
2559 let doc = Document::load(data).expect("an /EFF entry opens");
2560 assert_eq!(body_of(&doc, 4), b"attached file bytes");
2561 assert_eq!(body_of(&doc, 5), b"decrypted stream body");
2562 }
2563
2564 #[test]
2568 fn crypt_filter_length_sets_the_key_size() {
2569 use crate::Document;
2570 let data = v4_fixture(
2571 5,
2572 "/CF << /StdCF << /CFM /V2 /Length 5 >> >> /StmF /StdCF /StrF /StdCF",
2573 |b, key| {
2574 let msg = rc4(&obj_key(key, 3, 0), b"Top secret message");
2575 b.object(3, &format!("<< /Msg {} >>", hexstr(&msg)));
2576 b.stream(4, "", &rc4(&obj_key(key, 4, 0), b"decrypted stream body"));
2577 },
2578 );
2579 let doc = Document::load(data).expect("a 40-bit V4 file opens");
2580 assert_eq!(msg_of(&doc, 3), b"Top secret message");
2581 assert_eq!(body_of(&doc, 4), b"decrypted stream body");
2582 }
2583
2584 #[test]
2588 fn aesv2_always_derives_a_16_byte_object_key() {
2589 use crate::Document;
2590 let object_key = |key: &[u8], num: u32| {
2591 let mut input = key.to_vec();
2592 input.extend_from_slice(&num.to_le_bytes()[..3]);
2593 input.extend_from_slice(&[0, 0]);
2594 input.extend_from_slice(b"sAlT");
2595 md5(&input).to_vec()
2596 };
2597 let data = v4_fixture(
2598 5,
2599 "/Length 40 /CF << /StdCF << /CFM /AESV2 /Length 5 >> >> /StmF /StdCF /StrF /StdCF",
2600 |b, key| {
2601 let msg = aes_encrypt_pdf(&object_key(key, 3), b"Top secret message", &IV);
2602 b.object(3, &format!("<< /Msg {} >>", hexstr(&msg)));
2603 let stream = aes_encrypt_pdf(&object_key(key, 4), b"decrypted stream body", &IV);
2604 b.stream(4, "", &stream);
2605 },
2606 );
2607 let doc = Document::load(data).expect("a 40-bit AESV2 file opens");
2608 assert_eq!(msg_of(&doc, 3), b"Top secret message");
2609 assert_eq!(body_of(&doc, 4), b"decrypted stream body");
2610 }
2611
2612 #[test]
2617 fn a_stream_crypt_filter_naming_identity_is_left_as_stored() {
2618 use crate::Document;
2619 let data = v4_fixture(
2620 16,
2621 &format!("/Length 128 {AESV2_CF} /StmF /StdCF /StrF /StdCF"),
2622 |b, key| {
2623 b.stream(
2624 4,
2625 "/Filter /Crypt /DecodeParms << /Type /CryptFilterDecodeParms /Name /Identity >>",
2626 b"stored in the clear",
2627 );
2628 let stream =
2629 aes_encrypt_pdf(&obj_key_aes(key, 5, 0), b"decrypted stream body", &IV);
2630 b.stream(5, "", &stream);
2631 },
2632 );
2633 let doc = Document::load(data).expect("opens");
2634 assert_eq!(body_of(&doc, 4), b"stored in the clear");
2635 assert_eq!(body_of(&doc, 5), b"decrypted stream body");
2636 }
2637
2638 #[test]
2641 fn a_stream_crypt_filter_without_a_name_means_identity() {
2642 use crate::Document;
2643 let data = v4_fixture(
2644 16,
2645 &format!("/Length 128 {AESV2_CF} /StmF /StdCF /StrF /StdCF"),
2646 |b, _| {
2647 b.stream(
2648 4,
2649 "/Filter [/Crypt /ASCIIHexDecode]",
2650 b"73746F72656420617320686578>",
2651 );
2652 },
2653 );
2654 let doc = Document::load(data).expect("opens");
2655 assert_eq!(body_of(&doc, 4), b"stored as hex");
2656 }
2657
2658 #[test]
2662 fn a_stream_crypt_filter_naming_a_cf_entry_uses_the_file_key_as_is() {
2663 use crate::Document;
2664 let data = v4_fixture(
2665 16,
2666 &format!("/Length 128 {TWO_CF} /StmF /StdCF /StrF /StdCF"),
2667 |b, key| {
2668 b.stream(
2669 4,
2670 "/Filter /Crypt /DecodeParms << /Name /RcCF >>",
2671 &rc4(key, b"under the file key"),
2672 );
2673 },
2674 );
2675 let doc = Document::load(data).expect("opens");
2676 assert_eq!(body_of(&doc, 4), b"under the file key");
2677 }
2678
2679 fn encrypted_fixture_aesv3(r: i64) -> Vec<u8> {
2682 encrypted_fixture_aesv3_with(r, b"", b"")
2683 }
2684
2685 fn encrypted_fixture_aesv3_with(r: i64, user_pw: &[u8], owner_pw: &[u8]) -> Vec<u8> {
2686 encrypted_fixture_aesv3_with_metadata(r, user_pw, owner_pw, true, None)
2687 }
2688
2689 fn encrypted_fixture_aesv3_with_metadata(
2695 r: i64,
2696 user_pw: &[u8],
2697 owner_pw: &[u8],
2698 encrypt_metadata: bool,
2699 metadata: Option<&[u8]>,
2700 ) -> Vec<u8> {
2701 use pdfboss_testkit::PdfBuilder;
2702 let key = aesv3_file_key();
2703 let iv = [0x22u8; 16];
2704 let msg = aes_encrypt_pdf(&key, b"AES-256 secret", &iv);
2705 let stream = aes_encrypt_pdf(&key, b"AES-256 stream body", &iv);
2706
2707 let mut b = PdfBuilder::new().version(1, 7);
2708 let catalog = match metadata {
2709 Some(_) => "<< /Type /Catalog /Pages 2 0 R /Metadata 5 0 R >>",
2710 None => "<< /Type /Catalog /Pages 2 0 R >>",
2711 };
2712 b.object(1, catalog);
2713 b.object(2, "<< /Type /Pages /Kids [] /Count 0 >>");
2714 b.object(3, &format!("<< /Msg {} >>", hexstr(&msg)));
2715 b.stream(4, "", &stream);
2716 if let Some(metadata) = metadata {
2717 b.stream(5, "<< /Type /Metadata /Subtype /XML >>", metadata);
2718 }
2719 let encrypt_metadata_entry = if encrypt_metadata {
2720 ""
2721 } else {
2722 " /EncryptMetadata false"
2723 };
2724 b.object(
2725 9,
2726 &format!(
2727 "<< /Filter /Standard /V 5 /R {r} /Length 256 /P {P} {}{encrypt_metadata_entry} \
2728 /CF << /StdCF << /CFM /AESV3 /Length 32 >> >> /StmF /StdCF /StrF /StdCF >>",
2729 aesv3_password_entries(r, user_pw, owner_pw, &key),
2730 ),
2731 );
2732 let trailer = format!("/Encrypt 9 0 R /ID [{}{}]", hexstr(ID0), hexstr(ID0));
2733 b.trailer_extra(&trailer).build(1)
2734 }
2735
2736 fn aesv3_file_key() -> Vec<u8> {
2738 (0u8..32).map(|i| i ^ 0x5a).collect()
2739 }
2740
2741 fn aesv3_password_entries(r: i64, user_pw: &[u8], owner_pw: &[u8], key: &[u8]) -> String {
2744 let vsalt: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
2745 let ksalt: [u8; 8] = [9, 10, 11, 12, 13, 14, 15, 16];
2746 let mut u = hash_2b(r, user_pw, &vsalt, &[]); u.extend_from_slice(&vsalt);
2748 u.extend_from_slice(&ksalt);
2749 let intermediate = hash_2b(r, user_pw, &ksalt, &[]);
2750 let ue = aes_cbc_encrypt_blocks(&intermediate, &[0u8; 16], key);
2751 let ovsalt: [u8; 8] = [21, 22, 23, 24, 25, 26, 27, 28];
2753 let oksalt: [u8; 8] = [31, 32, 33, 34, 35, 36, 37, 38];
2754 let mut o = hash_2b(r, owner_pw, &ovsalt, &u[..48]);
2755 o.extend_from_slice(&ovsalt);
2756 o.extend_from_slice(&oksalt);
2757 let ointermediate = hash_2b(r, owner_pw, &oksalt, &u[..48]);
2758 let oe = aes_cbc_encrypt_blocks(&ointermediate, &[0u8; 16], key);
2759 format!(
2760 "/U {} /UE {} /O {} /OE {}",
2761 hexstr(&u),
2762 hexstr(&ue),
2763 hexstr(&o),
2764 hexstr(&oe)
2765 )
2766 }
2767
2768 #[test]
2772 fn an_indirect_cf_dictionary_is_followed() {
2773 use crate::Document;
2774 use pdfboss_testkit::PdfBuilder;
2775 let key = aesv3_file_key();
2776 let stream = aes_encrypt_pdf(&key, b"AES-256 stream body", &[0x22u8; 16]);
2777 let mut b = PdfBuilder::new().version(1, 7);
2778 b.object(1, "<< /Type /Catalog /Pages 2 0 R >>");
2779 b.object(2, "<< /Type /Pages /Kids [] /Count 0 >>");
2780 b.stream(4, "", &stream);
2781 b.object(8, "<< /StdCF << /CFM /AESV3 /Length 32 >> >>");
2782 b.object(
2783 9,
2784 &format!(
2785 "<< /Filter /Standard /V 5 /R 6 /Length 256 /P {P} {} \
2786 /CF 8 0 R /StmF /StdCF /StrF /StdCF >>",
2787 aesv3_password_entries(6, b"", b"", &key),
2788 ),
2789 );
2790 let trailer = format!("/Encrypt 9 0 R /ID [{}{}]", hexstr(ID0), hexstr(ID0));
2791 let doc = Document::load(b.trailer_extra(&trailer).build(1))
2792 .expect("an indirect /CF still names the filters");
2793 assert_eq!(body_of(&doc, 4), b"AES-256 stream body");
2794 }
2795
2796 #[test]
2799 fn aesv3_identity_string_filter_leaves_strings_as_stored() {
2800 use crate::Document;
2801 use pdfboss_testkit::PdfBuilder;
2802 let key = aesv3_file_key();
2803 let stream = aes_encrypt_pdf(&key, b"AES-256 stream body", &[0x22u8; 16]);
2804 let mut b = PdfBuilder::new().version(1, 7);
2805 b.object(1, "<< /Type /Catalog /Pages 2 0 R >>");
2806 b.object(2, "<< /Type /Pages /Kids [] /Count 0 >>");
2807 b.object(3, "<< /Msg (stored in the clear) >>");
2808 b.stream(4, "", &stream);
2809 b.object(
2810 9,
2811 &format!(
2812 "<< /Filter /Standard /V 5 /R 6 /Length 256 /P {P} {} \
2813 /CF << /StdCF << /CFM /AESV3 /Length 32 >> >> /StmF /StdCF /StrF /Identity >>",
2814 aesv3_password_entries(6, b"", b"", &key),
2815 ),
2816 );
2817 let trailer = format!("/Encrypt 9 0 R /ID [{}{}]", hexstr(ID0), hexstr(ID0));
2818 let doc = Document::load(b.trailer_extra(&trailer).build(1))
2819 .expect("an Identity string filter is a valid V5 file");
2820 assert_eq!(msg_of(&doc, 3), b"stored in the clear");
2821 assert_eq!(body_of(&doc, 4), b"AES-256 stream body");
2822 }
2823
2824 fn assert_aesv3_decrypts(r: i64) {
2825 use crate::object::ObjRef;
2826 use crate::Document;
2827 let doc = Document::load(encrypted_fixture_aesv3(r)).expect("AESV3 empty password opens");
2828 let obj3 = doc.get(ObjRef { num: 3, gen: 0 }).unwrap();
2829 let msg = obj3
2830 .as_dict()
2831 .unwrap()
2832 .get("Msg")
2833 .unwrap()
2834 .as_str_bytes()
2835 .unwrap();
2836 assert_eq!(msg, b"AES-256 secret", "R{r} string");
2837 let obj4 = doc.get(ObjRef { num: 4, gen: 0 }).unwrap();
2838 assert_eq!(
2839 doc.stream_data(obj4.as_stream().unwrap()).unwrap(),
2840 b"AES-256 stream body",
2841 "R{r} stream"
2842 );
2843 }
2844
2845 #[test]
2847 fn document_load_decrypts_aesv3_r5() {
2848 assert_aesv3_decrypts(5);
2849 }
2850
2851 #[test]
2853 fn document_load_decrypts_aesv3_r6() {
2854 assert_aesv3_decrypts(6); }
2856
2857 #[test]
2859 fn encrypt_metadata_false_leaves_the_metadata_stream_plaintext() {
2860 use crate::object::ObjRef;
2861 use crate::Document;
2862
2863 const XMP: &[u8] = b"<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>\
2864 <x:xmpmeta xmlns:x='adobe:ns:meta/'><rdf:RDF \
2865 xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'><rdf:Description \
2866 xmlns:dc='http://purl.org/dc/elements/1.1/'><dc:title>XMP Secret \
2867 Title</dc:title></rdf:Description></rdf:RDF></x:xmpmeta><?xpacket end='w'?>";
2868
2869 let bytes =
2870 encrypted_fixture_aesv3_with_metadata(6, b"user-pw", b"owner-pw", false, Some(XMP));
2871 let doc = Document::load_with_password(bytes, "user-pw").expect("user password opens");
2872
2873 let obj3 = doc.get(ObjRef { num: 3, gen: 0 }).unwrap();
2874 let msg = obj3.as_dict().unwrap().get("Msg").unwrap();
2875 assert_eq!(
2876 msg.as_str_bytes().unwrap(),
2877 b"AES-256 secret",
2878 "an ordinary string still decrypts under EncryptMetadata false"
2879 );
2880
2881 let obj5 = doc.get(ObjRef { num: 5, gen: 0 }).unwrap();
2882 let metadata = doc.stream_data(obj5.as_stream().unwrap()).unwrap();
2883 assert_eq!(
2884 metadata, XMP,
2885 "the metadata stream was stored in plaintext and must not be decrypted"
2886 );
2887 }
2888
2889 #[test]
2900 fn r6_key_material_opens_under_aesv3_key() {
2901 let mut c = 0u8;
2902 let mut rng = |b: &mut [u8]| {
2903 for x in b {
2904 c = c.wrapping_add(1);
2905 *x = c;
2906 }
2907 };
2908 let material = r6_key_material(b"user-pw", b"owner-pw", P, true, &mut rng);
2909 let dict = aes256_encrypt_dict(&material, P);
2910
2911 let user_key = aesv3_key(&dict, 6, b"user-pw").expect("user password opens");
2912 assert_eq!(user_key, material.file_key.to_vec());
2913
2914 let owner_key = aesv3_key(&dict, 6, b"owner-pw").expect("owner password opens");
2915 assert_eq!(owner_key, material.file_key.to_vec());
2916
2917 assert!(aesv3_key(&dict, 6, b"wrong-pw").is_none());
2918
2919 assert!(perms_marker_valid(&material.file_key, &material.perms));
2920
2921 let mut without_perms = dict.clone();
2926 without_perms.remove("Perms");
2927 assert_eq!(
2928 aesv3_key(&without_perms, 6, b"user-pw"),
2929 Some(material.file_key.to_vec())
2930 );
2931 assert_eq!(
2932 aesv3_key(&without_perms, 6, b"owner-pw"),
2933 Some(material.file_key.to_vec())
2934 );
2935 }
2936
2937 #[test]
2940 fn permissions_all_grants_every_bit() {
2941 assert_eq!(Permissions::all().p_value(), -4);
2943 assert_eq!(Permissions::default().p_value(), -4);
2944 }
2945
2946 #[test]
2947 fn permissions_p_value_clears_exactly_its_own_bit() {
2948 let base = Permissions::all().p_value();
2949 assert_eq!(
2950 Permissions {
2951 print: false,
2952 ..Permissions::all()
2953 }
2954 .p_value(),
2955 base & !(1 << 2), );
2957 assert_eq!(
2958 Permissions {
2959 modify: false,
2960 ..Permissions::all()
2961 }
2962 .p_value(),
2963 base & !(1 << 3), );
2965 assert_eq!(
2966 Permissions {
2967 copy: false,
2968 ..Permissions::all()
2969 }
2970 .p_value(),
2971 base & !(1 << 4), );
2973 assert_eq!(
2974 Permissions {
2975 annotate: false,
2976 ..Permissions::all()
2977 }
2978 .p_value(),
2979 base & !(1 << 5), );
2981 assert_eq!(
2982 Permissions {
2983 fill_forms: false,
2984 ..Permissions::all()
2985 }
2986 .p_value(),
2987 base & !(1 << 8), );
2989 assert_eq!(
2990 Permissions {
2991 accessibility: false,
2992 ..Permissions::all()
2993 }
2994 .p_value(),
2995 base & !(1 << 9), );
2997 assert_eq!(
2998 Permissions {
2999 assemble: false,
3000 ..Permissions::all()
3001 }
3002 .p_value(),
3003 base & !(1 << 10), );
3005 assert_eq!(
3006 Permissions {
3007 print_hires: false,
3008 ..Permissions::all()
3009 }
3010 .p_value(),
3011 base & !(1 << 11), );
3013 }
3014
3015 #[allow(clippy::type_complexity, reason = "see Encryptor's rng field")]
3021 fn counter_rng() -> Box<dyn FnMut(&mut [u8]) + Send> {
3022 let mut c = 0u8;
3023 Box::new(move |buf: &mut [u8]| {
3024 for b in buf {
3025 c = c.wrapping_add(1);
3026 *b = c;
3027 }
3028 })
3029 }
3030
3031 fn decryptor_for(dict: &Dict, password: &[u8]) -> Decryptor {
3036 let key = aesv3_key(dict, 6, password).expect("password opens the produced dict");
3037 Decryptor {
3038 key,
3039 filters: CryptFilters::uniform(Cipher::Aesv3),
3040 encrypt_metadata: true,
3041 }
3042 }
3043
3044 #[test]
3045 fn encrypt_object_round_trips_dict_array_and_leaves_other_types_untouched() {
3046 use crate::object::ObjRef;
3047
3048 let (mut enc, dict) =
3049 Encryptor::aes256_with_rng("user-pw", "owner-pw", Permissions::all(), counter_rng());
3050
3051 let mut d = Dict::new();
3052 d.insert(
3053 Name("Msg".to_string()),
3054 Object::String(b"Top secret message".to_vec()),
3055 );
3056 d.insert(
3057 Name("List".to_string()),
3058 Object::Array(vec![
3059 Object::String(b"first".to_vec()),
3060 Object::String(b"second".to_vec()),
3061 ]),
3062 );
3063 d.insert(
3064 Name("Ref".to_string()),
3065 Object::Ref(ObjRef { num: 7, gen: 0 }),
3066 );
3067 d.insert(
3068 Name("Kind".to_string()),
3069 Object::Name(Name("Example".to_string())),
3070 );
3071 d.insert(Name("Count".to_string()), Object::Int(42));
3072 d.insert(Name("Scale".to_string()), Object::Real(1.5));
3073 d.insert(Name("On".to_string()), Object::Bool(true));
3074 d.insert(Name("Missing".to_string()), Object::Null);
3075 let original = Object::Dict(d);
3076
3077 let mut obj = original.clone();
3078 enc.encrypt_object(&mut obj, 3, 0);
3079 assert_ne!(obj, original, "encryption must change the strings");
3080
3081 let (enc_dict, orig_dict) = (obj.as_dict().unwrap(), original.as_dict().unwrap());
3084 for key in ["Ref", "Kind", "Count", "Scale", "On", "Missing"] {
3085 assert_eq!(
3086 enc_dict.get(key),
3087 orig_dict.get(key),
3088 "{key} passes through untouched"
3089 );
3090 }
3091
3092 let decryptor = decryptor_for(&dict, b"user-pw");
3093 let mut roundtripped = obj.clone();
3094 decryptor.decrypt_object(&mut roundtripped, 3, 0);
3095 assert_eq!(roundtripped, original);
3096
3097 let owner_decryptor = decryptor_for(&dict, b"owner-pw");
3099 let mut via_owner = obj;
3100 owner_decryptor.decrypt_object(&mut via_owner, 3, 0);
3101 assert_eq!(via_owner, original);
3102 }
3103
3104 #[test]
3105 fn encrypt_object_round_trips_a_stream_and_its_dict() {
3106 use crate::object::Stream;
3107
3108 let (mut enc, dict) =
3109 Encryptor::aes256_with_rng("", "owner-pw", Permissions::all(), counter_rng());
3110
3111 let mut stream_dict = Dict::new();
3112 stream_dict.insert(
3113 Name("Producer".to_string()),
3114 Object::String(b"pdfboss".to_vec()),
3115 );
3116 let original = Object::Stream(Stream {
3117 dict: stream_dict,
3118 data: b"decrypted stream body".to_vec(),
3119 });
3120 let mut obj = original.clone();
3121 enc.encrypt_object(&mut obj, 4, 0);
3122 let encrypted = obj.as_stream().unwrap();
3123 assert_ne!(encrypted.data, original.as_stream().unwrap().data);
3124 assert_ne!(
3125 encrypted.dict.get("Producer"),
3126 original.as_stream().unwrap().dict.get("Producer"),
3127 "the stream dict's own strings are encrypted too"
3128 );
3129
3130 let decryptor = decryptor_for(&dict, b"");
3131 let mut roundtripped = obj;
3132 decryptor.decrypt_object(&mut roundtripped, 4, 0);
3133 assert_eq!(roundtripped, original);
3134 }
3135
3136 #[test]
3140 fn encrypt_object_leaves_an_identity_crypt_stream_as_stored() {
3141 use crate::object::Stream;
3142
3143 let (mut enc, dict) =
3144 Encryptor::aes256_with_rng("", "owner-pw", Permissions::all(), counter_rng());
3145 let mut stream_dict = Dict::new();
3146 stream_dict.insert(
3147 Name("Filter".to_string()),
3148 Object::Name(Name("Crypt".to_string())),
3149 );
3150 let mut parms = Dict::new();
3151 parms.insert(
3152 Name("Name".to_string()),
3153 Object::Name(Name("Identity".to_string())),
3154 );
3155 stream_dict.insert(Name("DecodeParms".to_string()), Object::Dict(parms));
3156 let original = Object::Stream(Stream {
3157 dict: stream_dict,
3158 data: b"<?xpacket?> metadata in the clear".to_vec(),
3159 });
3160
3161 let mut obj = original.clone();
3162 enc.encrypt_object(&mut obj, 6, 0);
3163 assert_eq!(obj, original, "an Identity stream is written as stored");
3164
3165 let decryptor = decryptor_for(&dict, b"");
3166 decryptor.decrypt_object(&mut obj, 6, 0);
3167 assert_eq!(obj, original, "and read back as stored");
3168 }
3169
3170 #[test]
3171 fn encrypt_object_round_trips_padding_edge_lengths() {
3172 let (mut enc, dict) =
3173 Encryptor::aes256_with_rng("pw", "owner", Permissions::all(), counter_rng());
3174 let decryptor = decryptor_for(&dict, b"pw");
3175
3176 for plaintext in [Vec::new(), vec![0x41], vec![0x42; 16]] {
3177 let original = Object::String(plaintext.clone());
3178 let mut obj = original.clone();
3179 enc.encrypt_object(&mut obj, 1, 0);
3180 let mut roundtripped = obj;
3181 decryptor.decrypt_object(&mut roundtripped, 1, 0);
3182 assert_eq!(roundtripped, original, "{} bytes", plaintext.len());
3183 }
3184 }
3185}