1use crate::encryption::{CryptFilterMethod, EncryptionKey, StandardSecurityHandler};
7use crate::error::{PdfError, Result};
8use crate::objects::{Dictionary, Object, ObjectId};
9use std::collections::HashMap;
10
11#[derive(Debug, Clone)]
13pub struct FunctionalCryptFilter {
14 pub name: String,
16 pub method: CryptFilterMethod,
18 pub length: Option<u32>,
20 pub auth_event: AuthEvent,
22 pub recipients: Option<Vec<String>>,
24}
25
26#[derive(Debug, Clone, Copy, PartialEq)]
28pub enum AuthEvent {
29 DocOpen,
31 EFOpen,
33}
34
35impl AuthEvent {
36 pub fn pdf_name(&self) -> &'static str {
38 match self {
39 AuthEvent::DocOpen => "DocOpen",
40 AuthEvent::EFOpen => "EFOpen",
41 }
42 }
43}
44
45pub struct CryptFilterManager {
47 filters: HashMap<String, FunctionalCryptFilter>,
49 default_stream_filter: String,
51 default_string_filter: String,
53 embedded_files_filter: Option<String>,
55 security_handler: Box<dyn SecurityHandler>,
57}
58
59impl CryptFilterManager {
60 pub fn new(
62 security_handler: Box<dyn SecurityHandler>,
63 default_stream_filter: String,
64 default_string_filter: String,
65 ) -> Self {
66 let mut manager = Self {
67 filters: HashMap::new(),
68 default_stream_filter,
69 default_string_filter,
70 embedded_files_filter: None,
71 security_handler,
72 };
73
74 manager.add_filter(FunctionalCryptFilter {
76 name: "Identity".to_string(),
77 method: CryptFilterMethod::None,
78 length: None,
79 auth_event: AuthEvent::DocOpen,
80 recipients: None,
81 });
82
83 manager
84 }
85
86 pub fn add_filter(&mut self, filter: FunctionalCryptFilter) {
88 self.filters.insert(filter.name.clone(), filter);
89 }
90
91 pub fn set_embedded_files_filter(&mut self, filter_name: String) {
93 self.embedded_files_filter = Some(filter_name);
94 }
95
96 pub fn get_filter(&self, name: &str) -> Option<&FunctionalCryptFilter> {
98 self.filters.get(name)
99 }
100
101 pub fn encrypt_string(
103 &self,
104 data: &[u8],
105 obj_id: &ObjectId,
106 filter_name: Option<&str>,
107 encryption_key: &EncryptionKey,
108 ) -> Result<Vec<u8>> {
109 let filter_name = filter_name.unwrap_or(&self.default_string_filter);
110 let filter = self.get_filter(filter_name).ok_or_else(|| {
111 PdfError::EncryptionError(format!("Crypt filter '{filter_name}' not found"))
112 })?;
113
114 match filter.method {
115 CryptFilterMethod::None => Ok(data.to_vec()),
116 CryptFilterMethod::V2 => {
117 self.security_handler
119 .encrypt_string(data, encryption_key, obj_id)
120 }
121 CryptFilterMethod::AESV2 => {
122 self.security_handler
124 .encrypt_string_aes(data, encryption_key, obj_id, 128)
125 }
126 CryptFilterMethod::AESV3 => {
127 self.security_handler
129 .encrypt_string_aes(data, encryption_key, obj_id, 256)
130 }
131 }
132 }
133
134 pub fn decrypt_string(
136 &self,
137 data: &[u8],
138 obj_id: &ObjectId,
139 filter_name: Option<&str>,
140 encryption_key: &EncryptionKey,
141 ) -> Result<Vec<u8>> {
142 let filter_name = filter_name.unwrap_or(&self.default_string_filter);
143 let filter = self.get_filter(filter_name).ok_or_else(|| {
144 PdfError::EncryptionError(format!("Crypt filter '{filter_name}' not found"))
145 })?;
146
147 match filter.method {
148 CryptFilterMethod::None => Ok(data.to_vec()),
149 CryptFilterMethod::V2 => {
150 self.security_handler
152 .decrypt_string(data, encryption_key, obj_id)
153 }
154 CryptFilterMethod::AESV2 => {
155 self.security_handler
157 .decrypt_string_aes(data, encryption_key, obj_id, 128)
158 }
159 CryptFilterMethod::AESV3 => {
160 self.security_handler
162 .decrypt_string_aes(data, encryption_key, obj_id, 256)
163 }
164 }
165 }
166
167 pub fn encrypt_stream(
169 &self,
170 data: &[u8],
171 obj_id: &ObjectId,
172 stream_dict: &Dictionary,
173 encryption_key: &EncryptionKey,
174 ) -> Result<Vec<u8>> {
175 let filter_name = self.get_stream_filter_name(stream_dict);
177 let filter = self.get_filter(&filter_name).ok_or_else(|| {
178 PdfError::EncryptionError(format!("Crypt filter '{filter_name}' not found"))
179 })?;
180
181 match filter.method {
182 CryptFilterMethod::None => Ok(data.to_vec()),
183 CryptFilterMethod::V2 => {
184 self.security_handler
186 .encrypt_stream(data, encryption_key, obj_id)
187 }
188 CryptFilterMethod::AESV2 => {
189 self.security_handler
191 .encrypt_stream_aes(data, encryption_key, obj_id, 128)
192 }
193 CryptFilterMethod::AESV3 => {
194 self.security_handler
196 .encrypt_stream_aes(data, encryption_key, obj_id, 256)
197 }
198 }
199 }
200
201 pub fn decrypt_stream(
203 &self,
204 data: &[u8],
205 obj_id: &ObjectId,
206 stream_dict: &Dictionary,
207 encryption_key: &EncryptionKey,
208 ) -> Result<Vec<u8>> {
209 let filter_name = self.get_stream_filter_name(stream_dict);
211 let filter = self.get_filter(&filter_name).ok_or_else(|| {
212 PdfError::EncryptionError(format!("Crypt filter '{filter_name}' not found"))
213 })?;
214
215 match filter.method {
216 CryptFilterMethod::None => Ok(data.to_vec()),
217 CryptFilterMethod::V2 => {
218 self.security_handler
220 .decrypt_stream(data, encryption_key, obj_id)
221 }
222 CryptFilterMethod::AESV2 => {
223 self.security_handler
225 .decrypt_stream_aes(data, encryption_key, obj_id, 128)
226 }
227 CryptFilterMethod::AESV3 => {
228 self.security_handler
230 .decrypt_stream_aes(data, encryption_key, obj_id, 256)
231 }
232 }
233 }
234
235 fn get_stream_filter_name(&self, stream_dict: &Dictionary) -> String {
237 if let Some(Object::Array(filters)) = stream_dict.get("Filter") {
239 for filter in filters {
241 if let Object::Name(name) = filter {
242 if name == "Crypt" {
243 if let Some(Object::Dictionary(decode_parms)) =
245 stream_dict.get("DecodeParms")
246 {
247 if let Some(Object::Name(crypt_name)) = decode_parms.get("Name") {
248 return crypt_name.clone();
249 }
250 }
251 }
252 }
253 }
254 }
255
256 self.default_stream_filter.clone()
258 }
259
260 pub fn create_standard_filter(
262 method: CryptFilterMethod,
263 key_length: Option<u32>,
264 ) -> FunctionalCryptFilter {
265 FunctionalCryptFilter {
266 name: "StdCF".to_string(),
267 method,
268 length: key_length,
269 auth_event: AuthEvent::DocOpen,
270 recipients: None,
271 }
272 }
273
274 pub fn to_cf_dict(&self) -> Dictionary {
276 let mut cf_dict = Dictionary::new();
277
278 for (name, filter) in &self.filters {
279 if name != "Identity" {
280 cf_dict.set(name, Object::Dictionary(filter.to_dict()));
281 }
282 }
283
284 cf_dict
285 }
286}
287
288impl FunctionalCryptFilter {
289 pub fn to_dict(&self) -> Dictionary {
291 let mut dict = Dictionary::new();
292
293 dict.set("CFM", Object::Name(self.method.pdf_name().to_string()));
294
295 if let Some(length) = self.length {
296 dict.set("Length", Object::Integer(length as i64));
297 }
298
299 dict.set(
300 "AuthEvent",
301 Object::Name(self.auth_event.pdf_name().to_string()),
302 );
303
304 if let Some(ref recipients) = self.recipients {
305 let recipient_array: Vec<Object> = recipients
306 .iter()
307 .map(|r| Object::String(r.clone()))
308 .collect();
309 dict.set("Recipients", Object::Array(recipient_array));
310 }
311
312 dict
313 }
314}
315
316pub trait SecurityHandler: Send + Sync {
318 fn encrypt_string(
320 &self,
321 data: &[u8],
322 key: &EncryptionKey,
323 obj_id: &ObjectId,
324 ) -> Result<Vec<u8>>;
325
326 fn decrypt_string(
328 &self,
329 data: &[u8],
330 key: &EncryptionKey,
331 obj_id: &ObjectId,
332 ) -> Result<Vec<u8>>;
333
334 fn encrypt_stream(
336 &self,
337 data: &[u8],
338 key: &EncryptionKey,
339 obj_id: &ObjectId,
340 ) -> Result<Vec<u8>>;
341
342 fn decrypt_stream(
344 &self,
345 data: &[u8],
346 key: &EncryptionKey,
347 obj_id: &ObjectId,
348 ) -> Result<Vec<u8>>;
349
350 fn encrypt_string_aes(
352 &self,
353 data: &[u8],
354 key: &EncryptionKey,
355 obj_id: &ObjectId,
356 bits: u32,
357 ) -> Result<Vec<u8>>;
358
359 fn decrypt_string_aes(
361 &self,
362 data: &[u8],
363 key: &EncryptionKey,
364 obj_id: &ObjectId,
365 bits: u32,
366 ) -> Result<Vec<u8>>;
367
368 fn encrypt_stream_aes(
370 &self,
371 data: &[u8],
372 key: &EncryptionKey,
373 obj_id: &ObjectId,
374 bits: u32,
375 ) -> Result<Vec<u8>>;
376
377 fn decrypt_stream_aes(
379 &self,
380 data: &[u8],
381 key: &EncryptionKey,
382 obj_id: &ObjectId,
383 bits: u32,
384 ) -> Result<Vec<u8>>;
385}
386
387impl SecurityHandler for StandardSecurityHandler {
389 fn encrypt_string(
390 &self,
391 data: &[u8],
392 key: &EncryptionKey,
393 obj_id: &ObjectId,
394 ) -> Result<Vec<u8>> {
395 Ok(self.encrypt_string(data, key, obj_id))
396 }
397
398 fn decrypt_string(
399 &self,
400 data: &[u8],
401 key: &EncryptionKey,
402 obj_id: &ObjectId,
403 ) -> Result<Vec<u8>> {
404 Ok(self.decrypt_string(data, key, obj_id))
405 }
406
407 fn encrypt_stream(
408 &self,
409 data: &[u8],
410 key: &EncryptionKey,
411 obj_id: &ObjectId,
412 ) -> Result<Vec<u8>> {
413 Ok(self.encrypt_stream(data, key, obj_id))
414 }
415
416 fn decrypt_stream(
417 &self,
418 data: &[u8],
419 key: &EncryptionKey,
420 obj_id: &ObjectId,
421 ) -> Result<Vec<u8>> {
422 Ok(self.decrypt_stream(data, key, obj_id))
423 }
424
425 fn encrypt_string_aes(
426 &self,
427 data: &[u8],
428 key: &EncryptionKey,
429 obj_id: &ObjectId,
430 bits: u32,
431 ) -> Result<Vec<u8>> {
432 match bits {
433 128 | 256 => {
434 self.encrypt_aes(data, key, obj_id)
436 }
437 _ => Err(PdfError::EncryptionError(format!(
438 "Unsupported AES key size: {bits} bits"
439 ))),
440 }
441 }
442
443 fn decrypt_string_aes(
444 &self,
445 data: &[u8],
446 key: &EncryptionKey,
447 obj_id: &ObjectId,
448 bits: u32,
449 ) -> Result<Vec<u8>> {
450 match bits {
451 128 | 256 => {
452 self.decrypt_aes(data, key, obj_id)
454 }
455 _ => Err(PdfError::EncryptionError(format!(
456 "Unsupported AES key size: {bits} bits"
457 ))),
458 }
459 }
460
461 fn encrypt_stream_aes(
462 &self,
463 data: &[u8],
464 key: &EncryptionKey,
465 obj_id: &ObjectId,
466 bits: u32,
467 ) -> Result<Vec<u8>> {
468 self.encrypt_string_aes(data, key, obj_id, bits)
469 }
470
471 fn decrypt_stream_aes(
472 &self,
473 data: &[u8],
474 key: &EncryptionKey,
475 obj_id: &ObjectId,
476 bits: u32,
477 ) -> Result<Vec<u8>> {
478 self.decrypt_string_aes(data, key, obj_id, bits)
479 }
480}
481
482#[cfg(test)]
483mod tests {
484 use super::*;
485
486 #[test]
487 fn test_auth_event_pdf_names() {
488 assert_eq!(AuthEvent::DocOpen.pdf_name(), "DocOpen");
489 assert_eq!(AuthEvent::EFOpen.pdf_name(), "EFOpen");
490 }
491
492 #[test]
493 fn test_functional_crypt_filter_creation() {
494 let filter = FunctionalCryptFilter {
495 name: "TestFilter".to_string(),
496 method: CryptFilterMethod::AESV2,
497 length: Some(16),
498 auth_event: AuthEvent::DocOpen,
499 recipients: None,
500 };
501
502 assert_eq!(filter.name, "TestFilter");
503 assert_eq!(filter.method, CryptFilterMethod::AESV2);
504 assert_eq!(filter.length, Some(16));
505 assert_eq!(filter.auth_event, AuthEvent::DocOpen);
506 }
507
508 #[test]
509 fn test_crypt_filter_to_dict() {
510 let filter = FunctionalCryptFilter {
511 name: "MyFilter".to_string(),
512 method: CryptFilterMethod::V2,
513 length: Some(16),
514 auth_event: AuthEvent::EFOpen,
515 recipients: Some(vec!["recipient1".to_string(), "recipient2".to_string()]),
516 };
517
518 let dict = filter.to_dict();
519 assert_eq!(dict.get("CFM"), Some(&Object::Name("V2".to_string())));
520 assert_eq!(dict.get("Length"), Some(&Object::Integer(16)));
521 assert_eq!(
522 dict.get("AuthEvent"),
523 Some(&Object::Name("EFOpen".to_string()))
524 );
525 assert!(dict.get("Recipients").is_some());
526 }
527
528 #[test]
529 fn test_crypt_filter_manager_creation() {
530 let handler = StandardSecurityHandler::rc4_128bit();
531 let manager =
532 CryptFilterManager::new(Box::new(handler), "StdCF".to_string(), "StdCF".to_string());
533
534 assert!(manager.get_filter("Identity").is_some());
536 }
537
538 #[test]
539 fn test_add_and_get_filter() {
540 let handler = StandardSecurityHandler::rc4_128bit();
541 let mut manager =
542 CryptFilterManager::new(Box::new(handler), "StdCF".to_string(), "StdCF".to_string());
543
544 let filter = FunctionalCryptFilter {
545 name: "CustomFilter".to_string(),
546 method: CryptFilterMethod::AESV3,
547 length: None,
548 auth_event: AuthEvent::DocOpen,
549 recipients: None,
550 };
551
552 manager.add_filter(filter.clone());
553
554 let retrieved = manager.get_filter("CustomFilter");
555 assert!(retrieved.is_some());
556 assert_eq!(retrieved.unwrap().method, CryptFilterMethod::AESV3);
557 }
558
559 #[test]
560 fn test_standard_filter_creation() {
561 let filter = CryptFilterManager::create_standard_filter(CryptFilterMethod::AESV2, Some(16));
562
563 assert_eq!(filter.name, "StdCF");
564 assert_eq!(filter.method, CryptFilterMethod::AESV2);
565 assert_eq!(filter.length, Some(16));
566 assert_eq!(filter.auth_event, AuthEvent::DocOpen);
567 }
568
569 #[test]
570 fn test_encrypt_decrypt_string_identity() {
571 let handler = StandardSecurityHandler::rc4_128bit();
572 let manager = CryptFilterManager::new(
573 Box::new(handler),
574 "Identity".to_string(),
575 "Identity".to_string(),
576 );
577
578 let data = b"Test data";
579 let obj_id = ObjectId::new(1, 0);
580 let key = EncryptionKey::new(vec![0u8; 16]);
581
582 let encrypted = manager.encrypt_string(data, &obj_id, None, &key).unwrap();
583 assert_eq!(encrypted, data);
584
585 let decrypted = manager
586 .decrypt_string(&encrypted, &obj_id, None, &key)
587 .unwrap();
588 assert_eq!(decrypted, data);
589 }
590
591 #[test]
592 fn test_set_embedded_files_filter() {
593 let handler = StandardSecurityHandler::rc4_128bit();
594 let mut manager =
595 CryptFilterManager::new(Box::new(handler), "StdCF".to_string(), "StdCF".to_string());
596
597 manager.set_embedded_files_filter("EFFFilter".to_string());
598 assert_eq!(manager.embedded_files_filter, Some("EFFFilter".to_string()));
599 }
600
601 #[test]
602 fn test_to_cf_dict() {
603 let handler = StandardSecurityHandler::rc4_128bit();
604 let mut manager =
605 CryptFilterManager::new(Box::new(handler), "StdCF".to_string(), "StdCF".to_string());
606
607 let filter1 = FunctionalCryptFilter {
608 name: "Filter1".to_string(),
609 method: CryptFilterMethod::V2,
610 length: Some(16),
611 auth_event: AuthEvent::DocOpen,
612 recipients: None,
613 };
614
615 let filter2 = FunctionalCryptFilter {
616 name: "Filter2".to_string(),
617 method: CryptFilterMethod::AESV2,
618 length: None,
619 auth_event: AuthEvent::EFOpen,
620 recipients: None,
621 };
622
623 manager.add_filter(filter1);
624 manager.add_filter(filter2);
625
626 let cf_dict = manager.to_cf_dict();
627
628 assert!(cf_dict.get("Identity").is_none());
630
631 assert!(cf_dict.get("Filter1").is_some());
633 assert!(cf_dict.get("Filter2").is_some());
634 }
635
636 #[test]
637 fn test_get_stream_filter_name_default() {
638 let handler = StandardSecurityHandler::rc4_128bit();
639 let manager = CryptFilterManager::new(
640 Box::new(handler),
641 "DefaultStreamFilter".to_string(),
642 "StdCF".to_string(),
643 );
644
645 let stream_dict = Dictionary::new();
646 let filter_name = manager.get_stream_filter_name(&stream_dict);
647 assert_eq!(filter_name, "DefaultStreamFilter");
648 }
649
650 #[test]
651 fn test_get_stream_filter_name_with_crypt() {
652 let handler = StandardSecurityHandler::rc4_128bit();
653 let manager = CryptFilterManager::new(
654 Box::new(handler),
655 "DefaultStreamFilter".to_string(),
656 "StdCF".to_string(),
657 );
658
659 let mut stream_dict = Dictionary::new();
660 let filters = vec![
661 Object::Name("FlateDecode".to_string()),
662 Object::Name("Crypt".to_string()),
663 ];
664 stream_dict.set("Filter", Object::Array(filters));
665
666 let mut decode_parms = Dictionary::new();
667 decode_parms.set("Name", Object::Name("SpecialFilter".to_string()));
668 stream_dict.set("DecodeParms", Object::Dictionary(decode_parms));
669
670 let filter_name = manager.get_stream_filter_name(&stream_dict);
671 assert_eq!(filter_name, "SpecialFilter");
672 }
673
674 #[test]
675 fn test_auth_event_equality() {
676 assert_eq!(AuthEvent::DocOpen, AuthEvent::DocOpen);
677 assert_eq!(AuthEvent::EFOpen, AuthEvent::EFOpen);
678 assert_ne!(AuthEvent::DocOpen, AuthEvent::EFOpen);
679 }
680
681 #[test]
682 fn test_crypt_filter_with_recipients() {
683 let recipients = vec![
684 "user1@example.com".to_string(),
685 "user2@example.com".to_string(),
686 ];
687
688 let filter = FunctionalCryptFilter {
689 name: "PublicKeyFilter".to_string(),
690 method: CryptFilterMethod::AESV3,
691 length: None,
692 auth_event: AuthEvent::DocOpen,
693 recipients: Some(recipients.clone()),
694 };
695
696 let dict = filter.to_dict();
697
698 if let Some(Object::Array(recipient_array)) = dict.get("Recipients") {
699 assert_eq!(recipient_array.len(), 2);
700 } else {
701 panic!("Recipients not found in dictionary");
702 }
703 }
704
705 #[test]
706 fn test_filter_not_found_error() {
707 let handler = StandardSecurityHandler::rc4_128bit();
708 let manager =
709 CryptFilterManager::new(Box::new(handler), "StdCF".to_string(), "StdCF".to_string());
710
711 let obj_id = ObjectId::new(1, 0);
712 let key = EncryptionKey::new(vec![0u8; 16]);
713
714 let result = manager.encrypt_string(b"test", &obj_id, Some("NonExistentFilter"), &key);
716
717 assert!(result.is_err());
718 if let Err(PdfError::EncryptionError(msg)) = result {
719 assert!(msg.contains("not found"));
720 }
721 }
722}