1use crate::crypto::DecryptionError::InvalidEncryption;
9use crate::crypto::aes::{AES128Cipher, AES256Cipher};
10use crate::crypto::rc4::Rc4;
11use crate::object;
12use crate::object::dict::keys::{
13 CF, CFM, ENCRYPT_META_DATA, FILTER, IDENTITY, LENGTH, O, OE, P, R, STM_F, STR_F, U, UE, V,
14};
15use crate::object::{Dict, Name, ObjectIdentifier};
16use crate::sync::HashMap;
17use alloc::vec;
18use alloc::vec::Vec;
19use core::cmp;
20use core::ops::Deref;
21
22mod aes;
23mod md5;
24mod rc4;
25mod sha256;
26mod sha384;
27mod sha512;
28
29const PASSWORD_PADDING: [u8; 32] = [
30 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
31 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A,
32];
33
34#[derive(Debug, Copy, Clone, PartialEq, Eq)]
36pub enum DecryptionError {
37 MissingIDEntry,
39 PasswordProtected,
42 InvalidEncryption,
44 UnsupportedAlgorithm,
46}
47
48#[derive(Debug, Copy, Clone, PartialEq, Eq)]
49enum DecryptorTag {
50 None,
51 Rc4,
52 Aes128,
53 Aes256,
54}
55
56impl DecryptorTag {
57 fn from_name(name: &Name<'_>) -> Option<Self> {
58 match name.as_str() {
59 "None" | "Identity" => Some(Self::None),
60 "V2" => Some(Self::Rc4),
61 "AESV2" => Some(Self::Aes128),
62 "AESV3" => Some(Self::Aes256),
63 _ => None,
64 }
65 }
66}
67#[derive(Debug, Clone)]
68pub(crate) enum Decryptor {
69 None,
70 Rc4 { key: Vec<u8> },
71 Aes128 { key: Vec<u8>, dict: DecryptorData },
72 Aes256 { key: Vec<u8>, dict: DecryptorData },
73}
74
75#[derive(Debug, Copy, Clone)]
76pub(crate) enum DecryptionTarget<'a> {
77 String,
78 Stream,
79 Named(&'a [u8]),
80}
81
82impl Decryptor {
83 pub(crate) fn decrypt(
84 &self,
85 id: ObjectIdentifier,
86 data: &[u8],
87 target: DecryptionTarget<'_>,
88 ) -> Option<Vec<u8>> {
89 if matches!(target, DecryptionTarget::Named(IDENTITY)) {
90 return Some(data.to_vec());
91 }
92
93 match self {
94 Self::None => Some(data.to_vec()),
95 Self::Rc4 { key } => match target {
96 DecryptionTarget::Named(_) => None,
97 _ => decrypt_rc4(key, data, id),
98 },
99 Self::Aes128 { key, dict } | Self::Aes256 { key, dict } => {
100 let crypt_dict = match target {
101 DecryptionTarget::String => dict.string_filter,
102 DecryptionTarget::Stream => dict.stream_filter,
103 DecryptionTarget::Named(name) => *dict.crypt_filters.get(name)?,
104 };
105
106 match crypt_dict.cfm {
107 DecryptorTag::None => Some(data.to_vec()),
108 DecryptorTag::Rc4 => decrypt_rc4(key, data, id),
109 DecryptorTag::Aes128 => decrypt_aes128(key, data, id),
110 DecryptorTag::Aes256 => decrypt_aes256(key, data),
111 }
112 }
113 }
114 }
115}
116
117pub(crate) fn get(
118 dict: &Dict<'_>,
119 id: &[u8],
120 password: &[u8],
121) -> Result<Decryptor, DecryptionError> {
122 let filter = dict.get::<Name<'_>>(FILTER).ok_or(InvalidEncryption)?;
123
124 if filter.deref() != b"Standard" {
125 return Err(DecryptionError::UnsupportedAlgorithm);
126 }
127
128 let encryption_v = dict.get::<u8>(V).ok_or(InvalidEncryption)?;
129 let encrypt_metadata = dict.get::<bool>(ENCRYPT_META_DATA).unwrap_or(true);
130 let revision = dict.get::<u8>(R).ok_or(InvalidEncryption)?;
131 let length = match encryption_v {
132 1 => 40,
133 2 => dict.get::<u16>(LENGTH).unwrap_or(40),
134 4 => dict.get::<u16>(LENGTH).unwrap_or(128),
135 5 => 256,
136 _ => return Err(DecryptionError::UnsupportedAlgorithm),
137 };
138
139 let (algorithm, data) = match encryption_v {
140 1 => (DecryptorTag::Rc4, None),
141 2 => (DecryptorTag::Rc4, None),
142 4 => (
143 DecryptorTag::Aes128,
144 Some(DecryptorData::from_dict(dict, length).ok_or(InvalidEncryption)?),
145 ),
146 5 | 6 => (
147 DecryptorTag::Aes256,
148 Some(DecryptorData::from_dict(dict, length).ok_or(InvalidEncryption)?),
149 ),
150 _ => {
151 return Err(DecryptionError::UnsupportedAlgorithm);
152 }
153 };
154
155 let byte_length = length / 8;
156 if byte_length == 0 {
157 return Err(InvalidEncryption);
158 }
159
160 let owner_string = dict.get::<object::String<'_>>(O).ok_or(InvalidEncryption)?;
161 let user_string = dict.get::<object::String<'_>>(U).ok_or(InvalidEncryption)?;
162 let permissions = {
163 let raw = dict.get::<i64>(P).ok_or(InvalidEncryption)?;
164
165 if raw < 0 {
166 u32::from_be_bytes((raw as i32).to_be_bytes())
167 } else {
168 raw as u32
169 }
170 };
171
172 let mut decryption_key = if revision <= 4 {
173 let key = decryption_key_rev1234(
174 password,
175 encrypt_metadata,
176 revision,
177 byte_length,
178 &owner_string,
179 permissions,
180 id,
181 )?;
182 authenticate_user_password_rev234(revision, &key, id, &user_string)?;
183
184 key
185 } else {
186 decryption_key_rev56(dict, revision, password, &owner_string, &user_string)?
187 };
188
189 if encryption_v == 4 && decryption_key.len() < 16 {
191 decryption_key.resize(16, 0);
192 }
193
194 match algorithm {
195 DecryptorTag::None => Ok(Decryptor::None),
196 DecryptorTag::Rc4 => Ok(Decryptor::Rc4 {
197 key: decryption_key,
198 }),
199 DecryptorTag::Aes128 => Ok(Decryptor::Aes128 {
200 key: decryption_key,
201 dict: data.unwrap(),
202 }),
203 DecryptorTag::Aes256 => Ok(Decryptor::Aes256 {
204 key: decryption_key,
205 dict: data.unwrap(),
206 }),
207 }
208}
209
210fn decrypt_aes256(key: &[u8], data: &[u8]) -> Option<Vec<u8>> {
212 let (iv, data) = data.split_at_checked(16)?;
219 let iv: [u8; 16] = iv.try_into().ok()?;
220 let cipher = AES256Cipher::new(key)?;
221 Some(cipher.decrypt_cbc(data, &iv, true))
222}
223
224fn decrypt_aes128(key: &[u8], data: &[u8], id: ObjectIdentifier) -> Option<Vec<u8>> {
225 decrypt_rc_aes(key, id, true, |key| {
226 let cipher = AES128Cipher::new(key)?;
230 let (iv, data) = data.split_at_checked(16)?;
231 let iv: [u8; 16] = iv.try_into().ok()?;
232
233 Some(cipher.decrypt_cbc(data, &iv, true))
234 })
235}
236
237fn decrypt_rc4(key: &[u8], data: &[u8], id: ObjectIdentifier) -> Option<Vec<u8>> {
238 decrypt_rc_aes(key, id, false, |key| {
239 let mut rc = Rc4::new(key);
240 Some(rc.decrypt(data))
241 })
242}
243
244fn decrypt_rc_aes(
246 key: &[u8],
247 id: ObjectIdentifier,
248 aes: bool,
249 with_key: impl FnOnce(&[u8]) -> Option<Vec<u8>>,
250) -> Option<Vec<u8>> {
251 let n = key.len();
252 let mut key = key.to_vec();
257
258 key.extend(&id.obj_number.to_le_bytes()[..3]);
264 key.extend(&id.gen_number.to_le_bytes()[..2]);
265
266 if aes {
270 key.extend(b"sAlT");
271 }
272
273 let hash = md5::calculate(&key);
276
277 let final_key = &hash[..cmp::min(16, n + 5)];
281
282 with_key(final_key)
283}
284
285#[derive(Debug, Clone)]
286pub(crate) struct DecryptorData {
287 stream_filter: CryptDictionary,
288 string_filter: CryptDictionary,
289 crypt_filters: HashMap<Vec<u8>, CryptDictionary>,
290}
291
292impl DecryptorData {
293 fn from_dict(dict: &Dict<'_>, default_length: u16) -> Option<Self> {
294 let mut mappings = HashMap::new();
295
296 if let Some(dict) = dict.get::<Dict<'_>>(CF) {
297 for key in dict.keys() {
298 if let Some(dict) = dict.get::<Dict<'_>>(key.as_ref())
299 && let Some(crypt_dict) = CryptDictionary::from_dict(&dict, default_length)
300 {
301 mappings.insert(key.to_vec(), crypt_dict);
302 }
303 }
304 }
305
306 let stm_f = *mappings
307 .get(dict.get::<Name<'_>>(STM_F)?.deref())
308 .unwrap_or(&CryptDictionary::identity(default_length));
309 let str_f = *mappings
310 .get(dict.get::<Name<'_>>(STR_F)?.deref())
311 .unwrap_or(&CryptDictionary::identity(default_length));
312
313 Some(Self {
314 stream_filter: stm_f,
315 string_filter: str_f,
316 crypt_filters: mappings,
317 })
318 }
319}
320
321#[derive(Debug, Copy, Clone)]
322struct CryptDictionary {
323 cfm: DecryptorTag,
324 _length: u16,
325}
326
327impl CryptDictionary {
328 fn from_dict(dict: &Dict<'_>, default_length: u16) -> Option<Self> {
329 let cfm = DecryptorTag::from_name(&dict.get::<Name<'_>>(CFM)?)?;
330 let mut length = dict.get::<u16>(LENGTH).unwrap_or(default_length / 8);
335
336 if cfm == DecryptorTag::Aes128 {
339 length = 16;
340 } else if cfm == DecryptorTag::Aes256 {
341 length = 32;
342 }
343
344 Some(Self {
345 cfm,
346 _length: length,
347 })
348 }
349
350 fn identity(default_length: u16) -> Self {
351 Self {
352 cfm: DecryptorTag::None,
353 _length: default_length,
354 }
355 }
356}
357
358fn compute_hash_rev56(
360 password: &[u8],
361 validation_salt: &[u8],
362 user_string: Option<&[u8]>,
363 revision: u8,
364) -> Result<[u8; 32], DecryptionError> {
365 let mut k = {
368 let mut input = Vec::new();
369 input.extend_from_slice(password);
370 input.extend_from_slice(validation_salt);
371
372 if let Some(user_string) = user_string {
373 input.extend_from_slice(user_string);
374 }
375
376 let hash = sha256::calculate(&input);
377
378 if revision == 5 {
380 return Ok(hash);
381 }
382
383 hash.to_vec()
384 };
385
386 let mut round: u16 = 0;
387
388 loop {
390 let k1 = {
396 let mut single: Vec<u8> = vec![];
397 single.extend(password);
398 single.extend(&k);
399
400 if let Some(user_string) = user_string {
401 single.extend(user_string);
402 }
403
404 single.repeat(64)
405 };
406
407 let e = {
411 let aes = AES128Cipher::new(&k[..16]).ok_or(InvalidEncryption)?;
412 let mut res = aes.encrypt_cbc(&k1, &k[16..32].try_into().unwrap());
413
414 res.truncate(k1.len());
416
417 res
418 };
419
420 let num = u128::from_be_bytes(e[..16].try_into().unwrap()) % 3;
425
426 k = match num {
429 0 => sha256::calculate(&e).to_vec(),
430 1 => sha384::calculate(&e).to_vec(),
431 2 => sha512::calculate(&e).to_vec(),
432 _ => unreachable!(),
433 };
434
435 round += 1;
436
437 if round > 63 {
441 let last_byte = *e.last().unwrap();
445
446 if (last_byte as u16) <= round - 32 {
450 break;
451 }
452 }
453 }
454
455 let mut result = [0_u8; 32];
457 result.copy_from_slice(&k[..32]);
458 Ok(result)
459}
460
461fn decryption_key_rev1234(
463 password: &[u8],
464 encrypt_metadata: bool,
465 revision: u8,
466 byte_length: u16,
467 owner_string: &object::String<'_>,
468 permissions: u32,
469 id: &[u8],
470) -> Result<Vec<u8>, DecryptionError> {
471 let mut md5_input = vec![];
472
473 let mut padded_password = [0_u8; 32];
476 let copy_len = password.len().min(32);
477 padded_password[..copy_len].copy_from_slice(&password[..copy_len]);
478 if copy_len < 32 {
479 padded_password[copy_len..].copy_from_slice(&PASSWORD_PADDING[..(32 - copy_len)]);
480 }
481
482 md5_input.extend(&padded_password);
485
486 md5_input.extend(owner_string.as_ref());
489
490 md5_input.extend(permissions.to_le_bytes());
493
494 md5_input.extend(id);
496
497 if !encrypt_metadata && revision >= 4 {
500 md5_input.extend(&[0xff, 0xff, 0xff, 0xff]);
501 }
502
503 let mut hash = md5::calculate(&md5_input);
505
506 if byte_length as usize > hash.len() {
507 return Err(InvalidEncryption);
508 }
509
510 if revision >= 3 {
515 for _ in 0..50 {
516 hash = md5::calculate(&hash[..byte_length as usize]);
517 }
518 }
519
520 let decryption_key = hash[..byte_length as usize].to_vec();
521 Ok(decryption_key)
522}
523
524fn authenticate_user_password_rev234(
526 revision: u8,
527 decryption_key: &[u8],
528 id: &[u8],
529 user_string: &object::String<'_>,
530) -> Result<(), DecryptionError> {
531 let result = match revision {
533 2 => user_password_rev2(decryption_key),
534 3 | 4 => user_password_rev34(decryption_key, id),
535 _ => return Err(InvalidEncryption),
536 };
537
538 match revision {
542 2 => {
543 if result.as_slice() != user_string.as_ref() {
544 return Err(DecryptionError::PasswordProtected);
545 }
546 }
547 3 | 4 => {
548 if Some(&result[..16]) != user_string.as_ref().get(0..16) {
549 return Err(DecryptionError::PasswordProtected);
550 }
551 }
552 _ => unreachable!(),
553 }
554
555 Ok(())
556}
557
558fn user_password_rev2(decryption_key: &[u8]) -> Vec<u8> {
561 let mut rc = Rc4::new(decryption_key);
565 rc.decrypt(&PASSWORD_PADDING)
566}
567
568fn user_password_rev34(decryption_key: &[u8], id: &[u8]) -> Vec<u8> {
571 let mut rc = Rc4::new(decryption_key);
573
574 let mut input = vec![];
575 input.extend(PASSWORD_PADDING);
577
578 input.extend(id);
581 let hash = md5::calculate(&input);
582
583 let mut encrypted = rc.encrypt(&hash);
586
587 for i in 1..=19 {
593 let mut key = decryption_key.to_vec();
594 for byte in &mut key {
595 *byte ^= i;
596 }
597
598 let mut rc = Rc4::new(&key);
599 encrypted = rc.encrypt(&encrypted);
600 }
601
602 encrypted.resize(32, 0);
603 encrypted
604}
605
606fn decryption_key_rev56(
608 dict: &Dict<'_>,
609 revision: u8,
610 password: &[u8],
611 owner_string: &object::String<'_>,
612 user_string: &object::String<'_>,
613) -> Result<Vec<u8>, DecryptionError> {
614 let password = &password[..password.len().min(127)];
620
621 let string_len = if revision <= 4 { 32 } else { 48 };
622
623 let trimmed_os = owner_string.get(..string_len).ok_or(InvalidEncryption)?;
624
625 let (owner_hash, owner_tail) = trimmed_os.split_at_checked(32).ok_or(InvalidEncryption)?;
626 let (owner_validation_salt, owner_key_salt) =
627 owner_tail.split_at_checked(8).ok_or(InvalidEncryption)?;
628
629 let trimmed_us = user_string.get(..string_len).ok_or(InvalidEncryption)?;
630 let (user_hash, user_tail) = trimmed_us.split_at_checked(32).ok_or(InvalidEncryption)?;
631 let (user_validation_salt, user_key_salt) =
632 user_tail.split_at_checked(8).ok_or(InvalidEncryption)?;
633
634 if compute_hash_rev56(password, owner_validation_salt, Some(trimmed_us), revision)?
639 == owner_hash
640 {
641 let intermediate_owner_key =
646 compute_hash_rev56(password, owner_key_salt, Some(trimmed_us), revision)?;
647
648 let oe_string = dict
649 .get::<object::String<'_>>(OE)
650 .ok_or(InvalidEncryption)?;
651
652 if oe_string.len() != 32 {
653 return Err(InvalidEncryption);
654 }
655
656 let cipher = AES256Cipher::new(&intermediate_owner_key).ok_or(InvalidEncryption)?;
657 let zero_iv = [0_u8; 16];
658
659 Ok(cipher.decrypt_cbc(&oe_string, &zero_iv, false))
660 } else if compute_hash_rev56(password, user_validation_salt, None, revision)? == user_hash {
661 let intermediate_key = compute_hash_rev56(password, user_key_salt, None, revision)?;
666
667 let ue_string = dict
668 .get::<object::String<'_>>(UE)
669 .ok_or(InvalidEncryption)?;
670
671 if ue_string.len() != 32 {
672 return Err(InvalidEncryption);
673 }
674
675 let cipher = AES256Cipher::new(&intermediate_key).ok_or(InvalidEncryption)?;
676 let zero_iv = [0_u8; 16];
677
678 Ok(cipher.decrypt_cbc(&ue_string, &zero_iv, false))
679 } else {
680 Err(DecryptionError::PasswordProtected)
681 }
682
683 }