1mod algorithms;
2pub mod crypt_filters;
3mod pkcs5;
4mod rc4;
5
6use crate::{Dictionary, Document, Error, Object, ObjectId};
7use bitflags::bitflags;
8use crypt_filters::*;
9use std::collections::BTreeMap;
10use std::sync::Arc;
11use thiserror::Error;
12
13pub use algorithms::PasswordAlgorithm;
14
15#[derive(Error, Debug)]
16pub enum DecryptionError {
17 #[error("the /Encrypt dictionary is missing")]
18 MissingEncryptDictionary,
19 #[error("missing encryption version")]
20 MissingVersion,
21 #[error("missing encryption revision")]
22 MissingRevision,
23 #[error("missing the owner password (/O)")]
24 MissingOwnerPassword,
25 #[error("missing the user password (/U)")]
26 MissingUserPassword,
27 #[error("missing the permissions field (/P)")]
28 MissingPermissions,
29 #[error("missing the file /ID elements")]
30 MissingFileID,
31
32 #[error("invalid hash length")]
33 InvalidHashLength,
34 #[error("invalid key length")]
35 InvalidKeyLength,
36 #[error("invalid ciphertext length")]
37 InvalidCipherTextLength,
38 #[error("invalid permission length")]
39 InvalidPermissionLength,
40 #[error("invalid version")]
41 InvalidVersion,
42 #[error("invalid revision")]
43 InvalidRevision,
44 #[error("unexpected type; document does not comply with the spec")]
46 InvalidType,
47
48 #[error("the object is not capable of being decrypted")]
49 NotDecryptable,
50 #[error("the supplied password is incorrect")]
51 IncorrectPassword,
52
53 #[error("the document uses an encryption scheme that is not implemented in lopdf")]
54 UnsupportedEncryption,
55 #[error("the encryption version is not implemented in lopdf")]
56 UnsupportedVersion,
57 #[error("the encryption revision is not implemented in lopdf")]
58 UnsupportedRevision,
59
60 #[error(transparent)]
61 StringPrep(#[from] stringprep::Error),
62 #[error("invalid padding encountered when decrypting, key might be incorrect")]
63 Padding,
64}
65
66bitflags! {
67 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
68 pub struct Permissions: u64 {
69 const PRINTABLE = 1 << 2;
74
75 const MODIFIABLE = 1 << 3;
78
79 const COPYABLE = 1 << 4;
83
84 const ANNOTABLE = 1 << 5;
88
89 const FILLABLE = 1 << 8;
92
93 const COPYABLE_FOR_ACCESSIBILITY = 1 << 9;
99
100 const ASSEMBLABLE = 1 << 10;
104
105 const PRINTABLE_IN_HIGH_QUALITY = 1 << 11;
111 }
112}
113
114impl Default for Permissions {
115 fn default() -> Self {
116 Self::all()
117 }
118}
119
120impl Permissions {
121 fn correct_bits(self) -> Self {
122 let mut bits = self.bits();
123
124 bits |= 0b11 << 6;
126
127 bits |= 0b1111 << 12 | 0xffff << 16;
129
130 bits |= 0xffffffff << 32;
133
134 Permissions::from_bits_retain(bits)
135 }
136}
137
138#[derive(Clone, Debug)]
139pub enum EncryptionVersion<'a> {
140 V1 {
143 document: &'a Document,
144 owner_password: &'a str,
145 user_password: &'a str,
146 permissions: Permissions,
147 },
148 V2 {
151 document: &'a Document,
152 owner_password: &'a str,
153 user_password: &'a str,
154 key_length: usize,
155 permissions: Permissions,
156 },
157 V4 {
162 document: &'a Document,
163 encrypt_metadata: bool,
164 crypt_filters: BTreeMap<Vec<u8>, Arc<dyn CryptFilter>>,
165 stream_filter: Vec<u8>,
166 string_filter: Vec<u8>,
167 owner_password: &'a str,
168 user_password: &'a str,
169 permissions: Permissions,
170 },
171 #[deprecated(
176 note = "R5 is a proprietary Adobe extension and should not be used in newly produced documents other than for testing purposes."
177 )]
178 R5 {
179 encrypt_metadata: bool,
180 crypt_filters: BTreeMap<Vec<u8>, Arc<dyn CryptFilter>>,
181 file_encryption_key: &'a [u8],
182 stream_filter: Vec<u8>,
183 string_filter: Vec<u8>,
184 owner_password: &'a str,
185 user_password: &'a str,
186 permissions: Permissions,
187 },
188 V5 {
192 encrypt_metadata: bool,
193 crypt_filters: BTreeMap<Vec<u8>, Arc<dyn CryptFilter>>,
194 file_encryption_key: &'a [u8],
195 stream_filter: Vec<u8>,
196 string_filter: Vec<u8>,
197 owner_password: &'a str,
198 user_password: &'a str,
199 permissions: Permissions,
200 },
201}
202
203#[derive(Clone, Debug, Default)]
204pub struct EncryptionState {
205 pub(crate) version: i64,
206 pub(crate) revision: i64,
207 pub(crate) key_length: Option<usize>,
208 pub(crate) encrypt_metadata: bool,
209 pub(crate) crypt_filters: BTreeMap<Vec<u8>, Arc<dyn CryptFilter>>,
210 pub(crate) file_encryption_key: Vec<u8>,
211 pub(crate) stream_filter: Vec<u8>,
212 pub(crate) string_filter: Vec<u8>,
213 pub(crate) owner_value: Vec<u8>,
214 pub(crate) owner_encrypted: Vec<u8>,
215 pub(crate) user_value: Vec<u8>,
216 pub(crate) user_encrypted: Vec<u8>,
217 pub(crate) permissions: Permissions,
218 pub(crate) permission_encrypted: Vec<u8>,
219}
220
221impl TryFrom<EncryptionVersion<'_>> for EncryptionState {
222 type Error = Error;
223
224 fn try_from(version: EncryptionVersion) -> Result<EncryptionState, Self::Error> {
225 match version {
226 EncryptionVersion::V1 {
227 document,
228 owner_password,
229 user_password,
230 permissions,
231 } => {
232 let permissions = permissions.correct_bits();
233
234 let mut algorithm = PasswordAlgorithm {
235 encrypt_metadata: true,
236 length: None,
237 version: 1,
238 revision: 2,
239 permissions,
240 ..Default::default()
241 };
242
243 let owner_password = algorithm.sanitize_password_r4(owner_password)?;
244 let user_password = algorithm.sanitize_password_r4(user_password)?;
245
246 algorithm.owner_value = algorithm
247 .compute_hashed_owner_password_r4(Some(&owner_password), &user_password)?;
248
249 algorithm.user_value =
250 algorithm.compute_hashed_user_password_r2(document, &user_password)?;
251
252 let file_encryption_key =
253 algorithm.compute_file_encryption_key_r4(document, &user_password)?;
254
255 Ok(Self {
256 version: algorithm.version,
257 revision: algorithm.revision,
258 key_length: algorithm.length,
259 encrypt_metadata: algorithm.encrypt_metadata,
260 file_encryption_key,
261 owner_value: algorithm.owner_value,
262 user_value: algorithm.user_value,
263 permissions: algorithm.permissions,
264 ..Default::default()
265 })
266 }
267 EncryptionVersion::V2 {
268 document,
269 owner_password,
270 user_password,
271 key_length,
272 permissions,
273 } => {
274 let permissions = permissions.correct_bits();
275
276 let mut algorithm = PasswordAlgorithm {
277 encrypt_metadata: true,
278 length: Some(key_length),
279 version: 2,
280 revision: 3,
281 permissions,
282 ..Default::default()
283 };
284
285 let owner_password = algorithm.sanitize_password_r4(owner_password)?;
286 let user_password = algorithm.sanitize_password_r4(user_password)?;
287
288 algorithm.owner_value = algorithm
289 .compute_hashed_owner_password_r4(Some(&owner_password), &user_password)?;
290
291 algorithm.user_value =
292 algorithm.compute_hashed_user_password_r3_r4(document, &user_password)?;
293
294 let file_encryption_key =
295 algorithm.compute_file_encryption_key_r4(document, &user_password)?;
296
297 Ok(Self {
298 version: algorithm.version,
299 revision: algorithm.revision,
300 key_length: algorithm.length,
301 encrypt_metadata: algorithm.encrypt_metadata,
302 file_encryption_key,
303 owner_value: algorithm.owner_value,
304 user_value: algorithm.user_value,
305 permissions,
306 ..Default::default()
307 })
308 }
309 EncryptionVersion::V4 {
310 document,
311 encrypt_metadata,
312 crypt_filters,
313 stream_filter,
314 string_filter,
315 owner_password,
316 user_password,
317 permissions,
318 } => {
319 let permissions = permissions.correct_bits();
320
321 let mut algorithm = PasswordAlgorithm {
322 encrypt_metadata,
323 length: Some(128),
324 version: 4,
325 revision: 4,
326 permissions,
327 ..Default::default()
328 };
329
330 let owner_password = algorithm.sanitize_password_r4(owner_password)?;
331 let user_password = algorithm.sanitize_password_r4(user_password)?;
332
333 algorithm.owner_value = algorithm
334 .compute_hashed_owner_password_r4(Some(&owner_password), &user_password)?;
335
336 algorithm.user_value =
337 algorithm.compute_hashed_user_password_r3_r4(document, &user_password)?;
338
339 let file_encryption_key =
340 algorithm.compute_file_encryption_key_r4(document, &user_password)?;
341
342 Ok(Self {
343 version: algorithm.version,
344 revision: algorithm.revision,
345 key_length: algorithm.length,
346 encrypt_metadata: algorithm.encrypt_metadata,
347 file_encryption_key,
348 crypt_filters,
349 stream_filter,
350 string_filter,
351 owner_value: algorithm.owner_value,
352 user_value: algorithm.user_value,
353 permissions: algorithm.permissions,
354 ..Default::default()
355 })
356 }
357 #[allow(deprecated)]
358 EncryptionVersion::R5 {
359 encrypt_metadata,
360 crypt_filters,
361 file_encryption_key,
362 stream_filter,
363 string_filter,
364 owner_password,
365 user_password,
366 permissions,
367 } => {
368 if file_encryption_key.len() != 32 {
369 return Err(DecryptionError::InvalidKeyLength)?;
370 }
371
372 let permissions = permissions.correct_bits();
373
374 let mut algorithm = PasswordAlgorithm {
375 encrypt_metadata,
376 version: 5,
377 revision: 5,
378 permissions,
379 ..Default::default()
380 };
381
382 let owner_password = algorithm.sanitize_password_r6(owner_password)?;
383 let user_password = algorithm.sanitize_password_r6(user_password)?;
384
385 let (user_value, user_encrypted) = algorithm
386 .compute_hashed_user_password_r6(file_encryption_key, user_password)?;
387
388 algorithm.user_value = user_value;
389 algorithm.user_encrypted = user_encrypted;
390
391 let (owner_value, owner_encrypted) = algorithm
392 .compute_hashed_owner_password_r6(file_encryption_key, owner_password)?;
393
394 algorithm.owner_value = owner_value;
395 algorithm.owner_encrypted = owner_encrypted;
396
397 algorithm.permission_encrypted =
398 algorithm.compute_permissions(file_encryption_key)?;
399
400 Ok(Self {
401 version: algorithm.version,
402 revision: algorithm.revision,
403 key_length: algorithm.length,
404 encrypt_metadata: algorithm.encrypt_metadata,
405 crypt_filters,
406 file_encryption_key: file_encryption_key.to_vec(),
407 stream_filter,
408 string_filter,
409 owner_value: algorithm.owner_value,
410 owner_encrypted: algorithm.owner_encrypted,
411 user_value: algorithm.user_value,
412 user_encrypted: algorithm.user_encrypted,
413 permissions: algorithm.permissions,
414 permission_encrypted: algorithm.permission_encrypted,
415 })
416 }
417 EncryptionVersion::V5 {
418 encrypt_metadata,
419 crypt_filters,
420 file_encryption_key,
421 stream_filter,
422 string_filter,
423 owner_password,
424 user_password,
425 permissions,
426 } => {
427 if file_encryption_key.len() != 32 {
428 return Err(DecryptionError::InvalidKeyLength)?;
429 }
430
431 let permissions = permissions.correct_bits();
432
433 let mut algorithm = PasswordAlgorithm {
434 encrypt_metadata,
435 version: 5,
436 revision: 6,
437 permissions,
438 ..Default::default()
439 };
440
441 let owner_password = algorithm.sanitize_password_r6(owner_password)?;
442 let user_password = algorithm.sanitize_password_r6(user_password)?;
443
444 let (user_value, user_encrypted) = algorithm
445 .compute_hashed_user_password_r6(file_encryption_key, user_password)?;
446
447 algorithm.user_value = user_value;
448 algorithm.user_encrypted = user_encrypted;
449
450 let (owner_value, owner_encrypted) = algorithm
451 .compute_hashed_owner_password_r6(file_encryption_key, owner_password)?;
452
453 algorithm.owner_value = owner_value;
454 algorithm.owner_encrypted = owner_encrypted;
455
456 algorithm.permission_encrypted =
457 algorithm.compute_permissions(file_encryption_key)?;
458
459 Ok(Self {
460 version: algorithm.version,
461 revision: algorithm.revision,
462 key_length: algorithm.length,
463 encrypt_metadata: algorithm.encrypt_metadata,
464 crypt_filters,
465 file_encryption_key: file_encryption_key.to_vec(),
466 stream_filter,
467 string_filter,
468 owner_value: algorithm.owner_value,
469 owner_encrypted: algorithm.owner_encrypted,
470 user_value: algorithm.user_value,
471 user_encrypted: algorithm.user_encrypted,
472 permissions: algorithm.permissions,
473 permission_encrypted: algorithm.permission_encrypted,
474 })
475 }
476 }
477 }
478}
479
480impl EncryptionState {
481 pub fn version(&self) -> i64 {
482 self.version
483 }
484
485 pub fn revision(&self) -> i64 {
486 self.revision
487 }
488
489 pub fn key_length(&self) -> Option<usize> {
490 self.key_length
491 }
492
493 pub fn encrypt_metadata(&self) -> bool {
494 self.encrypt_metadata
495 }
496
497 pub fn crypt_filters(&self) -> &BTreeMap<Vec<u8>, Arc<dyn CryptFilter>> {
498 &self.crypt_filters
499 }
500
501 pub fn file_encryption_key(&self) -> &[u8] {
502 self.file_encryption_key.as_ref()
503 }
504
505 pub fn default_stream_filter(&self) -> &[u8] {
506 self.stream_filter.as_ref()
507 }
508
509 pub fn default_string_filter(&self) -> &[u8] {
510 self.string_filter.as_ref()
511 }
512
513 pub fn owner_value(&self) -> &[u8] {
514 self.owner_value.as_ref()
515 }
516
517 pub fn owner_encrypted(&self) -> &[u8] {
518 self.owner_encrypted.as_ref()
519 }
520
521 pub fn user_value(&self) -> &[u8] {
522 self.user_value.as_ref()
523 }
524
525 pub fn user_encrypted(&self) -> &[u8] {
526 self.user_encrypted.as_ref()
527 }
528
529 pub fn permissions(&self) -> Permissions {
530 self.permissions
531 }
532
533 pub fn permission_encrypted(&self) -> &[u8] {
534 self.permission_encrypted.as_ref()
535 }
536
537 pub fn decode<P>(document: &Document, password: P) -> Result<Self, Error>
538 where
539 P: AsRef<[u8]>,
540 {
541 if !document.is_encrypted() {
542 return Err(Error::NotEncrypted);
543 }
544
545 let filter = document
550 .get_encrypted()
551 .and_then(|dict| dict.get(b"Filter"))
552 .and_then(|object| object.as_name())
553 .map_err(|_| Error::DictKey("Filter".to_string()))?;
554
555 if filter != b"Standard" {
556 return Err(Error::UnsupportedSecurityHandler(filter.to_vec()));
557 }
558
559 let algorithm = PasswordAlgorithm::try_from(document)?;
560 let file_encryption_key = algorithm.compute_file_encryption_key(document, password)?;
561
562 let mut crypt_filters = document.get_crypt_filters();
563
564 if algorithm.version < 4 {
566 crypt_filters.clear();
567 }
568
569 let mut state = Self {
570 version: algorithm.version,
571 revision: algorithm.revision,
572 key_length: algorithm.length,
573 encrypt_metadata: algorithm.encrypt_metadata,
574 crypt_filters,
575 file_encryption_key,
576 owner_value: algorithm.owner_value,
577 owner_encrypted: algorithm.owner_encrypted,
578 user_value: algorithm.user_value,
579 user_encrypted: algorithm.user_encrypted,
580 permissions: algorithm.permissions,
581 permission_encrypted: algorithm.permission_encrypted,
582 ..Default::default()
583 };
584
585 if algorithm.version == 4 || algorithm.version == 5 {
587 if let Ok(stream_filter) = document
588 .get_encrypted()
589 .and_then(|dict| dict.get(b"StmF"))
590 .and_then(|object| object.as_name())
591 {
592 state.stream_filter = stream_filter.to_vec();
593 }
594
595 if let Ok(string_filter) = document
596 .get_encrypted()
597 .and_then(|dict| dict.get(b"StrF"))
598 .and_then(|object| object.as_name())
599 {
600 state.string_filter = string_filter.to_vec();
601 }
602 }
603
604 Ok(state)
605 }
606
607 pub fn encode(&self) -> Result<Dictionary, DecryptionError> {
608 let mut encrypted = Dictionary::new();
609
610 encrypted.set(b"Filter", Object::Name(b"Standard".to_vec()));
611
612 encrypted.set(b"V", Object::Integer(self.version));
613 encrypted.set(b"R", Object::Integer(self.revision));
614
615 if let Some(key_length) = self.key_length {
616 encrypted.set(b"Length", Object::Integer(key_length as i64));
617 }
618
619 if self.version >= 4 {
622 encrypted.set(b"EncryptMetadata", Object::Boolean(self.encrypt_metadata));
623 }
624
625 encrypted.set(b"O", Object::string_literal(self.owner_value.clone()));
626 encrypted.set(b"U", Object::string_literal(self.user_value.clone()));
627 encrypted.set(b"P", Object::Integer(self.permissions.bits() as i64));
628
629 if self.revision >= 4 {
630 let mut filters = Dictionary::new();
631
632 for (name, crypt_filter) in &self.crypt_filters {
633 let mut filter = Dictionary::new();
634
635 filter.set(b"Type", Object::Name(b"CryptFilter".to_vec()));
636 filter.set(b"CFM", Object::Name(crypt_filter.method().to_vec()));
637
638 filters.set(name.to_vec(), Object::Dictionary(filter));
639 }
640
641 encrypted.set(b"CF", Object::Dictionary(filters));
642 encrypted.set(b"StmF", Object::Name(self.stream_filter.clone()));
643 encrypted.set(b"StrF", Object::Name(self.string_filter.clone()));
644 }
645
646 if self.revision >= 5 {
647 encrypted.set(b"OE", Object::string_literal(self.owner_encrypted.clone()));
648 encrypted.set(b"UE", Object::string_literal(self.user_encrypted.clone()));
649 encrypted.set(
650 b"Perms",
651 Object::string_literal(self.permission_encrypted.clone()),
652 );
653 }
654
655 Ok(encrypted)
656 }
657
658 pub fn get_stream_filter(&self) -> Arc<dyn CryptFilter> {
659 self.crypt_filters
660 .get(&self.stream_filter)
661 .cloned()
662 .unwrap_or(Arc::new(Rc4CryptFilter))
663 }
664
665 pub fn get_string_filter(&self) -> Arc<dyn CryptFilter> {
666 self.crypt_filters
667 .get(&self.string_filter)
668 .cloned()
669 .unwrap_or(Arc::new(Rc4CryptFilter))
670 }
671}
672
673pub fn aes256_encryption_state(
678 owner_password: &str,
679 user_password: &str,
680 permissions: Permissions,
681) -> crate::Result<EncryptionState> {
682 use rand::Rng as _;
683 let mut file_key = [0u8; 32];
684 rand::rng().fill(&mut file_key);
685 let crypt_filter: Arc<dyn CryptFilter> = Arc::new(Aes256CryptFilter);
686 EncryptionState::try_from(EncryptionVersion::V5 {
687 encrypt_metadata: true,
688 crypt_filters: BTreeMap::from([(b"StdCF".to_vec(), crypt_filter)]),
689 file_encryption_key: &file_key,
690 stream_filter: b"StdCF".to_vec(),
691 string_filter: b"StdCF".to_vec(),
692 owner_password,
693 user_password,
694 permissions,
695 })
696}
697
698pub fn encrypt_object(
700 state: &EncryptionState,
701 obj_id: ObjectId,
702 obj: &mut Object,
703) -> Result<(), DecryptionError> {
704 let is_xref_stream = obj
707 .as_stream()
708 .map(|stream| stream.dict.has_type(b"XRef"))
709 .unwrap_or(false);
710
711 if is_xref_stream {
712 return Ok(());
713 }
714
715 if obj.type_name().ok() == Some(b"Metadata") && !state.encrypt_metadata {
717 return Ok(());
718 }
719
720 let override_crypt_filter = obj
725 .as_stream()
726 .ok()
727 .filter(|stream| {
728 stream
729 .filters()
730 .map(|filters| filters.contains(&&b"Crypt"[..]))
731 .unwrap_or(false)
732 })
733 .and_then(|stream| stream.dict.get(b"DecodeParms").ok())
734 .and_then(|object| object.as_dict().ok())
735 .map(|dict| {
736 dict.get(b"Name")
737 .and_then(|object| object.as_name())
738 .ok()
739 .and_then(|name| state.crypt_filters.get(name).cloned())
740 .unwrap_or(Arc::new(IdentityCryptFilter))
741 });
742
743 let (mut crypt_filter, plaintext) = match obj {
746 Object::Array(objects) => {
750 for obj in objects {
751 encrypt_object(state, obj_id, obj)?;
752 }
753
754 return Ok(());
755 }
756 Object::Dictionary(objects) => {
757 for (_, obj) in objects.iter_mut() {
758 encrypt_object(state, obj_id, obj)?;
759 }
760
761 return Ok(());
762 }
763 Object::String(content, _) => (state.get_string_filter(), &*content),
766 Object::Stream(stream) => (state.get_stream_filter(), &stream.content),
767 _ => {
769 return Ok(());
770 }
771 };
772
773 if let Some(filter) = override_crypt_filter {
776 crypt_filter = filter;
777 }
778
779 let key = crypt_filter.compute_key(&state.file_encryption_key, obj_id)?;
782
783 let ciphertext = crypt_filter.encrypt(&key, plaintext)?;
785
786 match obj {
788 Object::Stream(stream) => stream.set_content(ciphertext),
789 Object::String(content, _) => *content = ciphertext,
790 _ => (),
791 }
792
793 Ok(())
794}
795
796pub fn decrypt_object(
798 state: &EncryptionState,
799 obj_id: ObjectId,
800 obj: &mut Object,
801) -> Result<(), DecryptionError> {
802 let is_xref_stream = obj
805 .as_stream()
806 .map(|stream| stream.dict.has_type(b"XRef"))
807 .unwrap_or(false);
808
809 if is_xref_stream {
810 return Ok(());
811 }
812
813 if obj.type_name().ok() == Some(b"Metadata") && !state.encrypt_metadata {
815 return Ok(());
816 }
817
818 let override_crypt_filter = obj
823 .as_stream()
824 .ok()
825 .filter(|stream| {
826 stream
827 .filters()
828 .map(|filters| filters.contains(&&b"Crypt"[..]))
829 .unwrap_or(false)
830 })
831 .and_then(|stream| stream.dict.get(b"DecodeParms").ok())
832 .and_then(|object| object.as_dict().ok())
833 .map(|dict| {
834 dict.get(b"Name")
835 .and_then(|object| object.as_name())
836 .ok()
837 .and_then(|name| state.crypt_filters.get(name).cloned())
838 .unwrap_or(Arc::new(IdentityCryptFilter))
839 });
840
841 let (mut crypt_filter, ciphertext) = match obj {
844 Object::Array(objects) => {
848 for obj in objects {
849 decrypt_object(state, obj_id, obj)?;
850 }
851
852 return Ok(());
853 }
854 Object::Dictionary(objects) => {
855 for (_, obj) in objects.iter_mut() {
856 decrypt_object(state, obj_id, obj)?;
857 }
858
859 return Ok(());
860 }
861 Object::String(content, _) => (state.get_string_filter(), &*content),
864 Object::Stream(stream) => (state.get_stream_filter(), &stream.content),
865 _ => {
867 return Ok(());
868 }
869 };
870
871 if let Some(filter) = override_crypt_filter {
874 crypt_filter = filter;
875 }
876
877 let key = crypt_filter.compute_key(&state.file_encryption_key, obj_id)?;
880
881 let plaintext = crypt_filter.decrypt(&key, ciphertext)?;
883
884 match obj {
886 Object::Stream(stream) => stream.set_content(plaintext),
887 Object::String(content, _) => *content = plaintext,
888 _ => (),
889 }
890
891 Ok(())
892}
893
894#[cfg(test)]
895mod tests {
896 use super::rc4::Rc4;
897 use crate::creator::tests::create_document;
898 use crate::encryption::{Aes128CryptFilter, Aes256CryptFilter, CryptFilter};
899 use crate::{EncryptionState, EncryptionVersion, Permissions};
900 use rand::Rng as _;
901 use std::collections::BTreeMap;
902 use std::sync::Arc;
903
904 #[test]
905 fn rc4_works() {
906 let cases = [
907 (
909 String::from("Key"),
910 String::from("Plaintext"),
911 String::from("BBF316E8D940AF0AD3"),
912 ),
913 (
914 String::from("Wiki"),
915 String::from("pedia"),
916 String::from("1021BF0420"),
917 ),
918 ];
919
920 for (key, plain, cipher) in cases {
921 let cipher = cipher.as_bytes();
923 let mut cipher_bytes = Vec::with_capacity(cipher.len() / 2);
924 for hex_pair in cipher.chunks_exact(2) {
925 cipher_bytes
926 .push(u8::from_str_radix(std::str::from_utf8(hex_pair).unwrap(), 16).unwrap());
927 }
928
929 let decryptor = Rc4::new(key);
930 let decrypted = decryptor.decrypt(&cipher_bytes);
931 assert_eq!(plain.as_bytes(), &decrypted[..]);
932 }
933 }
934
935 #[test]
936 fn encrypt_v1() {
937 let mut document = create_document();
938
939 let version = EncryptionVersion::V1 {
940 document: &document,
941 owner_password: "owner",
942 user_password: "user",
943 permissions: Permissions::all(),
944 };
945
946 let state = EncryptionState::try_from(version).unwrap();
947
948 assert!(document.encrypt(&state).is_ok());
949 assert!(document.decrypt("user").is_ok());
950 }
951
952 #[test]
953 fn encrypt_v2() {
954 let mut document = create_document();
955
956 let version = EncryptionVersion::V2 {
957 document: &document,
958 owner_password: "owner",
959 user_password: "user",
960 key_length: 40,
961 permissions: Permissions::all(),
962 };
963
964 let state = EncryptionState::try_from(version).unwrap();
965
966 assert!(document.encrypt(&state).is_ok());
967 assert!(document.decrypt("user").is_ok());
968 }
969
970 #[test]
971 fn encrypt_v4() {
972 let mut document = create_document();
973
974 let crypt_filter: Arc<dyn CryptFilter> = Arc::new(Aes128CryptFilter);
975
976 let version = EncryptionVersion::V4 {
977 document: &document,
978 encrypt_metadata: true,
979 crypt_filters: BTreeMap::from([(b"StdCF".to_vec(), crypt_filter)]),
980 stream_filter: b"StdCF".to_vec(),
981 string_filter: b"StdCF".to_vec(),
982 owner_password: "owner",
983 user_password: "user",
984 permissions: Permissions::all(),
985 };
986
987 let state = EncryptionState::try_from(version).unwrap();
988
989 assert!(document.encrypt(&state).is_ok());
990 assert!(document.decrypt("user").is_ok());
991 }
992
993 #[test]
994 fn encrypt_r5() {
995 let mut document = create_document();
996
997 let crypt_filter: Arc<dyn CryptFilter> = Arc::new(Aes256CryptFilter);
998
999 let mut file_encryption_key = [0u8; 32];
1000
1001 let mut rng = rand::rng();
1002 rng.fill(&mut file_encryption_key);
1003
1004 #[allow(deprecated)]
1005 let version = EncryptionVersion::R5 {
1006 encrypt_metadata: true,
1007 crypt_filters: BTreeMap::from([(b"StdCF".to_vec(), crypt_filter)]),
1008 file_encryption_key: &file_encryption_key,
1009 stream_filter: b"StdCF".to_vec(),
1010 string_filter: b"StdCF".to_vec(),
1011 owner_password: "owner",
1012 user_password: "user",
1013 permissions: Permissions::all(),
1014 };
1015
1016 let state = EncryptionState::try_from(version).unwrap();
1017
1018 assert!(document.encrypt(&state).is_ok());
1019 assert!(document.decrypt("user").is_ok());
1020 }
1021
1022 #[test]
1023 fn encrypt_v5() {
1024 let mut document = create_document();
1025
1026 let crypt_filter: Arc<dyn CryptFilter> = Arc::new(Aes256CryptFilter);
1027
1028 let mut file_encryption_key = [0u8; 32];
1029
1030 let mut rng = rand::rng();
1031 rng.fill(&mut file_encryption_key);
1032
1033 let version = EncryptionVersion::V5 {
1034 encrypt_metadata: true,
1035 crypt_filters: BTreeMap::from([(b"StdCF".to_vec(), crypt_filter)]),
1036 file_encryption_key: &file_encryption_key,
1037 stream_filter: b"StdCF".to_vec(),
1038 string_filter: b"StdCF".to_vec(),
1039 owner_password: "owner",
1040 user_password: "user",
1041 permissions: Permissions::all(),
1042 };
1043
1044 let state = EncryptionState::try_from(version).unwrap();
1045
1046 assert!(document.encrypt(&state).is_ok());
1047 assert!(document.decrypt("user").is_ok());
1048 }
1049}