1use super::objects::PdfDictionary;
7use super::{ParseError, ParseResult};
8use crate::encryption::{
9 EncryptionKey, OwnerPassword, Permissions, Rc4, Rc4Key, StandardSecurityHandler, UserPassword,
10};
11use crate::objects::ObjectId;
12
13#[derive(Debug, Clone)]
19#[non_exhaustive]
20pub struct EncryptionInfo {
21 pub filter: String,
23 pub v: i32,
25 pub r: i32,
27 pub o: Vec<u8>,
29 pub u: Vec<u8>,
31 pub p: i32,
33 pub length: Option<i32>,
35 pub ue: Option<Vec<u8>>,
37 pub oe: Option<Vec<u8>>,
39 pub(crate) cfm: Option<String>,
45 pub(crate) encrypt_metadata: bool,
52}
53
54pub struct EncryptionHandler {
56 encryption_info: EncryptionInfo,
58 security_handler: StandardSecurityHandler,
60 encryption_key: Option<EncryptionKey>,
62 file_id: Option<Vec<u8>>,
64}
65
66impl EncryptionHandler {
67 pub fn new(encrypt_dict: &PdfDictionary, file_id: Option<Vec<u8>>) -> ParseResult<Self> {
69 let encryption_info = Self::parse_encryption_dict(encrypt_dict)?;
70
71 let security_handler = match encryption_info.r {
76 2 => StandardSecurityHandler::rc4_40bit(),
77 3 => StandardSecurityHandler::rc4_128bit(),
78 4 => match encryption_info.cfm.as_deref() {
79 Some("V2") => StandardSecurityHandler::rc4_128bit(),
81 _ => StandardSecurityHandler::aes_128_r4(),
86 },
87 5 => StandardSecurityHandler::aes_256_r5(),
88 6 => StandardSecurityHandler::aes_256_r6(),
89 _ => {
90 return Err(ParseError::SyntaxError {
91 position: 0,
92 message: format!("Encryption revision {} not supported", encryption_info.r),
93 });
94 }
95 };
96
97 Ok(Self {
98 encryption_info,
99 security_handler,
100 encryption_key: None,
101 file_id,
102 })
103 }
104
105 fn parse_encryption_dict(dict: &PdfDictionary) -> ParseResult<EncryptionInfo> {
107 let filter = dict
109 .get("Filter")
110 .and_then(|obj| obj.as_name())
111 .map(|name| name.0.as_str())
112 .ok_or_else(|| ParseError::MissingKey("Filter".to_string()))?;
113
114 if filter != "Standard" {
115 return Err(ParseError::SyntaxError {
116 position: 0,
117 message: format!("Encryption filter '{filter}' not supported"),
118 });
119 }
120
121 let v = dict
123 .get("V")
124 .and_then(|obj| obj.as_integer())
125 .map(|i| i as i32)
126 .unwrap_or(0);
127
128 let r = dict
130 .get("R")
131 .and_then(|obj| obj.as_integer())
132 .map(|i| i as i32)
133 .ok_or_else(|| ParseError::MissingKey("R".to_string()))?;
134
135 let o = dict
137 .get("O")
138 .and_then(|obj| obj.as_string())
139 .ok_or_else(|| ParseError::MissingKey("O".to_string()))?
140 .as_bytes()
141 .to_vec();
142
143 let u = dict
145 .get("U")
146 .and_then(|obj| obj.as_string())
147 .ok_or_else(|| ParseError::MissingKey("U".to_string()))?
148 .as_bytes()
149 .to_vec();
150
151 let p = dict
153 .get("P")
154 .and_then(|obj| obj.as_integer())
155 .map(|i| i as i32)
156 .ok_or_else(|| ParseError::MissingKey("P".to_string()))?;
157
158 let length = dict
160 .get("Length")
161 .and_then(|obj| obj.as_integer())
162 .map(|i| i as i32);
163
164 let ue = dict
166 .get("UE")
167 .and_then(|obj| obj.as_string())
168 .map(|s| s.as_bytes().to_vec());
169
170 let oe = dict
172 .get("OE")
173 .and_then(|obj| obj.as_string())
174 .map(|s| s.as_bytes().to_vec());
175
176 let cfm = if v >= 4 {
179 Self::parse_stream_cfm(dict)
180 } else {
181 None
182 };
183
184 let encrypt_metadata = dict
187 .get("EncryptMetadata")
188 .and_then(|obj| obj.as_bool())
189 .unwrap_or(true);
190
191 Ok(EncryptionInfo {
192 filter: filter.to_string(),
193 v,
194 r,
195 o,
196 u,
197 p,
198 length,
199 ue,
200 oe,
201 cfm,
202 encrypt_metadata,
203 })
204 }
205
206 fn parse_stream_cfm(dict: &PdfDictionary) -> Option<String> {
212 let stmf = dict
213 .get("StmF")
214 .and_then(|o| o.as_name())
215 .map(|n| n.0.as_str())
216 .unwrap_or("Identity"); if stmf == "Identity" {
219 return Some("Identity".to_string());
220 }
221
222 let cf = dict.get("CF").and_then(|o| o.as_dict())?;
223 cf.get(stmf)
224 .and_then(|o| o.as_dict())
225 .and_then(|f| f.get("CFM"))
226 .and_then(|o| o.as_name())
227 .map(|n| n.0.clone())
228 }
229
230 pub fn detect_encryption(trailer: &PdfDictionary) -> bool {
232 trailer.contains_key("Encrypt")
233 }
234
235 pub fn unlock_with_user_password(&mut self, password: &str) -> ParseResult<bool> {
237 let user_password = UserPassword(password.to_string());
238
239 match self.encryption_info.r {
240 5 | 6 => self.unlock_user_r5_r6(&user_password),
241 _ => self.unlock_user_r2_r4(&user_password),
242 }
243 }
244
245 fn unlock_user_r2_r4(&mut self, user_password: &UserPassword) -> ParseResult<bool> {
247 let permissions = Permissions::from_bits(self.encryption_info.p as u32);
248
249 let encrypt_metadata = self.encryption_info.encrypt_metadata || self.encryption_info.r < 4;
254
255 let computed_u = self
256 .security_handler
257 .compute_user_hash_with_metadata(
258 user_password,
259 &self.encryption_info.o,
260 permissions,
261 self.file_id.as_deref(),
262 encrypt_metadata,
263 )
264 .map_err(|e| ParseError::SyntaxError {
265 position: 0,
266 message: format!("Failed to compute user hash: {e}"),
267 })?;
268
269 let comparison_length = if self.encryption_info.r >= 3 { 16 } else { 32 };
271
272 if computed_u.len() < comparison_length || self.encryption_info.u.len() < comparison_length
273 {
274 return Ok(false);
275 }
276
277 let matches =
278 computed_u[..comparison_length] == self.encryption_info.u[..comparison_length];
279
280 if matches {
281 let key = self
282 .security_handler
283 .compute_encryption_key_with_metadata(
284 user_password,
285 &self.encryption_info.o,
286 permissions,
287 self.file_id.as_deref(),
288 encrypt_metadata,
289 )
290 .map_err(|e| ParseError::SyntaxError {
291 position: 0,
292 message: format!("Failed to compute encryption key: {e}"),
293 })?;
294 self.encryption_key = Some(key);
295 }
296
297 Ok(matches)
298 }
299
300 fn unlock_user_r5_r6(&mut self, user_password: &UserPassword) -> ParseResult<bool> {
302 let u_entry = &self.encryption_info.u;
303
304 let is_valid = if self.encryption_info.r == 5 {
306 self.security_handler
307 .validate_r5_user_password(user_password, u_entry)
308 } else {
309 self.security_handler
310 .validate_r6_user_password(user_password, u_entry)
311 }
312 .map_err(|e| ParseError::SyntaxError {
313 position: 0,
314 message: format!(
315 "Failed to validate R{} user password: {e}",
316 self.encryption_info.r
317 ),
318 })?;
319
320 if is_valid {
321 let ue_entry =
323 self.encryption_info
324 .ue
325 .as_deref()
326 .ok_or_else(|| ParseError::SyntaxError {
327 position: 0,
328 message: format!(
329 "R{} encryption requires UE entry but it is missing",
330 self.encryption_info.r
331 ),
332 })?;
333
334 let key = if self.encryption_info.r == 5 {
335 self.security_handler
336 .recover_r5_encryption_key(user_password, u_entry, ue_entry)
337 } else {
338 self.security_handler
339 .recover_r6_encryption_key(user_password, u_entry, ue_entry)
340 }
341 .map_err(|e| ParseError::SyntaxError {
342 position: 0,
343 message: format!(
344 "Failed to recover R{} encryption key: {e}",
345 self.encryption_info.r
346 ),
347 })?;
348
349 self.encryption_key = Some(key);
350 }
351
352 Ok(is_valid)
353 }
354
355 fn unlock_owner_r5_r6(&mut self, owner_password: &OwnerPassword) -> ParseResult<bool> {
360 let o_entry = self.encryption_info.o.clone();
361 let u_entry = self.encryption_info.u.clone();
362
363 let is_valid = if self.encryption_info.r == 5 {
364 self.security_handler
365 .validate_r5_owner_password(owner_password, &o_entry, &u_entry)
366 } else {
367 self.security_handler
368 .validate_r6_owner_password(owner_password, &o_entry, &u_entry)
369 }
370 .map_err(|e| ParseError::SyntaxError {
371 position: 0,
372 message: format!(
373 "Failed to validate R{} owner password: {e}",
374 self.encryption_info.r
375 ),
376 })?;
377
378 if is_valid {
379 let oe_entry =
380 self.encryption_info
381 .oe
382 .as_deref()
383 .ok_or_else(|| ParseError::SyntaxError {
384 position: 0,
385 message: format!(
386 "R{} encryption requires OE entry but it is missing",
387 self.encryption_info.r
388 ),
389 })?;
390
391 let key = if self.encryption_info.r == 5 {
392 self.security_handler.recover_r5_owner_encryption_key(
393 owner_password,
394 &o_entry,
395 &u_entry,
396 oe_entry,
397 )
398 } else {
399 self.security_handler.recover_r6_owner_encryption_key(
400 owner_password,
401 &o_entry,
402 &u_entry,
403 oe_entry,
404 )
405 }
406 .map_err(|e| ParseError::SyntaxError {
407 position: 0,
408 message: format!(
409 "Failed to recover R{} owner encryption key: {e}",
410 self.encryption_info.r
411 ),
412 })?;
413
414 self.encryption_key = Some(EncryptionKey::new(key));
415 }
416
417 Ok(is_valid)
418 }
419
420 pub fn unlock_with_owner_password(&mut self, password: &str) -> ParseResult<bool> {
427 if self.encryption_info.r >= 5 {
431 return self.unlock_owner_r5_r6(&OwnerPassword(password.to_string()));
432 }
433
434 const PADDING: [u8; 32] = [
436 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA,
437 0x01, 0x08, 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE,
438 0x64, 0x53, 0x69, 0x7A,
439 ];
440
441 let mut padded = [0u8; 32];
443 let password_bytes = password.as_bytes();
444 let len = password_bytes.len().min(32);
445 padded[..len].copy_from_slice(&password_bytes[..len]);
446 if len < 32 {
447 padded[len..].copy_from_slice(&PADDING[..32 - len]);
448 }
449
450 let mut hash = md5::compute(&padded).to_vec();
452
453 let key_length = self.security_handler.key_length;
455 if self.encryption_info.r >= 3 {
456 for _ in 0..50 {
457 hash = md5::compute(&hash).to_vec();
458 }
459 }
460
461 if self.encryption_info.o.len() < 32 {
464 return Ok(false);
465 }
466 let mut decrypted = self.encryption_info.o[..32].to_vec();
467
468 if self.encryption_info.r >= 3 {
469 for i in (0..20).rev() {
471 let mut key_bytes = hash[..key_length].to_vec();
472 for byte in &mut key_bytes {
473 *byte ^= i as u8;
474 }
475 let rc4_key = Rc4Key::from_slice(&key_bytes);
476 let mut cipher = Rc4::new(&rc4_key);
477 decrypted = cipher.process(&decrypted);
478 }
479 } else {
480 let rc4_key = Rc4Key::from_slice(&hash[..key_length]);
482 let mut cipher = Rc4::new(&rc4_key);
483 decrypted = cipher.process(&decrypted);
484 }
485
486 let permissions = Permissions::from_bits(self.encryption_info.p as u32);
497 let encrypt_metadata = self.encryption_info.encrypt_metadata || self.encryption_info.r < 4;
498
499 let computed_u = self
500 .security_handler
501 .compute_user_hash_from_padded(
502 &decrypted,
503 &self.encryption_info.o,
504 permissions,
505 self.file_id.as_deref(),
506 encrypt_metadata,
507 )
508 .map_err(|e| ParseError::SyntaxError {
509 position: 0,
510 message: format!("Failed to compute user hash from /O: {e}"),
511 })?;
512
513 let comparison_length = if self.encryption_info.r >= 3 { 16 } else { 32 };
515 if computed_u.len() < comparison_length || self.encryption_info.u.len() < comparison_length
516 {
517 return Ok(false);
518 }
519 if computed_u[..comparison_length] != self.encryption_info.u[..comparison_length] {
520 return Ok(false);
521 }
522
523 let key = self
525 .security_handler
526 .compute_key_from_padded(
527 &decrypted,
528 &self.encryption_info.o,
529 permissions,
530 self.file_id.as_deref(),
531 encrypt_metadata,
532 )
533 .map_err(|e| ParseError::SyntaxError {
534 position: 0,
535 message: format!("Failed to compute key from /O: {e}"),
536 })?;
537 self.encryption_key = Some(key);
538 Ok(true)
539 }
540
541 pub fn try_empty_password(&mut self) -> ParseResult<bool> {
543 self.unlock_with_user_password("")
544 }
545
546 pub fn is_unlocked(&self) -> bool {
548 self.encryption_key.is_some()
549 }
550
551 pub fn encryption_key(&self) -> Option<&EncryptionKey> {
553 self.encryption_key.as_ref()
554 }
555
556 pub fn decrypt_string(&self, data: &[u8], obj_id: &ObjectId) -> ParseResult<Vec<u8>> {
561 match &self.encryption_key {
562 Some(key) => self
563 .security_handler
564 .try_decrypt_string(data, key, obj_id)
565 .map_err(|e| ParseError::SyntaxError {
566 position: 0,
567 message: format!("Failed to decrypt string for object {obj_id:?}: {e}"),
568 }),
569 None => Err(ParseError::EncryptionNotSupported),
570 }
571 }
572
573 pub fn decrypt_stream(&self, data: &[u8], obj_id: &ObjectId) -> ParseResult<Vec<u8>> {
578 match &self.encryption_key {
579 Some(key) => self
580 .security_handler
581 .try_decrypt_stream(data, key, obj_id)
582 .map_err(|e| ParseError::SyntaxError {
583 position: 0,
584 message: format!("Failed to decrypt stream for object {obj_id:?}: {e}"),
585 }),
586 None => Err(ParseError::EncryptionNotSupported),
587 }
588 }
589
590 pub fn algorithm_info(&self) -> String {
592 match (
593 self.encryption_info.r,
594 self.encryption_info.length.unwrap_or(40),
595 ) {
596 (2, _) => "RC4 40-bit".to_string(),
597 (3, len) => format!("RC4 {len}-bit"),
598 (4, len) => match self.encryption_info.cfm.as_deref() {
600 Some("V2") => format!("RC4 {len}-bit with metadata control"),
601 _ => "AES-128 (Revision 4)".to_string(),
602 },
603 (5, _) => "AES-256 (Revision 5)".to_string(),
604 (6, _) => "AES-256 (Revision 6, Unicode passwords)".to_string(),
605 (r, len) => format!("Unknown revision {r} with {len}-bit key"),
606 }
607 }
608
609 pub fn permissions(&self) -> Permissions {
611 Permissions::from_bits(self.encryption_info.p as u32)
612 }
613
614 pub fn has_file_id(&self) -> bool {
616 self.file_id.is_some()
617 }
618
619 pub fn revision(&self) -> i32 {
621 self.encryption_info.r
622 }
623
624 pub fn encrypt_strings(&self) -> bool {
626 true
628 }
629
630 pub fn encrypt_streams(&self) -> bool {
632 true
634 }
635
636 pub fn encrypt_metadata(&self) -> bool {
638 self.encryption_info.encrypt_metadata
639 }
640}
641
642#[derive(Debug)]
644pub enum PasswordResult {
645 Success,
647 Rejected,
649 Cancelled,
651}
652
653pub trait PasswordProvider {
655 fn prompt_user_password(&self) -> ParseResult<Option<String>>;
657
658 fn prompt_owner_password(&self) -> ParseResult<Option<String>>;
660}
661
662pub struct ConsolePasswordProvider;
664
665impl PasswordProvider for ConsolePasswordProvider {
666 fn prompt_user_password(&self) -> ParseResult<Option<String>> {
667 tracing::debug!(
668 "PDF is encrypted. Enter user password (or press Enter for empty password):"
669 );
670
671 let mut input = String::new();
672 std::io::stdin()
673 .read_line(&mut input)
674 .map_err(|e| ParseError::SyntaxError {
675 position: 0,
676 message: format!("Failed to read password: {e}"),
677 })?;
678
679 input.truncate(input.trim_end().len());
681 Ok(Some(input))
682 }
683
684 fn prompt_owner_password(&self) -> ParseResult<Option<String>> {
685 tracing::debug!("User password failed. Enter owner password:");
686
687 let mut input = String::new();
688 std::io::stdin()
689 .read_line(&mut input)
690 .map_err(|e| ParseError::SyntaxError {
691 position: 0,
692 message: format!("Failed to read password: {e}"),
693 })?;
694
695 input.truncate(input.trim_end().len());
697 Ok(Some(input))
698 }
699}
700
701pub struct InteractiveDecryption<P: PasswordProvider> {
703 password_provider: P,
704}
705
706impl<P: PasswordProvider> InteractiveDecryption<P> {
707 pub fn new(password_provider: P) -> Self {
709 Self { password_provider }
710 }
711
712 pub fn unlock_pdf(&self, handler: &mut EncryptionHandler) -> ParseResult<PasswordResult> {
714 if handler.try_empty_password()? {
716 return Ok(PasswordResult::Success);
717 }
718
719 if let Some(password) = self.password_provider.prompt_user_password()? {
721 if handler.unlock_with_user_password(&password)? {
722 return Ok(PasswordResult::Success);
723 }
724 } else {
725 return Ok(PasswordResult::Cancelled);
726 }
727
728 if let Some(password) = self.password_provider.prompt_owner_password()? {
730 if handler.unlock_with_owner_password(&password)? {
731 return Ok(PasswordResult::Success);
732 }
733 } else {
734 return Ok(PasswordResult::Cancelled);
735 }
736
737 Ok(PasswordResult::Rejected)
738 }
739}
740
741#[cfg(test)]
742mod tests {
743 use super::*;
744 use crate::parser::objects::{PdfDictionary, PdfName, PdfObject, PdfString};
745
746 fn create_test_encryption_dict() -> PdfDictionary {
747 let mut dict = PdfDictionary::new();
748 dict.insert(
749 "Filter".to_string(),
750 PdfObject::Name(PdfName("Standard".to_string())),
751 );
752 dict.insert("V".to_string(), PdfObject::Integer(1));
753 dict.insert("R".to_string(), PdfObject::Integer(2));
754 dict.insert(
755 "O".to_string(),
756 PdfObject::String(PdfString::new(vec![0u8; 32])),
757 );
758 dict.insert(
759 "U".to_string(),
760 PdfObject::String(PdfString::new(vec![0u8; 32])),
761 );
762 dict.insert("P".to_string(), PdfObject::Integer(-4));
763 dict
764 }
765
766 #[test]
767 fn test_encryption_detection() {
768 let mut trailer = PdfDictionary::new();
769 assert!(!EncryptionHandler::detect_encryption(&trailer));
770
771 trailer.insert("Encrypt".to_string(), PdfObject::Reference(1, 0));
772 assert!(EncryptionHandler::detect_encryption(&trailer));
773 }
774
775 #[test]
776 fn test_encryption_info_parsing() {
777 let dict = create_test_encryption_dict();
778 let info = EncryptionHandler::parse_encryption_dict(&dict).unwrap();
779
780 assert_eq!(info.filter, "Standard");
781 assert_eq!(info.v, 1);
782 assert_eq!(info.r, 2);
783 assert_eq!(info.o.len(), 32);
784 assert_eq!(info.u.len(), 32);
785 assert_eq!(info.p, -4);
786 assert_eq!(info.cfm, None);
788 }
789
790 fn create_v4_encryption_dict(cfm: &str) -> PdfDictionary {
792 let mut dict = PdfDictionary::new();
793 dict.insert(
794 "Filter".to_string(),
795 PdfObject::Name(PdfName("Standard".to_string())),
796 );
797 dict.insert("V".to_string(), PdfObject::Integer(4));
798 dict.insert("R".to_string(), PdfObject::Integer(4));
799 dict.insert("Length".to_string(), PdfObject::Integer(128));
800 dict.insert(
801 "O".to_string(),
802 PdfObject::String(PdfString::new(vec![0u8; 32])),
803 );
804 dict.insert(
805 "U".to_string(),
806 PdfObject::String(PdfString::new(vec![0u8; 32])),
807 );
808 dict.insert("P".to_string(), PdfObject::Integer(-4));
809
810 let mut std_cf = PdfDictionary::new();
811 std_cf.insert("CFM".to_string(), PdfObject::Name(PdfName(cfm.to_string())));
812 let mut cf = PdfDictionary::new();
813 cf.insert("StdCF".to_string(), PdfObject::Dictionary(std_cf));
814 dict.insert("CF".to_string(), PdfObject::Dictionary(cf));
815 dict.insert(
816 "StmF".to_string(),
817 PdfObject::Name(PdfName("StdCF".to_string())),
818 );
819 dict
820 }
821
822 #[test]
823 fn test_cfm_parsed_from_crypt_filter() {
824 let aes =
826 EncryptionHandler::parse_encryption_dict(&create_v4_encryption_dict("AESV2")).unwrap();
827 assert_eq!(aes.cfm.as_deref(), Some("AESV2"));
828
829 let rc4 =
830 EncryptionHandler::parse_encryption_dict(&create_v4_encryption_dict("V2")).unwrap();
831 assert_eq!(rc4.cfm.as_deref(), Some("V2"));
832 }
833
834 #[test]
835 fn test_r4_algorithm_info_reflects_cipher() {
836 let aes = EncryptionHandler::new(&create_v4_encryption_dict("AESV2"), None).unwrap();
838 assert_eq!(aes.algorithm_info(), "AES-128 (Revision 4)");
839
840 let rc4 = EncryptionHandler::new(&create_v4_encryption_dict("V2"), None).unwrap();
842 assert!(
843 rc4.algorithm_info().starts_with("RC4"),
844 "got: {}",
845 rc4.algorithm_info()
846 );
847 }
848
849 #[test]
850 fn test_encryption_handler_creation() {
851 let dict = create_test_encryption_dict();
852 let handler = EncryptionHandler::new(&dict, None).unwrap();
853
854 assert_eq!(handler.encryption_info.r, 2);
855 assert!(!handler.is_unlocked());
856 assert_eq!(handler.algorithm_info(), "RC4 40-bit");
857 }
858
859 #[test]
860 fn test_empty_password_attempt() {
861 let dict = create_test_encryption_dict();
862 let mut handler = EncryptionHandler::new(&dict, None).unwrap();
863
864 let result = handler.try_empty_password().unwrap();
866 assert!(!result);
867 assert!(!handler.is_unlocked());
868 }
869
870 #[test]
871 fn test_permissions() {
872 let dict = create_test_encryption_dict();
873 let handler = EncryptionHandler::new(&dict, None).unwrap();
874
875 let permissions = handler.permissions();
876 assert!(permissions.bits() != 0);
878 }
879
880 #[test]
881 fn test_encryption_flags() {
882 let dict = create_test_encryption_dict();
883 let handler = EncryptionHandler::new(&dict, None).unwrap();
884
885 assert!(handler.encrypt_strings());
886 assert!(handler.encrypt_streams());
887 assert!(handler.encrypt_metadata());
888 }
889
890 #[test]
891 fn test_decrypt_without_key() {
892 let dict = create_test_encryption_dict();
893 let handler = EncryptionHandler::new(&dict, None).unwrap();
894
895 let obj_id = ObjectId::new(1, 0);
896 let result = handler.decrypt_string(b"test", &obj_id);
897 assert!(result.is_err());
898 }
899
900 #[test]
901 fn test_unsupported_filter() {
902 let mut dict = PdfDictionary::new();
903 dict.insert(
904 "Filter".to_string(),
905 PdfObject::Name(PdfName("UnsupportedFilter".to_string())),
906 );
907 dict.insert("R".to_string(), PdfObject::Integer(2));
908 dict.insert(
909 "O".to_string(),
910 PdfObject::String(PdfString::new(vec![0u8; 32])),
911 );
912 dict.insert(
913 "U".to_string(),
914 PdfObject::String(PdfString::new(vec![0u8; 32])),
915 );
916 dict.insert("P".to_string(), PdfObject::Integer(-4));
917
918 let result = EncryptionHandler::new(&dict, None);
919 assert!(result.is_err());
920 }
921
922 #[test]
923 fn test_unsupported_revision() {
924 let mut dict = create_test_encryption_dict();
925 dict.insert("R".to_string(), PdfObject::Integer(99)); let result = EncryptionHandler::new(&dict, None);
928 assert!(result.is_err());
929 }
930
931 #[test]
932 fn test_missing_required_keys() {
933 let test_cases = vec![
934 ("Filter", PdfObject::Name(PdfName("Standard".to_string()))),
935 ("R", PdfObject::Integer(2)),
936 ("O", PdfObject::String(PdfString::new(vec![0u8; 32]))),
937 ("U", PdfObject::String(PdfString::new(vec![0u8; 32]))),
938 ("P", PdfObject::Integer(-4)),
939 ];
940
941 for (skip_key, _) in test_cases {
942 let mut dict = create_test_encryption_dict();
943 dict.0.remove(&PdfName(skip_key.to_string()));
944
945 let result = EncryptionHandler::parse_encryption_dict(&dict);
946 assert!(result.is_err(), "Should fail when {skip_key} is missing");
947 }
948 }
949
950 struct MockPasswordProvider {
952 user_password: Option<String>,
953 owner_password: Option<String>,
954 }
955
956 impl PasswordProvider for MockPasswordProvider {
957 fn prompt_user_password(&self) -> ParseResult<Option<String>> {
958 Ok(self.user_password.clone())
959 }
960
961 fn prompt_owner_password(&self) -> ParseResult<Option<String>> {
962 Ok(self.owner_password.clone())
963 }
964 }
965
966 #[test]
967 fn test_interactive_decryption_cancelled() {
968 let provider = MockPasswordProvider {
969 user_password: None,
970 owner_password: None,
971 };
972
973 let decryption = InteractiveDecryption::new(provider);
974 let dict = create_test_encryption_dict();
975 let mut handler = EncryptionHandler::new(&dict, None).unwrap();
976
977 let result = decryption.unlock_pdf(&mut handler).unwrap();
978 matches!(result, PasswordResult::Cancelled);
979 }
980
981 #[test]
982 fn test_interactive_decryption_rejected() {
983 let provider = MockPasswordProvider {
984 user_password: Some("wrong_password".to_string()),
985 owner_password: Some("also_wrong".to_string()),
986 };
987
988 let decryption = InteractiveDecryption::new(provider);
989 let dict = create_test_encryption_dict();
990 let mut handler = EncryptionHandler::new(&dict, None).unwrap();
991
992 let result = decryption.unlock_pdf(&mut handler).unwrap();
993 matches!(result, PasswordResult::Rejected);
994 }
995
996 #[test]
999 fn test_malformed_encryption_dictionary_invalid_types() {
1000 let mut dict = PdfDictionary::new();
1002 dict.insert("Filter".to_string(), PdfObject::Integer(123)); dict.insert("R".to_string(), PdfObject::Integer(2));
1004 dict.insert(
1005 "O".to_string(),
1006 PdfObject::String(PdfString::new(vec![0u8; 32])),
1007 );
1008 dict.insert(
1009 "U".to_string(),
1010 PdfObject::String(PdfString::new(vec![0u8; 32])),
1011 );
1012 dict.insert("P".to_string(), PdfObject::Integer(-4));
1013
1014 let result = EncryptionHandler::parse_encryption_dict(&dict);
1015 assert!(result.is_err());
1016
1017 let mut dict = create_test_encryption_dict();
1019 dict.insert(
1020 "R".to_string(),
1021 PdfObject::Name(PdfName("not_a_number".to_string())),
1022 );
1023 let result = EncryptionHandler::parse_encryption_dict(&dict);
1024 assert!(result.is_err());
1025 }
1026
1027 #[test]
1028 fn test_encryption_dictionary_edge_values() {
1029 let mut dict = create_test_encryption_dict();
1031 dict.insert("R".to_string(), PdfObject::Integer(0)); let result = EncryptionHandler::new(&dict, None);
1033 assert!(result.is_err());
1034
1035 let mut dict = create_test_encryption_dict();
1037 dict.insert("R".to_string(), PdfObject::Integer(-1));
1038 let result = EncryptionHandler::new(&dict, None);
1039 assert!(result.is_err());
1040
1041 let mut dict = create_test_encryption_dict();
1043 dict.insert("R".to_string(), PdfObject::Integer(1000));
1044 let result = EncryptionHandler::new(&dict, None);
1045 assert!(result.is_err());
1046 }
1047
1048 #[test]
1049 fn test_encryption_dictionary_invalid_hash_lengths() {
1050 let mut dict = create_test_encryption_dict();
1052 dict.insert(
1053 "O".to_string(),
1054 PdfObject::String(PdfString::new(vec![0u8; 16])),
1055 ); let result = EncryptionHandler::parse_encryption_dict(&dict);
1057 assert!(result.is_ok());
1059
1060 let mut dict = create_test_encryption_dict();
1062 dict.insert(
1063 "U".to_string(),
1064 PdfObject::String(PdfString::new(vec![0u8; 64])),
1065 ); let result = EncryptionHandler::parse_encryption_dict(&dict);
1067 assert!(result.is_ok());
1068
1069 let mut dict = create_test_encryption_dict();
1071 dict.insert("O".to_string(), PdfObject::String(PdfString::new(vec![])));
1072 dict.insert("U".to_string(), PdfObject::String(PdfString::new(vec![])));
1073 let result = EncryptionHandler::parse_encryption_dict(&dict);
1074 assert!(result.is_ok());
1075 }
1076
1077 #[test]
1078 fn test_encryption_with_different_key_lengths() {
1079 let mut dict = create_test_encryption_dict();
1081 dict.insert("R".to_string(), PdfObject::Integer(2));
1082 let handler = EncryptionHandler::new(&dict, None).unwrap();
1083 assert_eq!(handler.algorithm_info(), "RC4 40-bit");
1084
1085 let mut dict = create_test_encryption_dict();
1087 dict.insert("R".to_string(), PdfObject::Integer(3));
1088 dict.insert("Length".to_string(), PdfObject::Integer(128));
1089 let handler = EncryptionHandler::new(&dict, None).unwrap();
1090 assert_eq!(handler.algorithm_info(), "RC4 128-bit");
1091
1092 let mut dict = create_test_encryption_dict();
1096 dict.insert("R".to_string(), PdfObject::Integer(4));
1097 dict.insert("Length".to_string(), PdfObject::Integer(128));
1098 let handler = EncryptionHandler::new(&dict, None).unwrap();
1099 assert_eq!(handler.algorithm_info(), "AES-128 (Revision 4)");
1100
1101 let mut dict = create_test_encryption_dict();
1103 dict.insert("R".to_string(), PdfObject::Integer(5));
1104 dict.insert("V".to_string(), PdfObject::Integer(5));
1105 let handler = EncryptionHandler::new(&dict, None).unwrap();
1106 assert_eq!(handler.algorithm_info(), "AES-256 (Revision 5)");
1107
1108 let mut dict = create_test_encryption_dict();
1110 dict.insert("R".to_string(), PdfObject::Integer(6));
1111 dict.insert("V".to_string(), PdfObject::Integer(5));
1112 let handler = EncryptionHandler::new(&dict, None).unwrap();
1113 assert_eq!(
1114 handler.algorithm_info(),
1115 "AES-256 (Revision 6, Unicode passwords)"
1116 );
1117 }
1118
1119 #[test]
1120 fn test_file_id_handling() {
1121 let dict = create_test_encryption_dict();
1122
1123 let file_id = Some(b"test_file_id_12345678".to_vec());
1125 let handler = EncryptionHandler::new(&dict, file_id.clone()).unwrap();
1126 assert_eq!(handler.file_id, file_id);
1128
1129 let handler = EncryptionHandler::new(&dict, None).unwrap();
1131 assert_eq!(handler.file_id, None);
1132
1133 let empty_file_id = Some(vec![]);
1135 let handler = EncryptionHandler::new(&dict, empty_file_id.clone()).unwrap();
1136 assert_eq!(handler.file_id, empty_file_id);
1137 }
1138
1139 #[test]
1140 fn test_permissions_edge_cases() {
1141 let permission_values = vec![0, -1, -4, -44, -100, i32::MAX, i32::MIN];
1143
1144 for p_value in permission_values {
1145 let mut dict = create_test_encryption_dict();
1146 dict.insert("P".to_string(), PdfObject::Integer(p_value as i64));
1147 let handler = EncryptionHandler::new(&dict, None).unwrap();
1148
1149 let permissions = handler.permissions();
1150 assert_eq!(permissions.bits(), p_value as u32);
1151 }
1152 }
1153
1154 #[test]
1155 fn test_decrypt_with_different_object_ids() {
1156 let dict = create_test_encryption_dict();
1157 let handler = EncryptionHandler::new(&dict, None).unwrap();
1158 let test_data = b"test data";
1159
1160 let object_ids = vec![
1162 ObjectId::new(1, 0),
1163 ObjectId::new(999, 0),
1164 ObjectId::new(1, 999),
1165 ObjectId::new(u32::MAX, u16::MAX),
1166 ];
1167
1168 for obj_id in object_ids {
1169 let result = handler.decrypt_string(test_data, &obj_id);
1170 assert!(result.is_err());
1171
1172 let result = handler.decrypt_stream(test_data, &obj_id);
1173 assert!(result.is_err());
1174 }
1175 }
1176
1177 #[test]
1178 fn test_password_scenarios_comprehensive() {
1179 let dict = create_test_encryption_dict();
1180 let mut handler = EncryptionHandler::new(&dict, None).unwrap();
1181
1182 let test_passwords = vec![
1184 "".to_string(), " ".to_string(), " ".to_string(), "password".to_string(), "Password123!@#".to_string(), "a".repeat(32), "a".repeat(50), "unicode_ñáéíóú".to_string(), "pass\nwith\nnewlines".to_string(), "pass\twith\ttabs".to_string(), "pass with spaces".to_string(), "🔐🗝️📄".to_string(), ];
1197
1198 for password in test_passwords {
1199 let result = handler.unlock_with_user_password(&password);
1201 assert!(result.is_ok());
1202 assert!(!result.unwrap());
1203
1204 let result = handler.unlock_with_owner_password(&password);
1205 assert!(result.is_ok());
1206 assert!(!result.unwrap());
1207 }
1208 }
1209
1210 #[test]
1211 fn test_encryption_handler_thread_safety_simulation() {
1212 let dict = create_test_encryption_dict();
1214 let handler = EncryptionHandler::new(&dict, None).unwrap();
1215
1216 for _ in 0..100 {
1218 assert!(!handler.is_unlocked());
1219 assert_eq!(handler.algorithm_info(), "RC4 40-bit");
1220 assert!(handler.encrypt_strings());
1221 assert!(handler.encrypt_streams());
1222 assert!(handler.encrypt_metadata());
1223 }
1224 }
1225
1226 #[test]
1227 fn test_encryption_state_transitions() {
1228 let dict = create_test_encryption_dict();
1229 let mut handler = EncryptionHandler::new(&dict, None).unwrap();
1230
1231 assert!(!handler.is_unlocked());
1233
1234 let result = handler.try_empty_password().unwrap();
1236 assert!(!result);
1237 assert!(!handler.is_unlocked());
1238
1239 let result = handler.unlock_with_user_password("test").unwrap();
1241 assert!(!result);
1242 assert!(!handler.is_unlocked());
1243
1244 let result = handler.unlock_with_owner_password("test").unwrap();
1246 assert!(!result);
1247 assert!(!handler.is_unlocked());
1248
1249 assert!(!handler.is_unlocked());
1251 }
1252
1253 #[test]
1254 fn test_interactive_decryption_edge_cases() {
1255 let provider = MockPasswordProvider {
1257 user_password: None,
1258 owner_password: None,
1259 };
1260
1261 let decryption = InteractiveDecryption::new(provider);
1262 let dict = create_test_encryption_dict();
1263 let mut handler = EncryptionHandler::new(&dict, None).unwrap();
1264
1265 let result = decryption.unlock_pdf(&mut handler).unwrap();
1266 matches!(result, PasswordResult::Cancelled);
1267
1268 let provider = MockPasswordProvider {
1270 user_password: Some("".to_string()),
1271 owner_password: Some("".to_string()),
1272 };
1273
1274 let decryption = InteractiveDecryption::new(provider);
1275 let mut handler = EncryptionHandler::new(&dict, None).unwrap();
1276
1277 let result = decryption.unlock_pdf(&mut handler).unwrap();
1278 matches!(result, PasswordResult::Rejected);
1279 }
1280
1281 struct EdgeCasePasswordProvider {
1283 call_count: std::cell::RefCell<usize>,
1284 passwords: Vec<Option<String>>,
1285 }
1286
1287 impl EdgeCasePasswordProvider {
1288 fn new(passwords: Vec<Option<String>>) -> Self {
1289 Self {
1290 call_count: std::cell::RefCell::new(0),
1291 passwords,
1292 }
1293 }
1294 }
1295
1296 impl PasswordProvider for EdgeCasePasswordProvider {
1297 fn prompt_user_password(&self) -> ParseResult<Option<String>> {
1298 let mut count = self.call_count.borrow_mut();
1299 if *count < self.passwords.len() {
1300 let result = self.passwords[*count].clone();
1301 *count += 1;
1302 Ok(result)
1303 } else {
1304 Ok(None)
1305 }
1306 }
1307
1308 fn prompt_owner_password(&self) -> ParseResult<Option<String>> {
1309 self.prompt_user_password()
1310 }
1311 }
1312
1313 #[test]
1314 fn test_interactive_decryption_with_sequence() {
1315 let passwords = vec![
1316 Some("first_attempt".to_string()),
1317 Some("second_attempt".to_string()),
1318 None, ];
1320
1321 let provider = EdgeCasePasswordProvider::new(passwords);
1322 let decryption = InteractiveDecryption::new(provider);
1323 let dict = create_test_encryption_dict();
1324 let mut handler = EncryptionHandler::new(&dict, None).unwrap();
1325
1326 let result = decryption.unlock_pdf(&mut handler).unwrap();
1327 matches!(result, PasswordResult::Cancelled);
1328 }
1329}