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
149 let owner_string = dict.get::<object::String<'_>>(O).ok_or(InvalidEncryption)?;
150 let user_string = dict.get::<object::String<'_>>(U).ok_or(InvalidEncryption)?;
151 let permissions = {
152 let raw = dict.get::<i64>(P).ok_or(InvalidEncryption)?;
153
154 if raw < 0 {
155 u32::from_be_bytes((raw as i32).to_be_bytes())
156 } else {
157 raw as u32
158 }
159 };
160
161 let mut decryption_key = if revision <= 4 {
162 let key = decryption_key_rev1234(
163 password,
164 encrypt_metadata,
165 revision,
166 byte_length,
167 &owner_string,
168 permissions,
169 id,
170 )?;
171 authenticate_user_password_rev234(revision, &key, id, &user_string)?;
172
173 key
174 } else {
175 decryption_key_rev56(dict, revision, password, &owner_string, &user_string)?
176 };
177
178 if encryption_v == 4 && decryption_key.len() < 16 {
180 decryption_key.resize(16, 0);
181 }
182
183 match algorithm {
184 DecryptorTag::None => Ok(Decryptor::None),
185 DecryptorTag::Rc4 => Ok(Decryptor::Rc4 {
186 key: decryption_key,
187 }),
188 DecryptorTag::Aes128 => Ok(Decryptor::Aes128 {
189 key: decryption_key,
190 dict: data.unwrap(),
191 }),
192 DecryptorTag::Aes256 => Ok(Decryptor::Aes256 {
193 key: decryption_key,
194 dict: data.unwrap(),
195 }),
196 }
197}
198
199fn decrypt_aes256(key: &[u8], data: &[u8]) -> Option<Vec<u8>> {
201 let (iv, data) = data.split_at_checked(16)?;
208 let iv: [u8; 16] = iv.try_into().ok()?;
209 let cipher = AES256Cipher::new(key)?;
210 Some(cipher.decrypt_cbc(data, &iv, true))
211}
212
213fn decrypt_aes128(key: &[u8], data: &[u8], id: ObjectIdentifier) -> Option<Vec<u8>> {
214 decrypt_rc_aes(key, id, true, |key| {
215 let cipher = AES128Cipher::new(key)?;
219 let (iv, data) = data.split_at_checked(16)?;
220 let iv: [u8; 16] = iv.try_into().ok()?;
221
222 Some(cipher.decrypt_cbc(data, &iv, true))
223 })
224}
225
226fn decrypt_rc4(key: &[u8], data: &[u8], id: ObjectIdentifier) -> Option<Vec<u8>> {
227 decrypt_rc_aes(key, id, false, |key| {
228 let mut rc = Rc4::new(key);
229 Some(rc.decrypt(data))
230 })
231}
232
233fn decrypt_rc_aes(
235 key: &[u8],
236 id: ObjectIdentifier,
237 aes: bool,
238 with_key: impl FnOnce(&[u8]) -> Option<Vec<u8>>,
239) -> Option<Vec<u8>> {
240 let n = key.len();
241 let mut key = key.to_vec();
246
247 key.extend(&id.obj_number.to_le_bytes()[..3]);
253 key.extend(&id.gen_number.to_le_bytes()[..2]);
254
255 if aes {
259 key.extend(b"sAlT");
260 }
261
262 let hash = md5::calculate(&key);
265
266 let final_key = &hash[..cmp::min(16, n + 5)];
270
271 with_key(final_key)
272}
273
274#[derive(Debug, Copy, Clone)]
275pub(crate) struct DecryptorData {
276 stream_filter: CryptDictionary,
277 string_filter: CryptDictionary,
278}
279
280impl DecryptorData {
281 fn from_dict(dict: &Dict<'_>, default_length: u16) -> Option<Self> {
282 let mut mappings = HashMap::new();
283
284 if let Some(dict) = dict.get::<Dict<'_>>(CF) {
285 for key in dict.keys() {
286 if let Some(dict) = dict.get::<Dict<'_>>(key.as_ref())
287 && let Some(crypt_dict) = CryptDictionary::from_dict(&dict, default_length)
288 {
289 mappings.insert(key.as_str().to_string(), crypt_dict);
290 }
291 }
292 }
293
294 let stm_f = *mappings
295 .get(dict.get::<Name<'_>>(STM_F)?.as_str())
296 .unwrap_or(&CryptDictionary::identity(default_length));
297 let str_f = *mappings
298 .get(dict.get::<Name<'_>>(STR_F)?.as_str())
299 .unwrap_or(&CryptDictionary::identity(default_length));
300
301 Some(Self {
302 stream_filter: stm_f,
303 string_filter: str_f,
304 })
305 }
306}
307
308#[derive(Debug, Copy, Clone)]
309struct CryptDictionary {
310 cfm: DecryptorTag,
311 _length: u16,
312}
313
314impl CryptDictionary {
315 fn from_dict(dict: &Dict<'_>, default_length: u16) -> Option<Self> {
316 let cfm = DecryptorTag::from_name(&dict.get::<Name<'_>>(CFM)?)?;
317 let mut length = dict.get::<u16>(LENGTH).unwrap_or(default_length / 8);
322
323 if cfm == DecryptorTag::Aes128 {
326 length = 16;
327 } else if cfm == DecryptorTag::Aes256 {
328 length = 32;
329 }
330
331 Some(Self {
332 cfm,
333 _length: length,
334 })
335 }
336
337 fn identity(default_length: u16) -> Self {
338 Self {
339 cfm: DecryptorTag::None,
340 _length: default_length,
341 }
342 }
343}
344
345fn compute_hash_rev56(
347 password: &[u8],
348 validation_salt: &[u8],
349 user_string: Option<&[u8]>,
350 revision: u8,
351) -> Result<[u8; 32], DecryptionError> {
352 let mut k = {
355 let mut input = Vec::new();
356 input.extend_from_slice(password);
357 input.extend_from_slice(validation_salt);
358
359 if let Some(user_string) = user_string {
360 input.extend_from_slice(user_string);
361 }
362
363 let hash = sha256::calculate(&input);
364
365 if revision == 5 {
367 return Ok(hash);
368 }
369
370 hash.to_vec()
371 };
372
373 let mut round: u16 = 0;
374
375 loop {
377 let k1 = {
383 let mut single: Vec<u8> = vec![];
384 single.extend(password);
385 single.extend(&k);
386
387 if let Some(user_string) = user_string {
388 single.extend(user_string);
389 }
390
391 single.repeat(64)
392 };
393
394 let e = {
398 let aes = AES128Cipher::new(&k[..16]).ok_or(InvalidEncryption)?;
399 let mut res = aes.encrypt_cbc(&k1, &k[16..32].try_into().unwrap());
400
401 res.truncate(k1.len());
403
404 res
405 };
406
407 let num = u128::from_be_bytes(e[..16].try_into().unwrap()) % 3;
412
413 k = match num {
416 0 => sha256::calculate(&e).to_vec(),
417 1 => sha384::calculate(&e).to_vec(),
418 2 => sha512::calculate(&e).to_vec(),
419 _ => unreachable!(),
420 };
421
422 round += 1;
423
424 if round > 63 {
428 let last_byte = *e.last().unwrap();
432
433 if (last_byte as u16) <= round - 32 {
437 break;
438 }
439 }
440 }
441
442 let mut result = [0_u8; 32];
444 result.copy_from_slice(&k[..32]);
445 Ok(result)
446}
447
448fn decryption_key_rev1234(
450 password: &[u8],
451 encrypt_metadata: bool,
452 revision: u8,
453 byte_length: u16,
454 owner_string: &object::String<'_>,
455 permissions: u32,
456 id: &[u8],
457) -> Result<Vec<u8>, DecryptionError> {
458 let mut md5_input = vec![];
459
460 let mut padded_password = [0_u8; 32];
463 let copy_len = password.len().min(32);
464 padded_password[..copy_len].copy_from_slice(&password[..copy_len]);
465 if copy_len < 32 {
466 padded_password[copy_len..].copy_from_slice(&PASSWORD_PADDING[..(32 - copy_len)]);
467 }
468
469 md5_input.extend(&padded_password);
472
473 md5_input.extend(owner_string.as_ref());
476
477 md5_input.extend(permissions.to_le_bytes());
480
481 md5_input.extend(id);
483
484 if !encrypt_metadata && revision >= 4 {
487 md5_input.extend(&[0xff, 0xff, 0xff, 0xff]);
488 }
489
490 let mut hash = md5::calculate(&md5_input);
492
493 if revision >= 3 {
498 for _ in 0..50 {
499 hash = md5::calculate(&hash[..byte_length as usize]);
500 }
501 }
502
503 let decryption_key = hash[..byte_length as usize].to_vec();
504 Ok(decryption_key)
505}
506
507fn authenticate_user_password_rev234(
509 revision: u8,
510 decryption_key: &[u8],
511 id: &[u8],
512 user_string: &object::String<'_>,
513) -> Result<(), DecryptionError> {
514 let result = match revision {
516 2 => user_password_rev2(decryption_key),
517 3 | 4 => user_password_rev34(decryption_key, id),
518 _ => return Err(InvalidEncryption),
519 };
520
521 match revision {
525 2 => {
526 if result.as_slice() != user_string.as_ref() {
527 return Err(DecryptionError::PasswordProtected);
528 }
529 }
530 3 | 4 => {
531 if Some(&result[..16]) != user_string.as_ref().get(0..16) {
532 return Err(DecryptionError::PasswordProtected);
533 }
534 }
535 _ => unreachable!(),
536 }
537
538 Ok(())
539}
540
541fn user_password_rev2(decryption_key: &[u8]) -> Vec<u8> {
544 let mut rc = Rc4::new(decryption_key);
548 rc.decrypt(&PASSWORD_PADDING)
549}
550
551fn user_password_rev34(decryption_key: &[u8], id: &[u8]) -> Vec<u8> {
554 let mut rc = Rc4::new(decryption_key);
556
557 let mut input = vec![];
558 input.extend(PASSWORD_PADDING);
560
561 input.extend(id);
564 let hash = md5::calculate(&input);
565
566 let mut encrypted = rc.encrypt(&hash);
569
570 for i in 1..=19 {
576 let mut key = decryption_key.to_vec();
577 for byte in &mut key {
578 *byte ^= i;
579 }
580
581 let mut rc = Rc4::new(&key);
582 encrypted = rc.encrypt(&encrypted);
583 }
584
585 encrypted.resize(32, 0);
586 encrypted
587}
588
589fn decryption_key_rev56(
591 dict: &Dict<'_>,
592 revision: u8,
593 password: &[u8],
594 owner_string: &object::String<'_>,
595 user_string: &object::String<'_>,
596) -> Result<Vec<u8>, DecryptionError> {
597 let password = &password[..password.len().min(127)];
603
604 let string_len = if revision <= 4 { 32 } else { 48 };
605
606 let trimmed_os = owner_string.get(..string_len).ok_or(InvalidEncryption)?;
607
608 let (owner_hash, owner_tail) = trimmed_os.split_at_checked(32).ok_or(InvalidEncryption)?;
609 let (owner_validation_salt, owner_key_salt) =
610 owner_tail.split_at_checked(8).ok_or(InvalidEncryption)?;
611
612 let trimmed_us = user_string.get(..string_len).ok_or(InvalidEncryption)?;
613 let (user_hash, user_tail) = trimmed_us.split_at_checked(32).ok_or(InvalidEncryption)?;
614 let (user_validation_salt, user_key_salt) =
615 user_tail.split_at_checked(8).ok_or(InvalidEncryption)?;
616
617 if compute_hash_rev56(password, owner_validation_salt, Some(trimmed_us), revision)?
622 == owner_hash
623 {
624 let intermediate_owner_key =
629 compute_hash_rev56(password, owner_key_salt, Some(trimmed_us), revision)?;
630
631 let oe_string = dict
632 .get::<object::String<'_>>(OE)
633 .ok_or(InvalidEncryption)?;
634
635 if oe_string.len() != 32 {
636 return Err(InvalidEncryption);
637 }
638
639 let cipher = AES256Cipher::new(&intermediate_owner_key).ok_or(InvalidEncryption)?;
640 let zero_iv = [0_u8; 16];
641
642 Ok(cipher.decrypt_cbc(&oe_string, &zero_iv, false))
643 } else if compute_hash_rev56(password, user_validation_salt, None, revision)? == user_hash {
644 let intermediate_key = compute_hash_rev56(password, user_key_salt, None, revision)?;
649
650 let ue_string = dict
651 .get::<object::String<'_>>(UE)
652 .ok_or(InvalidEncryption)?;
653
654 if ue_string.len() != 32 {
655 return Err(InvalidEncryption);
656 }
657
658 let cipher = AES256Cipher::new(&intermediate_key).ok_or(InvalidEncryption)?;
659 let zero_iv = [0_u8; 16];
660
661 Ok(cipher.decrypt_cbc(&ue_string, &zero_iv, false))
662 } else {
663 Err(DecryptionError::PasswordProtected)
664 }
665
666 }