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, 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::string::ToString;
18use alloc::vec;
19use alloc::vec::Vec;
20use core::cmp;
21use core::ops::Deref;
22
23mod aes;
24mod md5;
25mod rc4;
26mod sha256;
27mod sha384;
28mod sha512;
29
30const PASSWORD_PADDING: [u8; 32] = [
31 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
32 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A,
33];
34
35#[derive(Debug, Copy, Clone, PartialEq, Eq)]
37pub enum DecryptionError {
38 MissingIDEntry,
40 PasswordProtected,
43 InvalidEncryption,
45 UnsupportedAlgorithm,
47}
48
49#[derive(Debug, Copy, Clone, PartialEq, Eq)]
50enum DecryptorTag {
51 None,
52 Rc4,
53 Aes128,
54 Aes256,
55}
56
57impl DecryptorTag {
58 fn from_name(name: &Name<'_>) -> Option<Self> {
59 match name.as_str() {
60 "None" | "Identity" => Some(Self::None),
61 "V2" => Some(Self::Rc4),
62 "AESV2" => Some(Self::Aes128),
63 "AESV3" => Some(Self::Aes256),
64 _ => None,
65 }
66 }
67}
68#[derive(Debug, Clone)]
69pub(crate) enum Decryptor {
70 None,
71 Rc4 { key: Vec<u8> },
72 Aes128 { key: Vec<u8>, dict: DecryptorData },
73 Aes256 { key: Vec<u8>, dict: DecryptorData },
74}
75
76#[derive(Debug, Copy, Clone)]
77pub(crate) enum DecryptionTarget {
78 String,
79 Stream,
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 match self {
90 Self::None => Some(data.to_vec()),
91 Self::Rc4 { key } => decrypt_rc4(key, data, id),
92 Self::Aes128 { key, dict } | Self::Aes256 { key, dict } => {
93 let crypt_dict = match target {
94 DecryptionTarget::String => dict.string_filter,
95 DecryptionTarget::Stream => dict.stream_filter,
96 };
97
98 match crypt_dict.cfm {
99 DecryptorTag::None => Some(data.to_vec()),
100 DecryptorTag::Rc4 => decrypt_rc4(key, data, id),
101 DecryptorTag::Aes128 => decrypt_aes128(key, data, id),
102 DecryptorTag::Aes256 => decrypt_aes256(key, data),
103 }
104 }
105 }
106 }
107}
108
109pub(crate) fn get(
110 dict: &Dict<'_>,
111 id: &[u8],
112 password: &[u8],
113) -> Result<Decryptor, DecryptionError> {
114 let filter = dict.get::<Name<'_>>(FILTER).ok_or(InvalidEncryption)?;
115
116 if filter.deref() != b"Standard" {
117 return Err(DecryptionError::UnsupportedAlgorithm);
118 }
119
120 let encryption_v = dict.get::<u8>(V).ok_or(InvalidEncryption)?;
121 let encrypt_metadata = dict.get::<bool>(ENCRYPT_META_DATA).unwrap_or(true);
122 let revision = dict.get::<u8>(R).ok_or(InvalidEncryption)?;
123 let length = match encryption_v {
124 1 => 40,
125 2 => dict.get::<u16>(LENGTH).unwrap_or(40),
126 4 => dict.get::<u16>(LENGTH).unwrap_or(128),
127 5 => 256,
128 _ => return Err(DecryptionError::UnsupportedAlgorithm),
129 };
130
131 let (algorithm, data) = match encryption_v {
132 1 => (DecryptorTag::Rc4, None),
133 2 => (DecryptorTag::Rc4, None),
134 4 => (
135 DecryptorTag::Aes128,
136 Some(DecryptorData::from_dict(dict, length).ok_or(InvalidEncryption)?),
137 ),
138 5 | 6 => (
139 DecryptorTag::Aes256,
140 Some(DecryptorData::from_dict(dict, length).ok_or(InvalidEncryption)?),
141 ),
142 _ => {
143 return Err(DecryptionError::UnsupportedAlgorithm);
144 }
145 };
146
147 let byte_length = length / 8;
148 if byte_length == 0 {
149 return Err(InvalidEncryption);
150 }
151
152 let owner_string = dict.get::<object::String<'_>>(O).ok_or(InvalidEncryption)?;
153 let user_string = dict.get::<object::String<'_>>(U).ok_or(InvalidEncryption)?;
154 let permissions = {
155 let raw = dict.get::<i64>(P).ok_or(InvalidEncryption)?;
156
157 if raw < 0 {
158 u32::from_be_bytes((raw as i32).to_be_bytes())
159 } else {
160 raw as u32
161 }
162 };
163
164 let mut decryption_key = if revision <= 4 {
165 let key = decryption_key_rev1234(
166 password,
167 encrypt_metadata,
168 revision,
169 byte_length,
170 &owner_string,
171 permissions,
172 id,
173 )?;
174 authenticate_user_password_rev234(revision, &key, id, &user_string)?;
175
176 key
177 } else {
178 decryption_key_rev56(dict, revision, password, &owner_string, &user_string)?
179 };
180
181 if encryption_v == 4 && decryption_key.len() < 16 {
183 decryption_key.resize(16, 0);
184 }
185
186 match algorithm {
187 DecryptorTag::None => Ok(Decryptor::None),
188 DecryptorTag::Rc4 => Ok(Decryptor::Rc4 {
189 key: decryption_key,
190 }),
191 DecryptorTag::Aes128 => Ok(Decryptor::Aes128 {
192 key: decryption_key,
193 dict: data.unwrap(),
194 }),
195 DecryptorTag::Aes256 => Ok(Decryptor::Aes256 {
196 key: decryption_key,
197 dict: data.unwrap(),
198 }),
199 }
200}
201
202fn decrypt_aes256(key: &[u8], data: &[u8]) -> Option<Vec<u8>> {
204 let (iv, data) = data.split_at_checked(16)?;
211 let iv: [u8; 16] = iv.try_into().ok()?;
212 let cipher = AES256Cipher::new(key)?;
213 Some(cipher.decrypt_cbc(data, &iv, true))
214}
215
216fn decrypt_aes128(key: &[u8], data: &[u8], id: ObjectIdentifier) -> Option<Vec<u8>> {
217 decrypt_rc_aes(key, id, true, |key| {
218 let cipher = AES128Cipher::new(key)?;
222 let (iv, data) = data.split_at_checked(16)?;
223 let iv: [u8; 16] = iv.try_into().ok()?;
224
225 Some(cipher.decrypt_cbc(data, &iv, true))
226 })
227}
228
229fn decrypt_rc4(key: &[u8], data: &[u8], id: ObjectIdentifier) -> Option<Vec<u8>> {
230 decrypt_rc_aes(key, id, false, |key| {
231 let mut rc = Rc4::new(key);
232 Some(rc.decrypt(data))
233 })
234}
235
236fn decrypt_rc_aes(
238 key: &[u8],
239 id: ObjectIdentifier,
240 aes: bool,
241 with_key: impl FnOnce(&[u8]) -> Option<Vec<u8>>,
242) -> Option<Vec<u8>> {
243 let n = key.len();
244 let mut key = key.to_vec();
249
250 key.extend(&id.obj_number.to_le_bytes()[..3]);
256 key.extend(&id.gen_number.to_le_bytes()[..2]);
257
258 if aes {
262 key.extend(b"sAlT");
263 }
264
265 let hash = md5::calculate(&key);
268
269 let final_key = &hash[..cmp::min(16, n + 5)];
273
274 with_key(final_key)
275}
276
277#[derive(Debug, Copy, Clone)]
278pub(crate) struct DecryptorData {
279 stream_filter: CryptDictionary,
280 string_filter: CryptDictionary,
281}
282
283impl DecryptorData {
284 fn from_dict(dict: &Dict<'_>, default_length: u16) -> Option<Self> {
285 let mut mappings = HashMap::new();
286
287 if let Some(dict) = dict.get::<Dict<'_>>(CF) {
288 for key in dict.keys() {
289 if let Some(dict) = dict.get::<Dict<'_>>(key.as_ref())
290 && let Some(crypt_dict) = CryptDictionary::from_dict(&dict, default_length)
291 {
292 mappings.insert(key.as_str().to_string(), crypt_dict);
293 }
294 }
295 }
296
297 let stm_f = *mappings
298 .get(dict.get::<Name<'_>>(STM_F)?.as_str())
299 .unwrap_or(&CryptDictionary::identity(default_length));
300 let str_f = *mappings
301 .get(dict.get::<Name<'_>>(STR_F)?.as_str())
302 .unwrap_or(&CryptDictionary::identity(default_length));
303
304 Some(Self {
305 stream_filter: stm_f,
306 string_filter: str_f,
307 })
308 }
309}
310
311#[derive(Debug, Copy, Clone)]
312struct CryptDictionary {
313 cfm: DecryptorTag,
314 _length: u16,
315}
316
317impl CryptDictionary {
318 fn from_dict(dict: &Dict<'_>, default_length: u16) -> Option<Self> {
319 let cfm = DecryptorTag::from_name(&dict.get::<Name<'_>>(CFM)?)?;
320 let mut length = dict.get::<u16>(LENGTH).unwrap_or(default_length / 8);
325
326 if cfm == DecryptorTag::Aes128 {
329 length = 16;
330 } else if cfm == DecryptorTag::Aes256 {
331 length = 32;
332 }
333
334 Some(Self {
335 cfm,
336 _length: length,
337 })
338 }
339
340 fn identity(default_length: u16) -> Self {
341 Self {
342 cfm: DecryptorTag::None,
343 _length: default_length,
344 }
345 }
346}
347
348fn compute_hash_rev56(
350 password: &[u8],
351 validation_salt: &[u8],
352 user_string: Option<&[u8]>,
353 revision: u8,
354) -> Result<[u8; 32], DecryptionError> {
355 let mut k = {
358 let mut input = Vec::new();
359 input.extend_from_slice(password);
360 input.extend_from_slice(validation_salt);
361
362 if let Some(user_string) = user_string {
363 input.extend_from_slice(user_string);
364 }
365
366 let hash = sha256::calculate(&input);
367
368 if revision == 5 {
370 return Ok(hash);
371 }
372
373 hash.to_vec()
374 };
375
376 let mut round: u16 = 0;
377
378 loop {
380 let k1 = {
386 let mut single: Vec<u8> = vec![];
387 single.extend(password);
388 single.extend(&k);
389
390 if let Some(user_string) = user_string {
391 single.extend(user_string);
392 }
393
394 single.repeat(64)
395 };
396
397 let e = {
401 let aes = AES128Cipher::new(&k[..16]).ok_or(InvalidEncryption)?;
402 let mut res = aes.encrypt_cbc(&k1, &k[16..32].try_into().unwrap());
403
404 res.truncate(k1.len());
406
407 res
408 };
409
410 let num = u128::from_be_bytes(e[..16].try_into().unwrap()) % 3;
415
416 k = match num {
419 0 => sha256::calculate(&e).to_vec(),
420 1 => sha384::calculate(&e).to_vec(),
421 2 => sha512::calculate(&e).to_vec(),
422 _ => unreachable!(),
423 };
424
425 round += 1;
426
427 if round > 63 {
431 let last_byte = *e.last().unwrap();
435
436 if (last_byte as u16) <= round - 32 {
440 break;
441 }
442 }
443 }
444
445 let mut result = [0_u8; 32];
447 result.copy_from_slice(&k[..32]);
448 Ok(result)
449}
450
451fn decryption_key_rev1234(
453 password: &[u8],
454 encrypt_metadata: bool,
455 revision: u8,
456 byte_length: u16,
457 owner_string: &object::String<'_>,
458 permissions: u32,
459 id: &[u8],
460) -> Result<Vec<u8>, DecryptionError> {
461 let mut md5_input = vec![];
462
463 let mut padded_password = [0_u8; 32];
466 let copy_len = password.len().min(32);
467 padded_password[..copy_len].copy_from_slice(&password[..copy_len]);
468 if copy_len < 32 {
469 padded_password[copy_len..].copy_from_slice(&PASSWORD_PADDING[..(32 - copy_len)]);
470 }
471
472 md5_input.extend(&padded_password);
475
476 md5_input.extend(owner_string.as_ref());
479
480 md5_input.extend(permissions.to_le_bytes());
483
484 md5_input.extend(id);
486
487 if !encrypt_metadata && revision >= 4 {
490 md5_input.extend(&[0xff, 0xff, 0xff, 0xff]);
491 }
492
493 let mut hash = md5::calculate(&md5_input);
495
496 if revision >= 3 {
501 for _ in 0..50 {
502 hash = md5::calculate(&hash[..byte_length as usize]);
503 }
504 }
505
506 let decryption_key = hash[..byte_length as usize].to_vec();
507 Ok(decryption_key)
508}
509
510fn authenticate_user_password_rev234(
512 revision: u8,
513 decryption_key: &[u8],
514 id: &[u8],
515 user_string: &object::String<'_>,
516) -> Result<(), DecryptionError> {
517 let result = match revision {
519 2 => user_password_rev2(decryption_key),
520 3 | 4 => user_password_rev34(decryption_key, id),
521 _ => return Err(InvalidEncryption),
522 };
523
524 match revision {
528 2 => {
529 if result.as_slice() != user_string.as_ref() {
530 return Err(DecryptionError::PasswordProtected);
531 }
532 }
533 3 | 4 => {
534 if Some(&result[..16]) != user_string.as_ref().get(0..16) {
535 return Err(DecryptionError::PasswordProtected);
536 }
537 }
538 _ => unreachable!(),
539 }
540
541 Ok(())
542}
543
544fn user_password_rev2(decryption_key: &[u8]) -> Vec<u8> {
547 let mut rc = Rc4::new(decryption_key);
551 rc.decrypt(&PASSWORD_PADDING)
552}
553
554fn user_password_rev34(decryption_key: &[u8], id: &[u8]) -> Vec<u8> {
557 let mut rc = Rc4::new(decryption_key);
559
560 let mut input = vec![];
561 input.extend(PASSWORD_PADDING);
563
564 input.extend(id);
567 let hash = md5::calculate(&input);
568
569 let mut encrypted = rc.encrypt(&hash);
572
573 for i in 1..=19 {
579 let mut key = decryption_key.to_vec();
580 for byte in &mut key {
581 *byte ^= i;
582 }
583
584 let mut rc = Rc4::new(&key);
585 encrypted = rc.encrypt(&encrypted);
586 }
587
588 encrypted.resize(32, 0);
589 encrypted
590}
591
592fn decryption_key_rev56(
594 dict: &Dict<'_>,
595 revision: u8,
596 password: &[u8],
597 owner_string: &object::String<'_>,
598 user_string: &object::String<'_>,
599) -> Result<Vec<u8>, DecryptionError> {
600 let password = &password[..password.len().min(127)];
606
607 let string_len = if revision <= 4 { 32 } else { 48 };
608
609 let trimmed_os = owner_string.get(..string_len).ok_or(InvalidEncryption)?;
610
611 let (owner_hash, owner_tail) = trimmed_os.split_at_checked(32).ok_or(InvalidEncryption)?;
612 let (owner_validation_salt, owner_key_salt) =
613 owner_tail.split_at_checked(8).ok_or(InvalidEncryption)?;
614
615 let trimmed_us = user_string.get(..string_len).ok_or(InvalidEncryption)?;
616 let (user_hash, user_tail) = trimmed_us.split_at_checked(32).ok_or(InvalidEncryption)?;
617 let (user_validation_salt, user_key_salt) =
618 user_tail.split_at_checked(8).ok_or(InvalidEncryption)?;
619
620 if compute_hash_rev56(password, owner_validation_salt, Some(trimmed_us), revision)?
625 == owner_hash
626 {
627 let intermediate_owner_key =
632 compute_hash_rev56(password, owner_key_salt, Some(trimmed_us), revision)?;
633
634 let oe_string = dict
635 .get::<object::String<'_>>(OE)
636 .ok_or(InvalidEncryption)?;
637
638 if oe_string.len() != 32 {
639 return Err(InvalidEncryption);
640 }
641
642 let cipher = AES256Cipher::new(&intermediate_owner_key).ok_or(InvalidEncryption)?;
643 let zero_iv = [0_u8; 16];
644
645 Ok(cipher.decrypt_cbc(&oe_string, &zero_iv, false))
646 } else if compute_hash_rev56(password, user_validation_salt, None, revision)? == user_hash {
647 let intermediate_key = compute_hash_rev56(password, user_key_salt, None, revision)?;
652
653 let ue_string = dict
654 .get::<object::String<'_>>(UE)
655 .ok_or(InvalidEncryption)?;
656
657 if ue_string.len() != 32 {
658 return Err(InvalidEncryption);
659 }
660
661 let cipher = AES256Cipher::new(&intermediate_key).ok_or(InvalidEncryption)?;
662 let zero_iv = [0_u8; 16];
663
664 Ok(cipher.decrypt_cbc(&ue_string, &zero_iv, false))
665 } else {
666 Err(DecryptionError::PasswordProtected)
667 }
668
669 }