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 '{}' not found", filter_name))
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 '{}' not found", filter_name))
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 '{}' not found", filter_name))
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 '{}' not found", filter_name))
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",
439 bits
440 ))),
441 }
442 }
443
444 fn decrypt_string_aes(
445 &self,
446 data: &[u8],
447 key: &EncryptionKey,
448 obj_id: &ObjectId,
449 bits: u32,
450 ) -> Result<Vec<u8>> {
451 match bits {
452 128 | 256 => {
453 self.decrypt_aes(data, key, obj_id)
455 }
456 _ => Err(PdfError::EncryptionError(format!(
457 "Unsupported AES key size: {} bits",
458 bits
459 ))),
460 }
461 }
462
463 fn encrypt_stream_aes(
464 &self,
465 data: &[u8],
466 key: &EncryptionKey,
467 obj_id: &ObjectId,
468 bits: u32,
469 ) -> Result<Vec<u8>> {
470 self.encrypt_string_aes(data, key, obj_id, bits)
471 }
472
473 fn decrypt_stream_aes(
474 &self,
475 data: &[u8],
476 key: &EncryptionKey,
477 obj_id: &ObjectId,
478 bits: u32,
479 ) -> Result<Vec<u8>> {
480 self.decrypt_string_aes(data, key, obj_id, bits)
481 }
482}
483
484#[cfg(test)]
485mod tests {
486 use super::*;
487
488 #[test]
489 fn test_auth_event_pdf_names() {
490 assert_eq!(AuthEvent::DocOpen.pdf_name(), "DocOpen");
491 assert_eq!(AuthEvent::EFOpen.pdf_name(), "EFOpen");
492 }
493
494 #[test]
495 fn test_functional_crypt_filter_creation() {
496 let filter = FunctionalCryptFilter {
497 name: "TestFilter".to_string(),
498 method: CryptFilterMethod::AESV2,
499 length: Some(16),
500 auth_event: AuthEvent::DocOpen,
501 recipients: None,
502 };
503
504 assert_eq!(filter.name, "TestFilter");
505 assert_eq!(filter.method, CryptFilterMethod::AESV2);
506 assert_eq!(filter.length, Some(16));
507 assert_eq!(filter.auth_event, AuthEvent::DocOpen);
508 }
509
510 #[test]
511 fn test_crypt_filter_to_dict() {
512 let filter = FunctionalCryptFilter {
513 name: "MyFilter".to_string(),
514 method: CryptFilterMethod::V2,
515 length: Some(16),
516 auth_event: AuthEvent::EFOpen,
517 recipients: Some(vec!["recipient1".to_string(), "recipient2".to_string()]),
518 };
519
520 let dict = filter.to_dict();
521 assert_eq!(dict.get("CFM"), Some(&Object::Name("V2".to_string())));
522 assert_eq!(dict.get("Length"), Some(&Object::Integer(16)));
523 assert_eq!(
524 dict.get("AuthEvent"),
525 Some(&Object::Name("EFOpen".to_string()))
526 );
527 assert!(dict.get("Recipients").is_some());
528 }
529
530 #[test]
531 fn test_crypt_filter_manager_creation() {
532 let handler = StandardSecurityHandler::rc4_128bit();
533 let manager =
534 CryptFilterManager::new(Box::new(handler), "StdCF".to_string(), "StdCF".to_string());
535
536 assert!(manager.get_filter("Identity").is_some());
538 }
539
540 #[test]
541 fn test_add_and_get_filter() {
542 let handler = StandardSecurityHandler::rc4_128bit();
543 let mut manager =
544 CryptFilterManager::new(Box::new(handler), "StdCF".to_string(), "StdCF".to_string());
545
546 let filter = FunctionalCryptFilter {
547 name: "CustomFilter".to_string(),
548 method: CryptFilterMethod::AESV3,
549 length: None,
550 auth_event: AuthEvent::DocOpen,
551 recipients: None,
552 };
553
554 manager.add_filter(filter.clone());
555
556 let retrieved = manager.get_filter("CustomFilter");
557 assert!(retrieved.is_some());
558 assert_eq!(retrieved.unwrap().method, CryptFilterMethod::AESV3);
559 }
560
561 #[test]
562 fn test_standard_filter_creation() {
563 let filter = CryptFilterManager::create_standard_filter(CryptFilterMethod::AESV2, Some(16));
564
565 assert_eq!(filter.name, "StdCF");
566 assert_eq!(filter.method, CryptFilterMethod::AESV2);
567 assert_eq!(filter.length, Some(16));
568 assert_eq!(filter.auth_event, AuthEvent::DocOpen);
569 }
570
571 #[test]
572 fn test_encrypt_decrypt_string_identity() {
573 let handler = StandardSecurityHandler::rc4_128bit();
574 let manager = CryptFilterManager::new(
575 Box::new(handler),
576 "Identity".to_string(),
577 "Identity".to_string(),
578 );
579
580 let data = b"Test data";
581 let obj_id = ObjectId::new(1, 0);
582 let key = EncryptionKey::new(vec![0u8; 16]);
583
584 let encrypted = manager.encrypt_string(data, &obj_id, None, &key).unwrap();
585 assert_eq!(encrypted, data);
586
587 let decrypted = manager
588 .decrypt_string(&encrypted, &obj_id, None, &key)
589 .unwrap();
590 assert_eq!(decrypted, data);
591 }
592
593 #[test]
594 fn test_set_embedded_files_filter() {
595 let handler = StandardSecurityHandler::rc4_128bit();
596 let mut manager =
597 CryptFilterManager::new(Box::new(handler), "StdCF".to_string(), "StdCF".to_string());
598
599 manager.set_embedded_files_filter("EFFFilter".to_string());
600 assert_eq!(manager.embedded_files_filter, Some("EFFFilter".to_string()));
601 }
602
603 #[test]
604 fn test_to_cf_dict() {
605 let handler = StandardSecurityHandler::rc4_128bit();
606 let mut manager =
607 CryptFilterManager::new(Box::new(handler), "StdCF".to_string(), "StdCF".to_string());
608
609 let filter1 = FunctionalCryptFilter {
610 name: "Filter1".to_string(),
611 method: CryptFilterMethod::V2,
612 length: Some(16),
613 auth_event: AuthEvent::DocOpen,
614 recipients: None,
615 };
616
617 let filter2 = FunctionalCryptFilter {
618 name: "Filter2".to_string(),
619 method: CryptFilterMethod::AESV2,
620 length: None,
621 auth_event: AuthEvent::EFOpen,
622 recipients: None,
623 };
624
625 manager.add_filter(filter1);
626 manager.add_filter(filter2);
627
628 let cf_dict = manager.to_cf_dict();
629
630 assert!(cf_dict.get("Identity").is_none());
632
633 assert!(cf_dict.get("Filter1").is_some());
635 assert!(cf_dict.get("Filter2").is_some());
636 }
637
638 #[test]
639 fn test_get_stream_filter_name_default() {
640 let handler = StandardSecurityHandler::rc4_128bit();
641 let manager = CryptFilterManager::new(
642 Box::new(handler),
643 "DefaultStreamFilter".to_string(),
644 "StdCF".to_string(),
645 );
646
647 let stream_dict = Dictionary::new();
648 let filter_name = manager.get_stream_filter_name(&stream_dict);
649 assert_eq!(filter_name, "DefaultStreamFilter");
650 }
651
652 #[test]
653 fn test_get_stream_filter_name_with_crypt() {
654 let handler = StandardSecurityHandler::rc4_128bit();
655 let manager = CryptFilterManager::new(
656 Box::new(handler),
657 "DefaultStreamFilter".to_string(),
658 "StdCF".to_string(),
659 );
660
661 let mut stream_dict = Dictionary::new();
662 let filters = vec![
663 Object::Name("FlateDecode".to_string()),
664 Object::Name("Crypt".to_string()),
665 ];
666 stream_dict.set("Filter", Object::Array(filters));
667
668 let mut decode_parms = Dictionary::new();
669 decode_parms.set("Name", Object::Name("SpecialFilter".to_string()));
670 stream_dict.set("DecodeParms", Object::Dictionary(decode_parms));
671
672 let filter_name = manager.get_stream_filter_name(&stream_dict);
673 assert_eq!(filter_name, "SpecialFilter");
674 }
675
676 #[test]
677 fn test_auth_event_equality() {
678 assert_eq!(AuthEvent::DocOpen, AuthEvent::DocOpen);
679 assert_eq!(AuthEvent::EFOpen, AuthEvent::EFOpen);
680 assert_ne!(AuthEvent::DocOpen, AuthEvent::EFOpen);
681 }
682
683 #[test]
684 fn test_crypt_filter_with_recipients() {
685 let recipients = vec![
686 "user1@example.com".to_string(),
687 "user2@example.com".to_string(),
688 ];
689
690 let filter = FunctionalCryptFilter {
691 name: "PublicKeyFilter".to_string(),
692 method: CryptFilterMethod::AESV3,
693 length: None,
694 auth_event: AuthEvent::DocOpen,
695 recipients: Some(recipients.clone()),
696 };
697
698 let dict = filter.to_dict();
699
700 if let Some(Object::Array(recipient_array)) = dict.get("Recipients") {
701 assert_eq!(recipient_array.len(), 2);
702 } else {
703 panic!("Recipients not found in dictionary");
704 }
705 }
706
707 #[test]
708 fn test_filter_not_found_error() {
709 let handler = StandardSecurityHandler::rc4_128bit();
710 let manager =
711 CryptFilterManager::new(Box::new(handler), "StdCF".to_string(), "StdCF".to_string());
712
713 let obj_id = ObjectId::new(1, 0);
714 let key = EncryptionKey::new(vec![0u8; 16]);
715
716 let result = manager.encrypt_string(b"test", &obj_id, Some("NonExistentFilter"), &key);
718
719 assert!(result.is_err());
720 if let Err(PdfError::EncryptionError(msg)) = result {
721 assert!(msg.contains("not found"));
722 }
723 }
724}