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