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 std::collections::HashMap;
17use std::ops::Deref;
18
19mod aes;
20mod md5;
21mod rc4;
22mod sha256;
23mod sha384;
24mod sha512;
25
26const PASSWORD_PADDING: [u8; 32] = [
27 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
28 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A,
29];
30
31#[derive(Debug, Copy, Clone, PartialEq, Eq)]
33pub enum DecryptionError {
34 MissingIDEntry,
36 PasswordProtected,
39 InvalidEncryption,
41 UnsupportedAlgorithm,
43}
44
45#[derive(Debug, Copy, Clone, PartialEq, Eq)]
46enum DecryptorTag {
47 None,
48 Rc4,
49 Aes128,
50 Aes256,
51}
52
53impl DecryptorTag {
54 fn from_name(name: &Name<'_>) -> Option<Self> {
55 match name.as_str() {
56 "None" | "Identity" => Some(Self::None),
57 "V2" => Some(Self::Rc4),
58 "AESV2" => Some(Self::Aes128),
59 "AESV3" => Some(Self::Aes256),
60 _ => None,
61 }
62 }
63}
64#[derive(Debug, Clone)]
65pub(crate) enum Decryptor {
66 None,
67 Rc4 { key: Vec<u8> },
68 Aes128 { key: Vec<u8>, dict: DecryptorData },
69 Aes256 { key: Vec<u8>, dict: DecryptorData },
70}
71
72#[derive(Debug, Copy, Clone)]
73pub(crate) enum DecryptionTarget {
74 String,
75 Stream,
76}
77
78impl Decryptor {
79 pub(crate) fn decrypt(
80 &self,
81 id: ObjectIdentifier,
82 data: &[u8],
83 target: DecryptionTarget,
84 ) -> Option<Vec<u8>> {
85 match self {
86 Self::None => Some(data.to_vec()),
87 Self::Rc4 { key } => decrypt_rc4(key, data, id),
88 Self::Aes128 { key, dict } | Self::Aes256 { key, dict } => {
89 let crypt_dict = match target {
90 DecryptionTarget::String => dict.string_filter,
91 DecryptionTarget::Stream => dict.stream_filter,
92 };
93
94 match crypt_dict.cfm {
95 DecryptorTag::None => Some(data.to_vec()),
96 DecryptorTag::Rc4 => decrypt_rc4(key, data, id),
97 DecryptorTag::Aes128 => decrypt_aes128(key, data, id),
98 DecryptorTag::Aes256 => decrypt_aes256(key, data),
99 }
100 }
101 }
102 }
103}
104
105pub(crate) fn get(
106 dict: &Dict<'_>,
107 id: &[u8],
108 password: &[u8],
109) -> Result<Decryptor, DecryptionError> {
110 let filter = dict.get::<Name<'_>>(FILTER).ok_or(InvalidEncryption)?;
111
112 if filter.deref() != b"Standard" {
113 return Err(DecryptionError::UnsupportedAlgorithm);
114 }
115
116 let encryption_v = dict.get::<u8>(V).ok_or(InvalidEncryption)?;
117 let encrypt_metadata = dict.get::<bool>(ENCRYPT_META_DATA).unwrap_or(true);
118 let revision = dict.get::<u8>(R).ok_or(InvalidEncryption)?;
119 let length = match encryption_v {
120 1 => 40,
121 2 => dict.get::<u16>(LENGTH).unwrap_or(40),
122 4 => dict.get::<u16>(LENGTH).unwrap_or(128),
123 5 => 256,
124 _ => return Err(DecryptionError::UnsupportedAlgorithm),
125 };
126
127 let (algorithm, data) = match encryption_v {
128 1 => (DecryptorTag::Rc4, None),
129 2 => (DecryptorTag::Rc4, None),
130 4 => (
131 DecryptorTag::Aes128,
132 Some(DecryptorData::from_dict(dict, length).ok_or(InvalidEncryption)?),
133 ),
134 5 | 6 => (
135 DecryptorTag::Aes256,
136 Some(DecryptorData::from_dict(dict, length).ok_or(InvalidEncryption)?),
137 ),
138 _ => {
139 return Err(DecryptionError::UnsupportedAlgorithm);
140 }
141 };
142
143 let byte_length = length / 8;
144
145 let owner_string = dict.get::<object::String<'_>>(O).ok_or(InvalidEncryption)?;
146 let user_string = dict.get::<object::String<'_>>(U).ok_or(InvalidEncryption)?;
147 let permissions = {
148 let raw = dict.get::<i64>(P).ok_or(InvalidEncryption)?;
149
150 if raw < 0 {
151 u32::from_be_bytes((raw as i32).to_be_bytes())
152 } else {
153 raw as u32
154 }
155 };
156
157 let mut decryption_key = if revision <= 4 {
158 let key = decryption_key_rev1234(
159 password,
160 encrypt_metadata,
161 revision,
162 byte_length,
163 &owner_string,
164 permissions,
165 id,
166 )?;
167 authenticate_user_password_rev234(revision, &key, id, &user_string)?;
168
169 key
170 } else {
171 decryption_key_rev56(dict, revision, password, &owner_string, &user_string)?
172 };
173
174 if encryption_v == 4 && decryption_key.len() < 16 {
176 decryption_key.resize(16, 0);
177 }
178
179 match algorithm {
180 DecryptorTag::None => Ok(Decryptor::None),
181 DecryptorTag::Rc4 => Ok(Decryptor::Rc4 {
182 key: decryption_key,
183 }),
184 DecryptorTag::Aes128 => Ok(Decryptor::Aes128 {
185 key: decryption_key,
186 dict: data.unwrap(),
187 }),
188 DecryptorTag::Aes256 => Ok(Decryptor::Aes256 {
189 key: decryption_key,
190 dict: data.unwrap(),
191 }),
192 }
193}
194
195fn decrypt_aes256(key: &[u8], data: &[u8]) -> Option<Vec<u8>> {
197 let (iv, data) = data.split_at_checked(16)?;
204 let iv: [u8; 16] = iv.try_into().ok()?;
205 let cipher = AES256Cipher::new(key)?;
206 Some(cipher.decrypt_cbc(data, &iv, true))
207}
208
209fn decrypt_aes128(key: &[u8], data: &[u8], id: ObjectIdentifier) -> Option<Vec<u8>> {
210 decrypt_rc_aes(key, id, true, |key| {
211 let cipher = AES128Cipher::new(key)?;
215 let (iv, data) = data.split_at_checked(16)?;
216 let iv: [u8; 16] = iv.try_into().ok()?;
217
218 Some(cipher.decrypt_cbc(data, &iv, true))
219 })
220}
221
222fn decrypt_rc4(key: &[u8], data: &[u8], id: ObjectIdentifier) -> Option<Vec<u8>> {
223 decrypt_rc_aes(key, id, false, |key| {
224 let mut rc = Rc4::new(key);
225 Some(rc.decrypt(data))
226 })
227}
228
229fn decrypt_rc_aes(
231 key: &[u8],
232 id: ObjectIdentifier,
233 aes: bool,
234 with_key: impl FnOnce(&[u8]) -> Option<Vec<u8>>,
235) -> Option<Vec<u8>> {
236 let n = key.len();
237 let mut key = key.to_vec();
242
243 key.extend(&id.obj_num.to_le_bytes()[..3]);
249 key.extend(&id.gen_num.to_le_bytes()[..2]);
250
251 if aes {
255 key.extend(b"sAlT");
256 }
257
258 let hash = md5::calculate(&key);
261
262 let final_key = &hash[..std::cmp::min(16, n + 5)];
266
267 with_key(final_key)
268}
269
270#[derive(Debug, Copy, Clone)]
271pub(crate) struct DecryptorData {
272 stream_filter: CryptDictionary,
273 string_filter: CryptDictionary,
274}
275
276impl DecryptorData {
277 fn from_dict(dict: &Dict<'_>, default_length: u16) -> Option<Self> {
278 let mut mappings = HashMap::new();
279
280 if let Some(dict) = dict.get::<Dict<'_>>(CF) {
281 for key in dict.keys() {
282 if let Some(dict) = dict.get::<Dict<'_>>(key.clone())
283 && let Some(crypt_dict) = CryptDictionary::from_dict(&dict, default_length)
284 {
285 mappings.insert(key.as_str().to_string(), crypt_dict);
286 }
287 }
288 }
289
290 let stm_f = *mappings
291 .get(dict.get::<Name<'_>>(STM_F)?.as_str())
292 .unwrap_or(&CryptDictionary::identity(default_length));
293 let str_f = *mappings
294 .get(dict.get::<Name<'_>>(STR_F)?.as_str())
295 .unwrap_or(&CryptDictionary::identity(default_length));
296
297 Some(Self {
298 stream_filter: stm_f,
299 string_filter: str_f,
300 })
301 }
302}
303
304#[derive(Debug, Copy, Clone)]
305struct CryptDictionary {
306 cfm: DecryptorTag,
307 _length: u16,
308}
309
310impl CryptDictionary {
311 fn from_dict(dict: &Dict<'_>, default_length: u16) -> Option<Self> {
312 let cfm = DecryptorTag::from_name(&dict.get::<Name<'_>>(CFM)?)?;
313 let mut length = dict.get::<u16>(LENGTH).unwrap_or(default_length / 8);
318
319 if cfm == DecryptorTag::Aes128 {
322 length = 16;
323 } else if cfm == DecryptorTag::Aes256 {
324 length = 32;
325 }
326
327 Some(Self {
328 cfm,
329 _length: length,
330 })
331 }
332
333 fn identity(default_length: u16) -> Self {
334 Self {
335 cfm: DecryptorTag::None,
336 _length: default_length,
337 }
338 }
339}
340
341fn compute_hash_rev56(
343 password: &[u8],
344 validation_salt: &[u8],
345 user_string: Option<&[u8]>,
346 revision: u8,
347) -> Result<[u8; 32], DecryptionError> {
348 let mut k = {
351 let mut input = Vec::new();
352 input.extend_from_slice(password);
353 input.extend_from_slice(validation_salt);
354
355 if let Some(user_string) = user_string {
356 input.extend_from_slice(user_string);
357 }
358
359 let hash = sha256::calculate(&input);
360
361 if revision == 5 {
363 return Ok(hash);
364 }
365
366 hash.to_vec()
367 };
368
369 let mut round: u16 = 0;
370
371 loop {
373 let k1 = {
379 let mut single: Vec<u8> = vec![];
380 single.extend(password);
381 single.extend(&k);
382
383 if let Some(user_string) = user_string {
384 single.extend(user_string);
385 }
386
387 single.repeat(64)
388 };
389
390 let e = {
394 let aes = AES128Cipher::new(&k[..16]).ok_or(InvalidEncryption)?;
395 let mut res = aes.encrypt_cbc(&k1, &k[16..32].try_into().unwrap());
396
397 res.truncate(k1.len());
399
400 res
401 };
402
403 let num = u128::from_be_bytes(e[..16].try_into().unwrap()) % 3;
408
409 k = match num {
412 0 => sha256::calculate(&e).to_vec(),
413 1 => sha384::calculate(&e).to_vec(),
414 2 => sha512::calculate(&e).to_vec(),
415 _ => unreachable!(),
416 };
417
418 round += 1;
419
420 if round > 63 {
424 let last_byte = *e.last().unwrap();
428
429 if (last_byte as u16) <= round - 32 {
433 break;
434 }
435 }
436 }
437
438 let mut result = [0_u8; 32];
440 result.copy_from_slice(&k[..32]);
441 Ok(result)
442}
443
444fn decryption_key_rev1234(
446 password: &[u8],
447 encrypt_metadata: bool,
448 revision: u8,
449 byte_length: u16,
450 owner_string: &object::String<'_>,
451 permissions: u32,
452 id: &[u8],
453) -> Result<Vec<u8>, DecryptionError> {
454 let mut md5_input = vec![];
455
456 let mut padded_password = [0_u8; 32];
459 let copy_len = password.len().min(32);
460 padded_password[..copy_len].copy_from_slice(&password[..copy_len]);
461 if copy_len < 32 {
462 padded_password[copy_len..].copy_from_slice(&PASSWORD_PADDING[..(32 - copy_len)]);
463 }
464
465 md5_input.extend(&padded_password);
468
469 md5_input.extend(owner_string.get().as_ref());
472
473 md5_input.extend(permissions.to_le_bytes());
476
477 md5_input.extend(id);
479
480 if !encrypt_metadata && revision >= 4 {
483 md5_input.extend(&[0xff, 0xff, 0xff, 0xff]);
484 }
485
486 let mut hash = md5::calculate(&md5_input);
488
489 if revision >= 3 {
494 for _ in 0..50 {
495 hash = md5::calculate(&hash[..byte_length as usize]);
496 }
497 }
498
499 let decryption_key = hash[..byte_length as usize].to_vec();
500 Ok(decryption_key)
501}
502
503fn authenticate_user_password_rev234(
505 revision: u8,
506 decryption_key: &[u8],
507 id: &[u8],
508 user_string: &object::String<'_>,
509) -> Result<(), DecryptionError> {
510 let result = match revision {
512 2 => user_password_rev2(decryption_key),
513 3 | 4 => user_password_rev34(decryption_key, id),
514 _ => return Err(InvalidEncryption),
515 };
516
517 match revision {
521 2 => {
522 if result.as_slice() != user_string.get().as_ref() {
523 return Err(DecryptionError::PasswordProtected);
524 }
525 }
526 3 | 4 => {
527 if Some(&result[..16]) != user_string.get().as_ref().get(0..16) {
528 return Err(DecryptionError::PasswordProtected);
529 }
530 }
531 _ => unreachable!(),
532 }
533
534 Ok(())
535}
536
537fn user_password_rev2(decryption_key: &[u8]) -> Vec<u8> {
540 let mut rc = Rc4::new(decryption_key);
544 rc.decrypt(&PASSWORD_PADDING)
545}
546
547fn user_password_rev34(decryption_key: &[u8], id: &[u8]) -> Vec<u8> {
550 let mut rc = Rc4::new(decryption_key);
552
553 let mut input = vec![];
554 input.extend(PASSWORD_PADDING);
556
557 input.extend(id);
560 let hash = md5::calculate(&input);
561
562 let mut encrypted = rc.encrypt(&hash);
565
566 for i in 1..=19 {
572 let mut key = decryption_key.to_vec();
573 for byte in &mut key {
574 *byte ^= i;
575 }
576
577 let mut rc = Rc4::new(&key);
578 encrypted = rc.encrypt(&encrypted);
579 }
580
581 encrypted.resize(32, 0);
582 encrypted
583}
584
585fn decryption_key_rev56(
587 dict: &Dict<'_>,
588 revision: u8,
589 password: &[u8],
590 owner_string: &object::String<'_>,
591 user_string: &object::String<'_>,
592) -> Result<Vec<u8>, DecryptionError> {
593 let password = &password[..password.len().min(127)];
599
600 let string_len = if revision <= 4 { 32 } else { 48 };
601
602 let os = owner_string.get();
603 let trimmed_os = os.get(..string_len).ok_or(InvalidEncryption)?;
604
605 let (owner_hash, owner_tail) = trimmed_os.split_at_checked(32).ok_or(InvalidEncryption)?;
606 let (owner_validation_salt, owner_key_salt) =
607 owner_tail.split_at_checked(8).ok_or(InvalidEncryption)?;
608
609 let us = user_string.get();
610 let trimmed_us = us.get(..string_len).ok_or(InvalidEncryption)?;
611 let (user_hash, user_tail) = trimmed_us.split_at_checked(32).ok_or(InvalidEncryption)?;
612 let (user_validation_salt, user_key_salt) =
613 user_tail.split_at_checked(8).ok_or(InvalidEncryption)?;
614
615 if compute_hash_rev56(password, owner_validation_salt, Some(trimmed_us), revision)?
620 == owner_hash
621 {
622 let intermediate_owner_key =
627 compute_hash_rev56(password, owner_key_salt, Some(trimmed_us), revision)?;
628
629 let oe_string = dict
630 .get::<object::String<'_>>(OE)
631 .ok_or(InvalidEncryption)?;
632
633 if oe_string.get().len() != 32 {
634 return Err(InvalidEncryption);
635 }
636
637 let cipher = AES256Cipher::new(&intermediate_owner_key).ok_or(InvalidEncryption)?;
638 let zero_iv = [0_u8; 16];
639
640 Ok(cipher.decrypt_cbc(&oe_string.get(), &zero_iv, false))
641 } else if compute_hash_rev56(password, user_validation_salt, None, revision)? == user_hash {
642 let intermediate_key = compute_hash_rev56(password, user_key_salt, None, revision)?;
647
648 let ue_string = dict
649 .get::<object::String<'_>>(UE)
650 .ok_or(InvalidEncryption)?;
651
652 if ue_string.get().len() != 32 {
653 return Err(InvalidEncryption);
654 }
655
656 let cipher = AES256Cipher::new(&intermediate_key).ok_or(InvalidEncryption)?;
657 let zero_iv = [0_u8; 16];
658
659 Ok(cipher.decrypt_cbc(&ue_string.get(), &zero_iv, false))
660 } else {
661 Err(DecryptionError::PasswordProtected)
662 }
663
664 }