lopdf/
encryption.rs

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    // Used generically when the object type violates the spec
45    #[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        /// (Security handlers of revision 2) Print the document.
70        /// (Security handlers of revision 3 or greater) Print the document (possibly not at the
71        /// highest quality level, depending on whether [`Permissions::PRINTABLE_IN_HIGH_QUALITY`]
72        /// is also set).
73        const PRINTABLE = 1 << 2;
74
75        /// Modify the contents of the document by operations other than those controlled by
76        /// [`Permissions::ANNOTABLE`], [`Permissions::FILLABLE`] and [`Permissions::ASSEMBLABLE`].
77        const MODIFIABLE = 1 << 3;
78
79        /// Copy or otherwise extract text and graphics from the document. However, for the limited
80        /// purpose of providing this content to assistive technology, a PDF reader should behave
81        /// as if this bit was set to 1.
82        const COPYABLE = 1 << 4;
83
84        /// Add or modify text annotations, fill in interactive form fields, and if
85        /// [`Permissions::MODIFIABLE`] is also set, create or modify interactive form fields
86        /// (including signature fields).
87        const ANNOTABLE = 1 << 5;
88
89        /// Fill in existing interactive fields (including signature fields), even if
90        /// [`Permissions::ANNOTABLE`] is clear.
91        const FILLABLE = 1 << 8;
92
93        /// Copy or otherwise extract text and graphics from the document for the purpose of
94        /// providing this content to assistive technology.
95        ///
96        /// Deprecated since PDF 2.0: must always be set for backward compatibility with PDF
97        /// viewers following earlier specifications.
98        const COPYABLE_FOR_ACCESSIBILITY = 1 << 9;
99
100        /// (Security handlers of revision 3 or greater) Assemble the document (insert, rotate, or
101        /// delete pages and create document outline items or thumbnail images), even if
102        /// [`Permissions::MODIFIABLE`] is not set.
103        const ASSEMBLABLE = 1 << 10;
104
105        /// (Security handlers of revision 3 or greater) Print the document to a representation
106        /// from which a faithful copy of the PDF content could be generated, based on an
107        /// implementation-dependent algorithm. When this bit is clear (and
108        /// [`Permissions::PRINTABLE`] is set), printing shall be limited to a low-level
109        /// representation of the appearance, possibly of degraded quality.
110        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        // 7-8: Reserved. Must be 1.
125        bits |= 0b11 << 6;
126
127        // 13-32: Reserved. Must be 1.
128        bits |= 0b1111 << 12 | 0xffff << 16;
129
130        // Extend the permissions (contents of the P integer) to 64 bits by setting the upper 32
131        // bits to all 1s.
132        bits |= 0xffffffff << 32;
133
134        Permissions::from_bits_retain(bits)
135    }
136}
137
138#[derive(Clone, Debug)]
139pub enum EncryptionVersion<'a> {
140    /// (PDF 1.4; deprecated in PDF 2.0) Indicates the use of encryption of data using the RC4 or
141    /// AES algorithms with a file encryption key length of 40 bits.
142    V1 {
143        document: &'a Document,
144        owner_password: &'a str,
145        user_password: &'a str,
146        permissions: Permissions,
147    },
148    /// (PDF 1.4; deprecated in PDF 2.0) Indicates the use of encryption of data using the RC4 or
149    /// AES algorithms but permitting file encryption key lengths greater or 40 bits.
150    V2 {
151        document: &'a Document,
152        owner_password: &'a str,
153        user_password: &'a str,
154        key_length: usize,
155        permissions: Permissions,
156    },
157    /// (PDF 1.5; deprecated in PDF 2.0) The security handler defines the use of encryption and
158    /// decryption in the document, using the rules specified by the CF, StmF and StrF entries
159    /// using encryption of data using the RC4 or AES algorithms (deprecated in PDF  2.0) with a
160    /// file encryption key length of 128 bits.
161    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    /// (PDF 2.0; deprecated in PDF 2.0) Shall not be used. This value was used by a deprecated
172    /// proprietary Adobe extension.
173    ///
174    /// This exists for testing purposes to guarantee improved compatibility.
175    #[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    /// (PDF 2.0) The security handler defines the use of encryption and decryption in the
187    /// document, using the rules specified by the CF, StmF, StrF and EFF entries using encryption
188    /// of data using the AES algorithms with a file encryption key length of 256 bits.
189    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        // The name of the preferred security handler for this document. It shall be the name of
575        // the security handler that was used to encrypt the document.
576        //
577        // Standard shall be the name of the built-in password-based security handler.
578        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        // CF is meaningful only when the value of V is 4 (PDF 1.5) or 5 (PDF 2.0).
593        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        // StmF and StrF are meaningful only when the value of V is 4 (PDF 1.5) or 5 (PDF 2.0).
614        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        // Optional; meaningful only when the value of V is 4 (PDF 1.5) or 5 (PDF 2.0)). Indicates
644        // whether the document-level metadata stream shall be encrypted. Default value: true.
645        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
688/// Encrypts `obj`.
689pub fn encrypt_object(state: &EncryptionState, obj_id: ObjectId, obj: &mut Object) -> Result<(), DecryptionError> {
690    // The cross-reference stream shall not be encrypted and strings appearing in the
691    // cross-reference stream dictionary shall not be encrypted.
692    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    // The Metadata stream shall only be encrypted if EncryptMetadata is set to true.
701    if obj.type_name().ok() == Some(b"Metadata") && !state.encrypt_metadata {
702        return Ok(());
703    }
704
705    // A stream filter type, the Crypt filter can be specified for any stream in the document to
706    // override the default filter for streams. The stream's DecodeParms entry shall contain a
707    // Crypt filter decode parameters dictionary whose Name entry specifies the particular crypt
708    // filter that shell be used (if missing, Identity is used).
709    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    // Retrieve the plaintext and the crypt filter to use to decrypt the ciphertext from the given
721    // object.
722    let (mut crypt_filter, plaintext) = match obj {
723        // Encryption applies to all strings and streams in the document's PDF file, i.e., we have to
724        // recursively process array and dictionary objects to decrypt any string and stream objects
725        // stored inside of those.
726        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        // Encryption applies to all strings and streams in the document's PDF file. We return the
741        // crypt filter and the content here.
742        Object::String(content, _) => (state.get_string_filter(), &*content),
743        Object::Stream(stream) => (state.get_stream_filter(), &stream.content),
744        // Encryption is not applied to other object types such as integers and boolean values.
745        _ => {
746            return Ok(());
747        }
748    };
749
750    // If the stream object specifies its own crypt filter, override the default one with the one
751    // from this stream object.
752    if let Some(filter) = override_crypt_filter {
753        crypt_filter = filter;
754    }
755
756    // Compute the key from the original file encryption key and the object identifier to use for
757    // the corresponding object.
758    let key = crypt_filter.compute_key(&state.file_encryption_key, obj_id)?;
759
760    // Encrypt the plaintext.
761    let ciphertext = crypt_filter.encrypt(&key, plaintext)?;
762
763    // Store the ciphertext in the object.
764    match obj {
765        Object::Stream(stream) => stream.set_content(ciphertext),
766        Object::String(content, _) => *content = ciphertext,
767        _ => (),
768    }
769
770    Ok(())
771}
772
773/// Decrypts `obj`.
774pub fn decrypt_object(state: &EncryptionState, obj_id: ObjectId, obj: &mut Object) -> Result<(), DecryptionError> {
775    // The cross-reference stream shall not be encrypted and strings appearing in the
776    // cross-reference stream dictionary shall not be encrypted.
777    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    // The Metadata stream shall only be encrypted if EncryptMetadata is set to true.
786    if obj.type_name().ok() == Some(b"Metadata") && !state.encrypt_metadata {
787        return Ok(());
788    }
789
790    // A stream filter type, the Crypt filter can be specified for any stream in the document to
791    // override the default filter for streams. The stream's DecodeParms entry shall contain a
792    // Crypt filter decode parameters dictionary whose Name entry specifies the particular crypt
793    // filter that shell be used (if missing, Identity is used).
794    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    // Retrieve the ciphertext and the crypt filter to use to decrypt the ciphertext from the given
806    // object.
807    let (mut crypt_filter, ciphertext) = match obj {
808        // Encryption applies to all strings and streams in the document's PDF file, i.e., we have to
809        // recursively process array and dictionary objects to decrypt any string and stream objects
810        // stored inside of those.
811        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        // Encryption applies to all strings and streams in the document's PDF file. We return the
826        // crypt filter and the content here.
827        Object::String(content, _) => (state.get_string_filter(), &*content),
828        Object::Stream(stream) => (state.get_stream_filter(), &stream.content),
829        // Encryption is not applied to other object types such as integers and boolean values.
830        _ => {
831            return Ok(());
832        }
833    };
834
835    // If the stream object specifies its own crypt filter, override the default one with the one
836    // from this stream object.
837    if let Some(filter) = override_crypt_filter {
838        crypt_filter = filter;
839    }
840
841    // Compute the key from the original file encryption key and the object identifier to use for
842    // the corresponding object.
843    let key = crypt_filter.compute_key(&state.file_encryption_key, obj_id)?;
844
845    // Decrypt the ciphertext.
846    let plaintext = crypt_filter.decrypt(&key, ciphertext)?;
847
848    // Store the plaintext in the object.
849    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            // Key, Plain, Cipher
872            (
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            // Reencode cipher from a hex string to a Vec<u8>
882            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}