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 =
247 algorithm.compute_hashed_owner_password_r4(Some(&owner_password), &user_password)?;
248
249 algorithm.user_value = algorithm.compute_hashed_user_password_r2(document, &user_password)?;
250
251 let file_encryption_key = algorithm.compute_file_encryption_key_r4(document, &user_password)?;
252
253 Ok(Self {
254 version: algorithm.version,
255 revision: algorithm.revision,
256 key_length: algorithm.length,
257 encrypt_metadata: algorithm.encrypt_metadata,
258 file_encryption_key,
259 owner_value: algorithm.owner_value,
260 user_value: algorithm.user_value,
261 permissions: algorithm.permissions,
262 ..Default::default()
263 })
264 }
265 EncryptionVersion::V2 {
266 document,
267 owner_password,
268 user_password,
269 key_length,
270 permissions,
271 } => {
272 let permissions = permissions.correct_bits();
273
274 let mut algorithm = PasswordAlgorithm {
275 encrypt_metadata: true,
276 length: Some(key_length),
277 version: 2,
278 revision: 3,
279 permissions,
280 ..Default::default()
281 };
282
283 let owner_password = algorithm.sanitize_password_r4(owner_password)?;
284 let user_password = algorithm.sanitize_password_r4(user_password)?;
285
286 algorithm.owner_value =
287 algorithm.compute_hashed_owner_password_r4(Some(&owner_password), &user_password)?;
288
289 algorithm.user_value = algorithm.compute_hashed_user_password_r3_r4(document, &user_password)?;
290
291 let file_encryption_key = algorithm.compute_file_encryption_key_r4(document, &user_password)?;
292
293 Ok(Self {
294 version: algorithm.version,
295 revision: algorithm.revision,
296 key_length: algorithm.length,
297 encrypt_metadata: algorithm.encrypt_metadata,
298 file_encryption_key,
299 owner_value: algorithm.owner_value,
300 user_value: algorithm.user_value,
301 permissions,
302 ..Default::default()
303 })
304 }
305 EncryptionVersion::V4 {
306 document,
307 encrypt_metadata,
308 crypt_filters,
309 stream_filter,
310 string_filter,
311 owner_password,
312 user_password,
313 permissions,
314 } => {
315 let permissions = permissions.correct_bits();
316
317 let mut algorithm = PasswordAlgorithm {
318 encrypt_metadata,
319 length: Some(128),
320 version: 4,
321 revision: 4,
322 permissions,
323 ..Default::default()
324 };
325
326 let owner_password = algorithm.sanitize_password_r4(owner_password)?;
327 let user_password = algorithm.sanitize_password_r4(user_password)?;
328
329 algorithm.owner_value =
330 algorithm.compute_hashed_owner_password_r4(Some(&owner_password), &user_password)?;
331
332 algorithm.user_value = algorithm.compute_hashed_user_password_r3_r4(document, &user_password)?;
333
334 let file_encryption_key = algorithm.compute_file_encryption_key_r4(document, &user_password)?;
335
336 Ok(Self {
337 version: algorithm.version,
338 revision: algorithm.revision,
339 key_length: algorithm.length,
340 encrypt_metadata: algorithm.encrypt_metadata,
341 file_encryption_key,
342 crypt_filters,
343 stream_filter,
344 string_filter,
345 owner_value: algorithm.owner_value,
346 user_value: algorithm.user_value,
347 permissions: algorithm.permissions,
348 ..Default::default()
349 })
350 }
351 #[allow(deprecated)]
352 EncryptionVersion::R5 {
353 encrypt_metadata,
354 crypt_filters,
355 file_encryption_key,
356 stream_filter,
357 string_filter,
358 owner_password,
359 user_password,
360 permissions,
361 } => {
362 if file_encryption_key.len() != 32 {
363 return Err(DecryptionError::InvalidKeyLength)?;
364 }
365
366 let permissions = permissions.correct_bits();
367
368 let mut algorithm = PasswordAlgorithm {
369 encrypt_metadata,
370 version: 5,
371 revision: 5,
372 permissions,
373 ..Default::default()
374 };
375
376 let owner_password = algorithm.sanitize_password_r6(owner_password)?;
377 let user_password = algorithm.sanitize_password_r6(user_password)?;
378
379 let (user_value, user_encrypted) =
380 algorithm.compute_hashed_user_password_r6(file_encryption_key, user_password)?;
381
382 algorithm.user_value = user_value;
383 algorithm.user_encrypted = user_encrypted;
384
385 let (owner_value, owner_encrypted) =
386 algorithm.compute_hashed_owner_password_r6(file_encryption_key, owner_password)?;
387
388 algorithm.owner_value = owner_value;
389 algorithm.owner_encrypted = owner_encrypted;
390
391 algorithm.permission_encrypted = algorithm.compute_permissions(file_encryption_key)?;
392
393 Ok(Self {
394 version: algorithm.version,
395 revision: algorithm.revision,
396 key_length: algorithm.length,
397 encrypt_metadata: algorithm.encrypt_metadata,
398 crypt_filters,
399 file_encryption_key: file_encryption_key.to_vec(),
400 stream_filter,
401 string_filter,
402 owner_value: algorithm.owner_value,
403 owner_encrypted: algorithm.owner_encrypted,
404 user_value: algorithm.user_value,
405 user_encrypted: algorithm.user_encrypted,
406 permissions: algorithm.permissions,
407 permission_encrypted: algorithm.permission_encrypted,
408 })
409 }
410 EncryptionVersion::V5 {
411 encrypt_metadata,
412 crypt_filters,
413 file_encryption_key,
414 stream_filter,
415 string_filter,
416 owner_password,
417 user_password,
418 permissions,
419 } => {
420 if file_encryption_key.len() != 32 {
421 return Err(DecryptionError::InvalidKeyLength)?;
422 }
423
424 let permissions = permissions.correct_bits();
425
426 let mut algorithm = PasswordAlgorithm {
427 encrypt_metadata,
428 version: 5,
429 revision: 6,
430 permissions,
431 ..Default::default()
432 };
433
434 let owner_password = algorithm.sanitize_password_r6(owner_password)?;
435 let user_password = algorithm.sanitize_password_r6(user_password)?;
436
437 let (user_value, user_encrypted) =
438 algorithm.compute_hashed_user_password_r6(file_encryption_key, user_password)?;
439
440 algorithm.user_value = user_value;
441 algorithm.user_encrypted = user_encrypted;
442
443 let (owner_value, owner_encrypted) =
444 algorithm.compute_hashed_owner_password_r6(file_encryption_key, owner_password)?;
445
446 algorithm.owner_value = owner_value;
447 algorithm.owner_encrypted = owner_encrypted;
448
449 algorithm.permission_encrypted = algorithm.compute_permissions(file_encryption_key)?;
450
451 Ok(Self {
452 version: algorithm.version,
453 revision: algorithm.revision,
454 key_length: algorithm.length,
455 encrypt_metadata: algorithm.encrypt_metadata,
456 crypt_filters,
457 file_encryption_key: file_encryption_key.to_vec(),
458 stream_filter,
459 string_filter,
460 owner_value: algorithm.owner_value,
461 owner_encrypted: algorithm.owner_encrypted,
462 user_value: algorithm.user_value,
463 user_encrypted: algorithm.user_encrypted,
464 permissions: algorithm.permissions,
465 permission_encrypted: algorithm.permission_encrypted,
466 })
467 }
468 }
469 }
470}
471
472impl EncryptionState {
473 pub fn version(&self) -> i64 {
474 self.version
475 }
476
477 pub fn revision(&self) -> i64 {
478 self.revision
479 }
480
481 pub fn key_length(&self) -> Option<usize> {
482 self.key_length
483 }
484
485 pub fn encrypt_metadata(&self) -> bool {
486 self.encrypt_metadata
487 }
488
489 pub fn crypt_filters(&self) -> &BTreeMap<Vec<u8>, Arc<dyn CryptFilter>> {
490 &self.crypt_filters
491 }
492
493 pub fn file_encryption_key(&self) -> &[u8] {
494 self.file_encryption_key.as_ref()
495 }
496
497 pub fn default_stream_filter(&self) -> &[u8] {
498 self.stream_filter.as_ref()
499 }
500
501 pub fn default_string_filter(&self) -> &[u8] {
502 self.string_filter.as_ref()
503 }
504
505 pub fn owner_value(&self) -> &[u8] {
506 self.owner_value.as_ref()
507 }
508
509 pub fn owner_encrypted(&self) -> &[u8] {
510 self.owner_encrypted.as_ref()
511 }
512
513 pub fn user_value(&self) -> &[u8] {
514 self.user_value.as_ref()
515 }
516
517 pub fn user_encrypted(&self) -> &[u8] {
518 self.user_encrypted.as_ref()
519 }
520
521 pub fn permissions(&self) -> Permissions {
522 self.permissions
523 }
524
525 pub fn permission_encrypted(&self) -> &[u8] {
526 self.permission_encrypted.as_ref()
527 }
528
529 pub fn decode<P>(document: &Document, password: P) -> Result<Self, Error>
530 where
531 P: AsRef<[u8]>,
532 {
533 if !document.is_encrypted() {
534 return Err(Error::NotEncrypted);
535 }
536
537 let filter = document
542 .get_encrypted()
543 .and_then(|dict| dict.get(b"Filter"))
544 .and_then(|object| object.as_name())
545 .map_err(|_| Error::DictKey("Filter".to_string()))?;
546
547 if filter != b"Standard" {
548 return Err(Error::UnsupportedSecurityHandler(filter.to_vec()));
549 }
550
551 let algorithm = PasswordAlgorithm::try_from(document)?;
552 let file_encryption_key = algorithm.compute_file_encryption_key(document, password)?;
553
554 let mut crypt_filters = document.get_crypt_filters();
555
556 if algorithm.version < 4 {
558 crypt_filters.clear();
559 }
560
561 let mut state = Self {
562 version: algorithm.version,
563 revision: algorithm.revision,
564 key_length: algorithm.length,
565 encrypt_metadata: algorithm.encrypt_metadata,
566 crypt_filters,
567 file_encryption_key,
568 owner_value: algorithm.owner_value,
569 owner_encrypted: algorithm.owner_encrypted,
570 user_value: algorithm.user_value,
571 user_encrypted: algorithm.user_encrypted,
572 permissions: algorithm.permissions,
573 permission_encrypted: algorithm.permission_encrypted,
574 ..Default::default()
575 };
576
577 if algorithm.version == 4 || algorithm.version == 5 {
579 if let Ok(stream_filter) = document
580 .get_encrypted()
581 .and_then(|dict| dict.get(b"StmF"))
582 .and_then(|object| object.as_name())
583 {
584 state.stream_filter = stream_filter.to_vec();
585 }
586
587 if let Ok(string_filter) = document
588 .get_encrypted()
589 .and_then(|dict| dict.get(b"StrF"))
590 .and_then(|object| object.as_name())
591 {
592 state.string_filter = string_filter.to_vec();
593 }
594 }
595
596 Ok(state)
597 }
598
599 pub fn encode(&self) -> Result<Dictionary, DecryptionError> {
600 let mut encrypted = Dictionary::new();
601
602 encrypted.set(b"Filter", Object::Name(b"Standard".to_vec()));
603
604 encrypted.set(b"V", Object::Integer(self.version));
605 encrypted.set(b"R", Object::Integer(self.revision));
606
607 if let Some(key_length) = self.key_length {
608 encrypted.set(b"Length", Object::Integer(key_length as i64));
609 }
610
611 if self.version >= 4 {
614 encrypted.set(b"EncryptMetadata", Object::Boolean(self.encrypt_metadata));
615 }
616
617 encrypted.set(b"O", Object::string_literal(self.owner_value.clone()));
618 encrypted.set(b"U", Object::string_literal(self.user_value.clone()));
619 encrypted.set(b"P", Object::Integer(self.permissions.bits() as i64));
620
621 if self.revision >= 4 {
622 let mut filters = Dictionary::new();
623
624 for (name, crypt_filter) in &self.crypt_filters {
625 let mut filter = Dictionary::new();
626
627 filter.set(b"Type", Object::Name(b"CryptFilter".to_vec()));
628 filter.set(b"CFM", Object::Name(crypt_filter.method().to_vec()));
629
630 filters.set(name.to_vec(), Object::Dictionary(filter));
631 }
632
633 encrypted.set(b"CF", Object::Dictionary(filters));
634 encrypted.set(b"StmF", Object::Name(self.stream_filter.clone()));
635 encrypted.set(b"StrF", Object::Name(self.string_filter.clone()));
636 }
637
638 if self.revision >= 5 {
639 encrypted.set(b"OE", Object::string_literal(self.owner_encrypted.clone()));
640 encrypted.set(b"UE", Object::string_literal(self.user_encrypted.clone()));
641 encrypted.set(b"Perms", Object::string_literal(self.permission_encrypted.clone()));
642 }
643
644 Ok(encrypted)
645 }
646
647 pub fn get_stream_filter(&self) -> Arc<dyn CryptFilter> {
648 self.crypt_filters
649 .get(&self.stream_filter)
650 .cloned()
651 .unwrap_or(Arc::new(Rc4CryptFilter))
652 }
653
654 pub fn get_string_filter(&self) -> Arc<dyn CryptFilter> {
655 self.crypt_filters
656 .get(&self.string_filter)
657 .cloned()
658 .unwrap_or(Arc::new(Rc4CryptFilter))
659 }
660}
661
662pub fn encrypt_object(state: &EncryptionState, obj_id: ObjectId, obj: &mut Object) -> Result<(), DecryptionError> {
664 let is_xref_stream = obj
667 .as_stream()
668 .map(|stream| stream.dict.has_type(b"XRef"))
669 .unwrap_or(false);
670
671 if is_xref_stream {
672 return Ok(());
673 }
674
675 if obj.type_name().ok() == Some(b"Metadata") && !state.encrypt_metadata {
677 return Ok(());
678 }
679
680 let override_crypt_filter = obj
685 .as_stream()
686 .ok()
687 .filter(|stream| {
688 stream
689 .filters()
690 .map(|filters| filters.contains(&&b"Crypt"[..]))
691 .unwrap_or(false)
692 })
693 .and_then(|stream| stream.dict.get(b"DecodeParms").ok())
694 .and_then(|object| object.as_dict().ok())
695 .map(|dict| {
696 dict.get(b"Name")
697 .and_then(|object| object.as_name())
698 .ok()
699 .and_then(|name| state.crypt_filters.get(name).cloned())
700 .unwrap_or(Arc::new(IdentityCryptFilter))
701 });
702
703 let (mut crypt_filter, plaintext) = match obj {
706 Object::Array(objects) => {
710 for obj in objects {
711 encrypt_object(state, obj_id, obj)?;
712 }
713
714 return Ok(());
715 }
716 Object::Dictionary(objects) => {
717 for (_, obj) in objects.iter_mut() {
718 encrypt_object(state, obj_id, obj)?;
719 }
720
721 return Ok(());
722 }
723 Object::String(content, _) => (state.get_string_filter(), &*content),
726 Object::Stream(stream) => (state.get_stream_filter(), &stream.content),
727 _ => {
729 return Ok(());
730 }
731 };
732
733 if let Some(filter) = override_crypt_filter {
736 crypt_filter = filter;
737 }
738
739 let key = crypt_filter.compute_key(&state.file_encryption_key, obj_id)?;
742
743 let ciphertext = crypt_filter.encrypt(&key, plaintext)?;
745
746 match obj {
748 Object::Stream(stream) => stream.set_content(ciphertext),
749 Object::String(content, _) => *content = ciphertext,
750 _ => (),
751 }
752
753 Ok(())
754}
755
756pub fn decrypt_object(state: &EncryptionState, obj_id: ObjectId, obj: &mut Object) -> Result<(), DecryptionError> {
758 let is_xref_stream = obj
761 .as_stream()
762 .map(|stream| stream.dict.has_type(b"XRef"))
763 .unwrap_or(false);
764
765 if is_xref_stream {
766 return Ok(());
767 }
768
769 if obj.type_name().ok() == Some(b"Metadata") && !state.encrypt_metadata {
771 return Ok(());
772 }
773
774 let override_crypt_filter = obj
779 .as_stream()
780 .ok()
781 .filter(|stream| {
782 stream
783 .filters()
784 .map(|filters| filters.contains(&&b"Crypt"[..]))
785 .unwrap_or(false)
786 })
787 .and_then(|stream| stream.dict.get(b"DecodeParms").ok())
788 .and_then(|object| object.as_dict().ok())
789 .map(|dict| {
790 dict.get(b"Name")
791 .and_then(|object| object.as_name())
792 .ok()
793 .and_then(|name| state.crypt_filters.get(name).cloned())
794 .unwrap_or(Arc::new(IdentityCryptFilter))
795 });
796
797 let (mut crypt_filter, ciphertext) = match obj {
800 Object::Array(objects) => {
804 for obj in objects {
805 decrypt_object(state, obj_id, obj)?;
806 }
807
808 return Ok(());
809 }
810 Object::Dictionary(objects) => {
811 for (_, obj) in objects.iter_mut() {
812 decrypt_object(state, obj_id, obj)?;
813 }
814
815 return Ok(());
816 }
817 Object::String(content, _) => (state.get_string_filter(), &*content),
820 Object::Stream(stream) => (state.get_stream_filter(), &stream.content),
821 _ => {
823 return Ok(());
824 }
825 };
826
827 if let Some(filter) = override_crypt_filter {
830 crypt_filter = filter;
831 }
832
833 let key = crypt_filter.compute_key(&state.file_encryption_key, obj_id)?;
836
837 let plaintext = crypt_filter.decrypt(&key, ciphertext)?;
839
840 match obj {
842 Object::Stream(stream) => stream.set_content(plaintext),
843 Object::String(content, _) => *content = plaintext,
844 _ => (),
845 }
846
847 Ok(())
848}
849
850#[cfg(test)]
851mod tests {
852 use super::rc4::Rc4;
853 use crate::creator::tests::create_document;
854 use crate::encryption::{Aes128CryptFilter, Aes256CryptFilter, CryptFilter};
855 use crate::{EncryptionState, EncryptionVersion, Permissions};
856 use rand::Rng as _;
857 use std::collections::BTreeMap;
858 use std::sync::Arc;
859
860 #[test]
861 fn rc4_works() {
862 let cases = [
863 (
865 String::from("Key"),
866 String::from("Plaintext"),
867 String::from("BBF316E8D940AF0AD3"),
868 ),
869 (String::from("Wiki"), String::from("pedia"), String::from("1021BF0420")),
870 ];
871
872 for (key, plain, cipher) in cases {
873 let cipher = cipher.as_bytes();
875 let mut cipher_bytes = Vec::with_capacity(cipher.len() / 2);
876 for hex_pair in cipher.chunks_exact(2) {
877 cipher_bytes.push(u8::from_str_radix(std::str::from_utf8(hex_pair).unwrap(), 16).unwrap());
878 }
879
880 let decryptor = Rc4::new(key);
881 let decrypted = decryptor.decrypt(&cipher_bytes);
882 assert_eq!(plain.as_bytes(), &decrypted[..]);
883 }
884 }
885
886 #[test]
887 fn encrypt_v1() {
888 let mut document = create_document();
889
890 let version = EncryptionVersion::V1 {
891 document: &document,
892 owner_password: "owner",
893 user_password: "user",
894 permissions: Permissions::all(),
895 };
896
897 let state = EncryptionState::try_from(version).unwrap();
898
899 assert!(document.encrypt(&state).is_ok());
900 assert!(document.decrypt("user").is_ok());
901 }
902
903 #[test]
904 fn encrypt_v2() {
905 let mut document = create_document();
906
907 let version = EncryptionVersion::V2 {
908 document: &document,
909 owner_password: "owner",
910 user_password: "user",
911 key_length: 40,
912 permissions: Permissions::all(),
913 };
914
915 let state = EncryptionState::try_from(version).unwrap();
916
917 assert!(document.encrypt(&state).is_ok());
918 assert!(document.decrypt("user").is_ok());
919 }
920
921 #[test]
922 fn encrypt_v4() {
923 let mut document = create_document();
924
925 let crypt_filter: Arc<dyn CryptFilter> = Arc::new(Aes128CryptFilter);
926
927 let version = EncryptionVersion::V4 {
928 document: &document,
929 encrypt_metadata: true,
930 crypt_filters: BTreeMap::from([(b"StdCF".to_vec(), crypt_filter)]),
931 stream_filter: b"StdCF".to_vec(),
932 string_filter: b"StdCF".to_vec(),
933 owner_password: "owner",
934 user_password: "user",
935 permissions: Permissions::all(),
936 };
937
938 let state = EncryptionState::try_from(version).unwrap();
939
940 assert!(document.encrypt(&state).is_ok());
941 assert!(document.decrypt("user").is_ok());
942 }
943
944 #[test]
945 fn encrypt_r5() {
946 let mut document = create_document();
947
948 let crypt_filter: Arc<dyn CryptFilter> = Arc::new(Aes256CryptFilter);
949
950 let mut file_encryption_key = [0u8; 32];
951
952 let mut rng = rand::rng();
953 rng.fill(&mut file_encryption_key);
954
955 #[allow(deprecated)]
956 let version = EncryptionVersion::R5 {
957 encrypt_metadata: true,
958 crypt_filters: BTreeMap::from([(b"StdCF".to_vec(), crypt_filter)]),
959 file_encryption_key: &file_encryption_key,
960 stream_filter: b"StdCF".to_vec(),
961 string_filter: b"StdCF".to_vec(),
962 owner_password: "owner",
963 user_password: "user",
964 permissions: Permissions::all(),
965 };
966
967 let state = EncryptionState::try_from(version).unwrap();
968
969 assert!(document.encrypt(&state).is_ok());
970 assert!(document.decrypt("user").is_ok());
971 }
972
973 #[test]
974 fn encrypt_v5() {
975 let mut document = create_document();
976
977 let crypt_filter: Arc<dyn CryptFilter> = Arc::new(Aes256CryptFilter);
978
979 let mut file_encryption_key = [0u8; 32];
980
981 let mut rng = rand::rng();
982 rng.fill(&mut file_encryption_key);
983
984 let version = EncryptionVersion::V5 {
985 encrypt_metadata: true,
986 crypt_filters: BTreeMap::from([(b"StdCF".to_vec(), crypt_filter)]),
987 file_encryption_key: &file_encryption_key,
988 stream_filter: b"StdCF".to_vec(),
989 string_filter: b"StdCF".to_vec(),
990 owner_password: "owner",
991 user_password: "user",
992 permissions: Permissions::all(),
993 };
994
995 let state = EncryptionState::try_from(version).unwrap();
996
997 assert!(document.encrypt(&state).is_ok());
998 assert!(document.decrypt("user").is_ok());
999 }
1000}