Skip to main content

lopdf/encryption/
algorithms.rs

1use super::DecryptionError;
2use super::rc4::Rc4;
3use crate::encodings;
4use crate::encryption::Permissions;
5use crate::{Document, Error, Object};
6use aes::cipher::{BlockDecryptMut as _, BlockEncryptMut as _, KeyInit as _, KeyIvInit as _};
7use md5::{Digest as _, Md5};
8use rand::RngExt as _;
9use sha2::{Sha256, Sha384, Sha512};
10
11type Aes128CbcEnc = cbc::Encryptor<aes::Aes128>;
12type Aes256CbcEnc = cbc::Encryptor<aes::Aes256>;
13type Aes256EbcEnc = ecb::Encryptor<aes::Aes256>;
14
15type Aes256CbcDec = cbc::Decryptor<aes::Aes256>;
16type Aes256EbcDec = ecb::Decryptor<aes::Aes256>;
17
18// If the password string is less than 32 bytes long, pad it by appending the required number of
19// additional bytes from the beginning of the following padding string.
20const PAD_BYTES: [u8; 32] = [
21    0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08, 0x2E, 0x2E, 0x00,
22    0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A,
23];
24
25#[derive(Clone, Debug, Default)]
26pub struct PasswordAlgorithm {
27    pub(crate) encrypt_metadata: bool,
28    pub(crate) length: Option<usize>,
29    pub(crate) version: i64,
30    pub(crate) revision: i64,
31    pub(crate) owner_value: Vec<u8>,
32    pub(crate) owner_encrypted: Vec<u8>,
33    pub(crate) user_value: Vec<u8>,
34    pub(crate) user_encrypted: Vec<u8>,
35    pub(crate) permissions: Permissions,
36    pub(crate) permission_encrypted: Vec<u8>,
37}
38
39impl TryFrom<&Document> for PasswordAlgorithm {
40    type Error = Error;
41
42    fn try_from(value: &Document) -> Result<Self, Self::Error> {
43        // Get the encrypted dictionary.
44        let encrypted = value
45            .get_encrypted()
46            .map_err(|_| DecryptionError::MissingEncryptDictionary)?;
47
48        // Get the EncryptMetadata field.
49        let encrypt_metadata = encrypted
50            .get(b"EncryptMetadata")
51            .unwrap_or(&Object::Boolean(true))
52            .as_bool()
53            .map_err(|_| DecryptionError::InvalidType)?;
54
55        // Get the Length field if any. Make sure that if it is present that it is a 64-bit integer and
56        // that it can be converted to an unsigned size.
57        let length: Option<usize> = if encrypted.get(b"Length").is_ok() {
58            Some(encrypted.get(b"Length")?.as_i64()?.try_into()?)
59        } else {
60            None
61        };
62
63        // Get the V field.
64        let version = encrypted
65            .get(b"V")
66            .map_err(|_| DecryptionError::MissingVersion)?
67            .as_i64()
68            .map_err(|_| DecryptionError::InvalidType)?;
69
70        // A code specifying the algorithm to be used in encrypting and decrypting the document.
71        match version {
72            // (Deprecated in PDF 2.0) An algorithm that is undocumented. This value shall not be
73            // used.
74            0 => return Err(DecryptionError::InvalidVersion)?,
75            // (PDF 1.4; deprecated in PDF 2.0) Indicates the use of encryption of data using the
76            // RC4 or AES algorithms with a file encryption key length of 40 bits.
77            1 => (),
78            // (PDF 1.4; deprecated in PDF 2.0) Indicates the use of encryption of data using the
79            // RC4 or AES algorithms but permitting file encryption key lengths greater or 40 bits.
80            2 => (),
81            // (PDF 1.4; deprecated in PDF 2.0) An unpublished algorithm that permits encryption
82            // key lengths ranging from 40 to 128 bits. This value shall not appear in a conforming
83            // PDF file.
84            3 => return Err(DecryptionError::InvalidVersion)?,
85            // (PDF 1.5; deprecated in PDF 2.0) The security handler defines the use of encryption
86            // and decryption in the document, using the rules specified by the CF, StmF and StrF
87            // entries using encryption of data using the RC4 or AES algorithms (deprecated in PDF
88            // 2.0) with a file encryption key length of 128 bits.
89            4 => (),
90            // (PDF 2.0) The security handler defines the use of encryption and decryption in the
91            // document, using the rules specified by the CF, StmF, StrF and EFF entries using
92            // encryption of data using the AES algorithms with a file encryption key length of 256
93            // bits.
94            5 => (),
95            // Unknown codes.
96            _ => return Err(DecryptionError::UnsupportedVersion)?,
97        }
98
99        // The length of the file encryption key shall only be present if V is 2 or 3 (but
100        // documents with higher values for V seem to have this field).
101        if let Some(length) = length {
102            match version {
103                // Although "Optional" and/or not required for V1 it appears in some documents
104                // with a default value of 40.
105                1 => {
106                    if length != 40 {
107                        return Err(DecryptionError::InvalidKeyLength)?;
108                    }
109                }
110                // The length of the file encryption key shall be a multiple of 8 in the range 40
111                // to and including 128.
112                2..=3 => {
113                    if length % 8 != 0 || !(40..=128).contains(&length) {
114                        return Err(DecryptionError::InvalidKeyLength)?;
115                    }
116                }
117                // The Length field should not be present if V is 4. However, if it is present it
118                // must be 128.
119                4 => {
120                    if length != 128 {
121                        return Err(DecryptionError::InvalidKeyLength)?;
122                    }
123                }
124                // The Length field should not be present if V is 5. However, if it is present it
125                // must be 256.
126                5 => {
127                    if length != 256 {
128                        return Err(DecryptionError::InvalidKeyLength)?;
129                    }
130                }
131                // The Length field may not be present otherwise.
132                _ => return Err(DecryptionError::InvalidKeyLength)?,
133            }
134        }
135
136        // Get the R field.
137        let revision = encrypted
138            .get(b"R")
139            .map_err(|_| DecryptionError::MissingRevision)?
140            .as_i64()
141            .map_err(|_| DecryptionError::InvalidType)?;
142
143        // Get the owner value and owner encrypted blobs.
144        let mut owner_value = encrypted
145            .get(b"O")
146            .map_err(|_| DecryptionError::MissingOwnerPassword)?
147            .as_str()
148            .map_err(|_| DecryptionError::InvalidType)?
149            .to_vec();
150
151        // The owner value is 32 bytes long if the value of R is 4 or less.
152        if revision <= 4 && owner_value.len() != 32 {
153            return Err(DecryptionError::InvalidHashLength)?;
154        }
155
156        // The owner value is 48 bytes long if the value of R is 5 or greater.
157        // Some PDF writers pad /O with trailing zeros beyond 48 bytes; truncate
158        // to the spec-required length so these documents are accepted.
159        if revision >= 5 {
160            if owner_value.len() < 48 {
161                return Err(DecryptionError::InvalidHashLength)?;
162            }
163            owner_value.truncate(48);
164        }
165
166        let owner_encrypted = encrypted
167            .get(b"OE")
168            .and_then(Object::as_str)
169            .map(|s| s.to_vec())
170            .ok()
171            .unwrap_or_default();
172
173        // The owner encrypted blob is required if R is 5 or greater and the blob shall be 32 bytes
174        // long.
175        if revision >= 5 && owner_encrypted.len() != 32 {
176            return Err(DecryptionError::InvalidCipherTextLength)?;
177        }
178
179        // Get the user value and user encrypted blobs.
180        let mut user_value = encrypted
181            .get(b"U")
182            .map_err(|_| DecryptionError::MissingUserPassword)?
183            .as_str()
184            .map_err(|_| DecryptionError::InvalidType)?
185            .to_vec();
186
187        // The user value is 32 bytes long if the value of R is 4 or less.
188        if revision <= 4 && user_value.len() != 32 {
189            return Err(DecryptionError::InvalidHashLength)?;
190        }
191
192        // The user value is 48 bytes long if the value of R is 5 or greater.
193        // Some PDF writers pad /U with trailing zeros beyond 48 bytes; truncate
194        // to the spec-required length so these documents are accepted.
195        if revision >= 5 {
196            if user_value.len() < 48 {
197                return Err(DecryptionError::InvalidHashLength)?;
198            }
199            user_value.truncate(48);
200        }
201
202        let user_encrypted = encrypted
203            .get(b"UE")
204            .and_then(Object::as_str)
205            .map(|s| s.to_vec())
206            .ok()
207            .unwrap_or_default();
208
209        // The user encrypted blob is required if R is 5 or greater and the blob shall be 32 bytes
210        // long.
211        if revision >= 5 && user_encrypted.len() != 32 {
212            return Err(DecryptionError::InvalidCipherTextLength)?;
213        }
214
215        // Get the permission value and permission encrypted blobs.
216        let permission_value = encrypted
217            .get(b"P")
218            .map_err(|_| DecryptionError::MissingPermissions)?
219            .as_i64()
220            .map_err(|_| DecryptionError::InvalidType)? as u64;
221
222        let permissions = Permissions::from_bits_retain(permission_value);
223
224        let permission_encrypted = encrypted
225            .get(b"Perms")
226            .and_then(Object::as_str)
227            .map(|s| s.to_vec())
228            .ok()
229            .unwrap_or_default();
230
231        // The permission encrypted blob is required if R is 65 or greater and the blob shall be
232        // 16 bytes long.
233        if revision >= 5 && permission_encrypted.len() != 16 {
234            return Err(DecryptionError::InvalidCipherTextLength)?;
235        }
236
237        Ok(Self {
238            encrypt_metadata,
239            length,
240            version,
241            revision,
242            owner_value,
243            owner_encrypted,
244            user_value,
245            user_encrypted,
246            permissions,
247            permission_encrypted,
248        })
249    }
250}
251
252impl PasswordAlgorithm {
253    /// Sanitize the password (revision 4 and earlier).
254    ///
255    /// This implements the first step of Algorithm 2 as described in ISO 32000-2:2020 (PDF 2.0).
256    ///
257    /// This algorithm is deprecated in PDF 2.0.
258    pub(crate) fn sanitize_password_r4(&self, password: &str) -> Result<Vec<u8>, DecryptionError> {
259        // The password string is generated from host system codepage characters (or system scripts) by
260        // first converting the string to PDFDocEncoding. If the input is Unicode, first convert to a
261        // codepage encoding, and then to PDFDocEncoding for backward compatibility.
262        let password = encodings::string_to_bytes(&encodings::PDF_DOC_ENCODING, password);
263
264        Ok(password)
265    }
266
267    /// Compute a file encryption key in order to encrypt/decrypt a document (revision 4 and
268    /// earlier).
269    ///
270    /// This implements Algorithm 2 as described in ISO 32000-2:2020 (PDF 2.0).
271    ///
272    /// This algorithm is deprecated in PDF 2.0.
273    pub(crate) fn compute_file_encryption_key_r4<P>(
274        &self, doc: &Document, password: P,
275    ) -> Result<Vec<u8>, DecryptionError>
276    where
277        P: AsRef<[u8]>,
278    {
279        let password = password.as_ref();
280
281        // Pad or truncate the resulting password string to exactly 32 bytes. If the password string is
282        // more than 32 bytes long, use only its first 32 bytes; if it is less than 32 bytes long, pad
283        // it by appending the required number of additional bytes from the beginning of the following
284        // padding string (see `PAD_BYTES`).
285        //
286        // That is, if the password is n bytes long, append the first 32 - n bytes of the padding
287        // string to the end of the password string. If the password string is empty (zero-length),
288        // meaning there is no user password, substitute the entire padding string in its place.
289        //
290        // i.e., we will simply calculate `len = min(password length, 32)` and use the first len bytes
291        // of password and the first len bytes of `PAD_BYTES`.
292        let len = password.len().min(32);
293
294        // Initialize the MD5 hash function and pass the result as input to this function.
295        let mut hasher = Md5::new();
296
297        hasher.update(&password[..len]);
298        hasher.update(&PAD_BYTES[..32 - len]);
299
300        // Pass the value of the encryption dictionary's O entry (owner password hash) to the MD5 hash
301        // function.
302        hasher.update(&self.owner_value);
303
304        // Convert the integer value of the P entry (permissions) to a 32-bit unsigned binary number
305        // and pass these bytes to the MD5 hash function, low-order byte first.
306        //
307        // We don't actually care about the permissions, but we need the correct value to derive the
308        // correct key.
309        hasher.update((self.permissions.bits() as u32).to_le_bytes());
310
311        // Pass the first element of the file's file identifier array (the value of the ID entry in the
312        // document's trailer dictionary to the MD5 hash function.
313        let file_id_0 = doc
314            .trailer
315            .get(b"ID")
316            .map_err(|_| DecryptionError::MissingFileID)?
317            .as_array()
318            .map_err(|_| DecryptionError::InvalidType)?
319            .first()
320            .ok_or(DecryptionError::InvalidType)?
321            .as_str()
322            .map_err(|_| DecryptionError::InvalidType)?;
323        hasher.update(file_id_0);
324
325        // (Security handlers of revision 4 or greater) If document metadata is not being encrypted,
326        // pass 4 bytes with the value 0xFFFFFFFF to the MD5 hash function.
327        if self.revision >= 4 && !self.encrypt_metadata {
328            hasher.update(b"\xff\xff\xff\xff");
329        }
330
331        // Finish the hash.
332        let mut hash = hasher.finalize();
333
334        // (Security handlers of revision 3 or greater) Do the following 50 times: take the output from
335        // the previous MD5 hash and pass the first n bytes of the output as input into a new MD5 hash,
336        // where n is the number of bytes of the file encryption key as defined by the value of the
337        // encryption dictionary's Length entry.
338        let n = if self.revision >= 3 {
339            self.length.unwrap_or(40) / 8
340        } else {
341            5
342        };
343
344        // The maximum supported key length is 16 bytes (128 bits) due to the use of MD5.
345        if n > 16 {
346            return Err(DecryptionError::InvalidKeyLength);
347        }
348
349        if self.revision >= 3 {
350            for _ in 0..50 {
351                hash = Md5::digest(&hash[..n]);
352            }
353        }
354
355        // Set the file encryption key to the first n bytes of the output from the final MD5 hash,
356        // where n shall always be 5 for security handlers of revision 2 but, for security handlers of
357        // revision 3 or greater, shall depend on the value of the encrpytion dictionary's Length
358        // entry.
359        Ok(hash[..n].to_vec())
360    }
361
362    /// Sanitize the password (revision 6 and later).
363    ///
364    /// This implements the first step of Algorithm 2.A as described in ISO 32000-2:2020 (PDF 2.0).
365    pub(crate) fn sanitize_password_r6(&self, password: &str) -> Result<Vec<u8>, DecryptionError> {
366        // The UTF-8 password string shall be generated from Unicode input by processing the input
367        // with the SASLprep (Internet RFC 4013) profile of stringprep (Internet RFC 3454) using
368        // the Normalize and BiDi options, and then coverting to a UTF-8 representation.
369        Ok(stringprep::saslprep(password)?.as_bytes().to_vec())
370    }
371
372    /// Compute a file encryption key in order to encrypt/decrypt a document (revision 6 and
373    /// later).
374    ///
375    /// This implements Algorithm 2.A as described in ISO 32000-2:2020 (PDF 2.0).
376    fn compute_file_encryption_key_r6<P>(&self, password: P) -> Result<Vec<u8>, DecryptionError>
377    where
378        P: AsRef<[u8]>,
379    {
380        let mut password = password.as_ref();
381
382        let hashed_owner_password = &self.owner_value[0..][..32];
383        let owner_validation_salt = &self.owner_value[32..][..8];
384        let owner_key_salt = &self.owner_value[40..][..8];
385
386        let hashed_user_password = &self.user_value[0..][..32];
387        let user_validation_salt = &self.user_value[32..][..8];
388        let user_key_salt = &self.user_value[40..][..8];
389
390        // Truncate the UTF-8 representation to 127 bytes if it is longer than 127 bytes.
391        if password.len() > 127 {
392            password = &password[..127];
393        }
394
395        // Test the password against the owner key by computing a hash using algorithm 2.B with an
396        // input string consisting of the UTF-8 password concatenated with the 8 bytes of owner
397        // validation salt, concatenated with the 48-byte U string. If the 32-byte result matches
398        // the first 32 bytes of the O string, this is the owner password.
399        if self.compute_hash(password, owner_validation_salt, Some(&self.user_value))? == hashed_owner_password {
400            // Compute an intermediate owner key by computing a hash using algorithm 2.B with an
401            // input string consisting of the UTF-8 owner password concatenated with the 8 bytes of
402            // owner key salt, concatenated with the 48-byte U string.
403            let hash = self.compute_hash(password, owner_key_salt, Some(&self.user_value))?;
404
405            let mut key = [0u8; 32];
406            key.copy_from_slice(&hash);
407
408            // The 32-byte result is the key used to decrypt the 32-byte OE string using AES-256 in
409            // CBC mode with no padding and an initialization vector of zero. The 32-byte result is
410            // the file encryption key.
411            let iv = [0u8; 16];
412
413            let mut owner_encrypted = self.owner_encrypted.clone();
414            let mut decryptor = Aes256CbcDec::new(&key.into(), &iv.into());
415
416            for block in owner_encrypted.chunks_exact_mut(16) {
417                decryptor.decrypt_block_mut(block.into());
418            }
419
420            return Ok(owner_encrypted);
421        }
422
423        // Note: this step is not in the specification, but is a precaution.
424        //
425        // Test the password against the user key by computing a hash using algorithm 2.B with an
426        // input string consisting of the UTF-8 password concatenated with the 8 bytes of user
427        // validation salt. If the 32-byte result matches the first 32-bytes of the U string, this
428        // is the user password.
429
430        if self.compute_hash(password, user_validation_salt, None)? == hashed_user_password {
431            // Compute an intermediate user key by computing a hash using algorithm 2.B with an
432            // input string consisting of the UTF-8 owner password concatenated with the 8 bytes of
433            // user key salt.
434            let hash = self.compute_hash(password, user_key_salt, None)?;
435
436            let mut key = [0u8; 32];
437            key.copy_from_slice(&hash);
438
439            // The 32-byte result is the key used to decrypt the 32-byte UE string using AES-256 in
440            // CBC mode with no padding and an initialization vector of zero. The 32-byte result is
441            // the file encryption key.
442            let iv = [0u8; 16];
443            let mut user_encrypted = self.user_encrypted.clone();
444            let mut decryptor = Aes256CbcDec::new(&key.into(), &iv.into());
445
446            for block in user_encrypted.chunks_exact_mut(16) {
447                decryptor.decrypt_block_mut(block.into());
448            }
449
450            // Decrypt the 16-byte Perms string using AES-256 in EBC mode with an initialization
451            // vector of zero and the file encryption key as the key. Verify that bytes 9-11 of the
452            // result are the characters "a", "d", "b". Bytes 0-3 of the decrypted Perms entry,
453            // treated as a little-endian integer, are the user permissions. They shall match the
454            // value in the P key.
455            //
456            // i.e., use algorithm 13 to validate the permissions.
457            self.validate_permissions(&user_encrypted)?;
458
459            return Ok(user_encrypted);
460        }
461
462        Err(DecryptionError::IncorrectPassword)
463    }
464
465    /// Compute a hash (revision 6 and later).
466    ///
467    /// This implements Algorithm 2.B as described in ISO 32000-2:2020 (PDF 2.0).
468    fn compute_hash<P, S>(&self, password: P, salt: S, user_key: Option<&[u8]>) -> Result<Vec<u8>, DecryptionError>
469    where
470        P: AsRef<[u8]>,
471        S: AsRef<[u8]>,
472    {
473        let password = password.as_ref();
474        let salt = salt.as_ref();
475
476        // Take the SHA-256 hash of the original input to the algorithm and name the resulting 32
477        // bytes, K.
478        let mut hasher = Sha256::new();
479
480        hasher.update(password);
481        hasher.update(salt);
482
483        if let Some(user_key) = user_key {
484            hasher.update(user_key);
485        }
486
487        let mut k = hasher.finalize().to_vec();
488
489        // Revision 5 uses a simplified hash algorithm that simply calculates the SHA-256 hash of
490        // the original input to the algorithm.
491        if self.revision == 5 {
492            return Ok(k);
493        }
494
495        let mut k1 =
496            Vec::with_capacity(64 * (password.len() + 64 + user_key.map(|user_key| user_key.len()).unwrap_or(0)));
497
498        // Perform the following steps at least 64 times, until the value of the last byte in K is
499        // less than or equal to (round number) - 32.
500        for round in 1.. {
501            // Make a new string K0 as follows:
502            //
503            // * When checking the owner password or creating the owner key, K0 is the concatenation of the input
504            //   password, K, and the 48-byte user key.
505            // * Otherwise, K0 is the concatenation of the input password and K.
506            //
507            // Next, set K1 to 64 repetitions of K0.
508            k1.clear();
509
510            for _ in 0..64 {
511                k1.extend_from_slice(password);
512                k1.extend_from_slice(&k);
513
514                if let Some(user_key) = user_key {
515                    k1.extend_from_slice(user_key);
516                }
517            }
518
519            // Encrypt K1 with the AES-128 (CBC, no padding) algorithm, using the first 16 bytes of
520            // K as the key, and the second 16 bytes of K as the initialization vector. The result
521            // of this encryption is E.
522            //
523            // The 64 repetitions of K0 ensure that K1 is a multiple of 64 bytes, thus a multiple
524            // of 16 bytes, i.e., it does not require padding.
525            let key = &k[0..][..16];
526            let iv = &k[16..][..16];
527
528            let mut encryptor = Aes128CbcEnc::new(key.into(), iv.into());
529
530            for block in k1.chunks_exact_mut(16) {
531                encryptor.encrypt_block_mut(block.into());
532            }
533
534            let e = k1;
535
536            // Taking the first 16 bytes of E as an unsigned big-endian integer, compute the
537            // remainder, modulo 3. If the result is 0, the next hash used is SHA-256. If the
538            // result is 1, the next hash used is SHA-384. If the result is 2, the next hash used
539            // is SHA-256.
540            //
541            // Using the hash algorithm determined in the previous step, take the hash of E. The
542            // result is a new value of K, which will be 32, 48 or 64 bytes in length.
543            k = match e[..16].iter().map(|v| *v as u32).sum::<u32>() % 3 {
544                0 => Sha256::digest(&e).to_vec(),
545                1 => Sha384::digest(&e).to_vec(),
546                2 => Sha512::digest(&e).to_vec(),
547                _ => unreachable!(),
548            };
549
550            // Look at the very last byte of E. If the value of that byte (taken as an unsigned
551            // integer) is greater than the round number - 32, repeat the round again.
552            //
553            // Repeat rounds until the value of the last byte is less than or equal to (round
554            // number) - 32.
555            if round >= 64 && e.last().copied().unwrap_or(0) as u32 <= round - 32 {
556                break;
557            }
558
559            // Move e into k1 for the next round (to reuse k1).
560            k1 = e;
561        }
562
563        // The first 32 bytes of the final K are the output of the algorithm.
564        k.truncate(32);
565
566        Ok(k)
567    }
568
569    /// Compute the encryption dictionary's O-entry value (revision 4 and earlier).
570    ///
571    /// This implements Algorithm 3 as described in ISO 32000-2:2020 (PDF 2.0).
572    ///
573    /// This algorithm is deprecated in PDF 2.0.
574    pub(crate) fn compute_hashed_owner_password_r4<O, U>(
575        &self, owner_password: Option<O>, user_password: U,
576    ) -> Result<Vec<u8>, DecryptionError>
577    where
578        O: AsRef<[u8]>,
579        U: AsRef<[u8]>,
580    {
581        let user_password = user_password.as_ref();
582
583        // Pad or truncate the owner string. If there is no owner password, use the user password
584        // instead.
585        let password = owner_password
586            .as_ref()
587            .map(|password| password.as_ref())
588            .unwrap_or(user_password);
589
590        // Pad or truncate the resulting password string to exactly 32 bytes. If the password string is
591        // more than 32 bytes long, use only its first 32 bytes; if it is less than 32 bytes long, pad
592        // it by appending the required number of additional bytes from the beginning of the following
593        // padding string (see `PAD_BYTES`).
594        //
595        // That is, if the password is n bytes long, append the first 32 - n bytes of the padding
596        // string to the end of the password string. If the password string is empty (zero-length),
597        // meaning there is no user password, substitute the entire padding string in its place.
598        //
599        // i.e., we will simply calculate `len = min(password length, 32)` and use the first len bytes
600        // of password and the first len bytes of `PAD_BYTES`.
601        let len = password.len().min(32);
602
603        // Initialize the MD5 hash function and pass the result as input to this function.
604        let mut hasher = Md5::new();
605
606        hasher.update(&password[..len]);
607        hasher.update(&PAD_BYTES[..32 - len]);
608
609        let mut hash = hasher.finalize();
610
611        // (Security handlers of revision 3 or greater) Do the following 50 times: take the output from
612        // the previous MD5 hash and pass it as input into a new MD5 hash.
613        if self.revision >= 3 {
614            for _ in 0..50 {
615                hash = Md5::digest(hash);
616            }
617        }
618
619        // Create an RC4 file encryption key using the first n bytes of the output from the final MD5
620        // hash, where n shall always be 5 for security handlers of revision 2 but, for security
621        // handlers of revision 3 or greater, shall depend on the value of the encryption dictionary's
622        // Length entry.
623        let n = if self.revision >= 3 {
624            self.length.unwrap_or(40) / 8
625        } else {
626            5
627        };
628
629        // The maximum supported key length is 16 bytes (128 bits) due to the use of MD5.
630        if n > 16 {
631            return Err(DecryptionError::InvalidKeyLength);
632        }
633
634        // Pad or truncate the user password string to exactly 32 bytes. If the user password string is
635        // more than 32 bytes long, use only its first 32 bytes; if it is less than 32 bytes long, pad
636        // it by appending the required number of additional bytes from the beginning of the following
637        // padding string (see `PAD_BYTES`).
638        //
639        // That is, if the password is n bytes long, append the first 32 - n bytes of the padding
640        // string to the end of the password string. If the password string is empty (zero-length),
641        // meaning there is no user password, substitute the entire padding string in its place.
642        //
643        // i.e., we will simply calculate `len = min(password length, 32)` and use the first len bytes
644        // of password and the first len bytes of `PAD_BYTES`.
645        let len = user_password.len().min(32);
646
647        // Encrypt the result of the previous step using an RC4 encryption function with the RC4 file
648        // encryption key obtained in the step before the previous step.
649        let mut bytes = [0u8; 32];
650
651        bytes[..len].copy_from_slice(&user_password[..len]);
652        bytes[len..].copy_from_slice(&PAD_BYTES[..32 - len]);
653
654        let mut result = Rc4::new(&hash[..n]).encrypt(bytes);
655
656        // (Security handlers of revision 3 or greater) Do the following 19 times: Take the output from
657        // the previous invocation of the RC4 function and pass it as input to a new invocation of the
658        // function; use a file encryption key generated by taking each byte of the RC4 file encryption
659        // key and performing an XOR (exclusive or) operation between that byte and the single-byte
660        // value of the iteration counter (from 1 to 19).
661        if self.revision >= 3 {
662            let mut key = vec![0u8; n];
663
664            for i in 1..=19 {
665                for (in_byte, out_byte) in hash[..n].iter().zip(key.iter_mut()) {
666                    *out_byte = in_byte ^ i;
667                }
668
669                result = Rc4::new(&key).encrypt(&result);
670            }
671        }
672
673        // Store the output from the final invocation of the RC4 function as the value of the O entry
674        // in the encryption dictionary.
675        Ok(result)
676    }
677
678    /// Compute the encryption dictionary's U-entry value (revision 2).
679    ///
680    /// This implements Algorithm 4 as described in ISO 32000-2:2020 (PDF 2.0).
681    ///
682    /// This algorithm is deprecated in PDF 2.0.
683    pub(crate) fn compute_hashed_user_password_r2<U>(
684        &self, doc: &Document, user_password: U,
685    ) -> Result<Vec<u8>, DecryptionError>
686    where
687        U: AsRef<[u8]>,
688    {
689        // Create a file encryption key based on the user password string.
690        let file_encryption_key = self.compute_file_encryption_key_r4(doc, user_password)?;
691
692        // Encrypt the 32-byte padding string using an RC4 encryption function with the file encryption
693        // key from the preceding step.
694        let result = Rc4::new(&file_encryption_key).encrypt(PAD_BYTES);
695
696        // Store the result of the previous step as the value of the U entry in the encryption dictionary.
697        Ok(result)
698    }
699
700    /// Compute the encryption dictionary's U-entry value (revision 3 or 4).
701    ///
702    /// This implements Algorithm 5 as described in ISO 32000-2:2020 (PDF 2.0).
703    ///
704    /// This algorithm is deprecated in PDF 2.0.
705    pub(crate) fn compute_hashed_user_password_r3_r4<U>(
706        &self, doc: &Document, user_password: U,
707    ) -> Result<Vec<u8>, DecryptionError>
708    where
709        U: AsRef<[u8]>,
710    {
711        // Create a file encryption key based on the user password string.
712        let file_encryption_key = self.compute_file_encryption_key_r4(doc, user_password)?;
713
714        // Initialize the MD5 hash function and pass the 32-byte padding string.
715        let mut hasher = Md5::new();
716
717        hasher.update(PAD_BYTES);
718
719        // Pass the first element of the file's file identifier array (the value of the ID entry in the
720        // document's trailer dictionary) to the hash function and finish the hash.
721        let file_id_0 = doc
722            .trailer
723            .get(b"ID")
724            .map_err(|_| DecryptionError::MissingFileID)?
725            .as_array()
726            .map_err(|_| DecryptionError::InvalidType)?
727            .first()
728            .ok_or(DecryptionError::InvalidType)?
729            .as_str()
730            .map_err(|_| DecryptionError::InvalidType)?;
731        hasher.update(file_id_0);
732
733        let hash = hasher.finalize();
734
735        // Encrypt the 16-byte result of the hash, using an RC4 encryption function with the file
736        // encryption key.
737        let mut result = Rc4::new(&file_encryption_key).encrypt(hash);
738
739        // Do the following 19 times: Take the output from the previous invocation of the RC4 function
740        // and pass it as input to a new invocation of the function; use a file encryption key
741        // generated by taking each byte of the RC4 file encryption key and performing an XOR
742        // (exclusive or) operation between that byte and the single-byte value of the iteration
743        // counter (from 1 to 19).
744        let mut key = vec![0u8; file_encryption_key.len()];
745
746        for i in 1..=19 {
747            for (in_byte, out_byte) in file_encryption_key.iter().zip(key.iter_mut()) {
748                *out_byte = in_byte ^ i;
749            }
750
751            result = Rc4::new(&key).encrypt(&result);
752        }
753
754        // Append 16 bytes of arbitrary padding to the output from the final invocation of the RC4
755        // function and store the 32-byte result as the value of the U entry in the encryption
756        // dictionary.
757        result.resize(32, 0);
758
759        let mut rng = rand::rng();
760        rng.fill(&mut result[16..]);
761
762        Ok(result)
763    }
764
765    /// Authenticate the user password (revision 4 and earlier).
766    ///
767    /// This implements Algorithm 6 as described in ISO 32000-2:2020 (PDF 2.0).
768    ///
769    /// This algorithm is deprecated in PDF 2.0.
770    fn authenticate_user_password_r4<U>(&self, doc: &Document, user_password: U) -> Result<(), DecryptionError>
771    where
772        U: AsRef<[u8]>,
773    {
774        // Perform all but the last step of Algorithm 4 (security handlers of revision 2) or Algorithm
775        // 5 (security handlers of revision 3 or 4) using the supplied password string to compute the
776        // encryption dictionary's U-entry value.
777        let hashed_user_password = match self.revision {
778            2 => self.compute_hashed_user_password_r2(doc, &user_password)?,
779            3 | 4 => self.compute_hashed_user_password_r3_r4(doc, &user_password)?,
780            _ => return Err(DecryptionError::InvalidRevision),
781        };
782
783        // If the result of the previous step is equal to the value of the encryption dictionary's U
784        // entry (comparing on the first 16 bytes in the case of security handlers of revision 3 or
785        // greater), the password supplied is the correct user password.
786        let len = match self.revision {
787            3 | 4 => 16,
788            _ => hashed_user_password.len(),
789        };
790
791        if self.user_value.len() < len {
792            return Err(DecryptionError::InvalidHashLength);
793        }
794
795        if hashed_user_password[..len] != self.user_value[..len] {
796            return Err(DecryptionError::IncorrectPassword);
797        }
798
799        Ok(())
800    }
801
802    /// Authenticate the owner password (revision 4 and earlier).
803    ///
804    /// This implements Algorithm 7 as described in ISO 32000-2:2020 (PDF 2.0).
805    ///
806    /// This algorithm is deprecated in PDF 2.0.
807    fn authenticate_owner_password_r4<O>(&self, doc: &Document, owner_password: O) -> Result<(), DecryptionError>
808    where
809        O: AsRef<[u8]>,
810    {
811        // Pad or truncate the owner string. If there is no owner password, use the user password
812        // instead.
813        let password = owner_password.as_ref();
814
815        // Pad or truncate the resulting password string to exactly 32 bytes. If the password string is
816        // more than 32 bytes long, use only its first 32 bytes; if it is less than 32 bytes long, pad
817        // it by appending the required number of additional bytes from the beginning of the following
818        // padding string (see `PAD_BYTES`).
819        //
820        // That is, if the password is n bytes long, append the first 32 - n bytes of the padding
821        // string to the end of the password string. If the password string is empty (zero-length),
822        // meaning there is no user password, substitute the entire padding string in its place.
823        //
824        // i.e., we will simply calculate `len = min(password length, 32)` and use the first len bytes
825        // of password and the first len bytes of `PAD_BYTES`.
826        let len = password.len().min(32);
827
828        // Initialize the MD5 hash function and pass the result as input to this function.
829        let mut hasher = Md5::new();
830
831        hasher.update(&password[..len]);
832        hasher.update(&PAD_BYTES[..32 - len]);
833
834        let mut hash = hasher.finalize();
835
836        // (Security handlers of revision 3 or greater) Do the following 50 times: take the output from
837        // the previous MD5 hash and pass it as input into a new MD5 hash.
838        if self.revision >= 3 {
839            for _ in 0..50 {
840                hash = Md5::digest(hash);
841            }
842        }
843
844        // Create an RC4 file encryption key using the first n bytes of the output from the final MD5
845        // hash, where n shall always be 5 for security handlers of revision 2 but, for security
846        // handlers of revision 3 or greater, shall depend on the value of the encryption dictionary's
847        // Length entry.
848        let n = if self.revision >= 3 {
849            self.length.unwrap_or(40) / 8
850        } else {
851            5
852        };
853
854        // The maximum supported key length is 16 bytes (128 bits) due to the use of MD5.
855        if n > 16 {
856            return Err(DecryptionError::InvalidKeyLength);
857        }
858
859        // Decrypt the value of the encryption dictionary's O entry, using an RC4 encryption function
860        // with the file encryption key to retrieve the user password.
861        let mut result = self.owner_value.to_vec();
862
863        // (Security handlers of revision 3 or greater) Do the following 19 times: Take the output from
864        // the previous invocation of the RC4 function and pass it as input to a new invocation of the
865        // function; use a file encryption key generated by taking each byte of the RC4 file encryption
866        // key and performing an XOR (exclusive or) operation between that byte and the single-byte
867        // value of the iteration counter (from 19 to 1).
868        if self.revision >= 3 {
869            let mut key = vec![0u8; n];
870
871            for i in (1..=19).rev() {
872                for (in_byte, out_byte) in hash[..n].iter().zip(key.iter_mut()) {
873                    *out_byte = in_byte ^ i;
874                }
875
876                result = Rc4::new(&key).decrypt(&result);
877            }
878        }
879
880        // (Security handler of revision 2 and the final step for revision 3 or greater) Decrypt the
881        // value of the encryption dictionary's O entry, using an RC4 encryption function with the file
882        // encryption key.
883        result = Rc4::new(&hash[..n]).decrypt(&result);
884
885        // The result of the previous step purports to be the user password. Authenticate this user
886        // password using Algorithm 5. If it is correct, the password supplied is the correct owner
887        // password.
888        self.authenticate_user_password_r4(doc, &result)
889    }
890
891    /// Compute the encryption dictionary's U-entry value (revision 6).
892    ///
893    /// This implements Algorithm 8 as described in ISO 32000-2:2020 (PDF 2.0).
894    pub(crate) fn compute_hashed_user_password_r6<K, U>(
895        &self, file_encryption_key: K, user_password: U,
896    ) -> Result<(Vec<u8>, Vec<u8>), DecryptionError>
897    where
898        K: AsRef<[u8]>,
899        U: AsRef<[u8]>,
900    {
901        let file_encryption_key = file_encryption_key.as_ref();
902        let user_password = user_password.as_ref();
903
904        // Generate 16 random bytes of data using a strong random number generator. The first 8
905        // bytes are the user validation salt. The second 8 bytes are the user key salt. Compute
906        // the 32-byte hash using algorithm 2.B with an input string consisting of the UTF-8
907        // password concatenated with the user validation salt. The 48-byte string consisting of
908        // the 32-byte hash followed by the user validation salt followed by the user key salt is
909        // stored as the U key.
910        let mut user_value = [0u8; 48];
911        let mut rng = rand::rng();
912
913        rng.fill(&mut user_value[32..]);
914
915        let user_validation_salt = &user_value[32..][..8];
916
917        let mut input = Vec::with_capacity(user_password.len() + user_validation_salt.len());
918
919        input.extend_from_slice(user_password);
920        input.extend_from_slice(user_validation_salt);
921
922        let hashed_user_password = self.compute_hash(user_password, user_validation_salt, None)?;
923        user_value[..32].copy_from_slice(&hashed_user_password);
924
925        // Compute the 32-byte hash using algorithm 2.B with an input string consisting of the
926        // UTF-8 password concatenated with the user key salt.
927        let user_key_salt = &user_value[40..][..8];
928
929        input.clear();
930
931        input.extend_from_slice(user_password);
932        input.extend_from_slice(user_key_salt);
933
934        let hash = self.compute_hash(user_password, user_key_salt, None)?;
935
936        // Using this hash as the key, encrypt the file encryption key using AES-256 in CBC mode
937        // with no padding and initialization vector of zero. The resulting 32-byte string is
938        // stored as the UE key.
939        let mut key = [0u8; 32];
940        key.copy_from_slice(&hash);
941
942        let iv = [0u8; 16];
943
944        let mut user_encrypted = file_encryption_key.to_vec();
945        let mut encryptor = Aes256CbcEnc::new(&key.into(), &iv.into());
946
947        for block in user_encrypted.chunks_exact_mut(16) {
948            encryptor.encrypt_block_mut(block.into());
949        }
950
951        Ok((user_value.to_vec(), user_encrypted))
952    }
953
954    /// Compute the encryption dictionary's O-entry value (revision 6).
955    ///
956    /// This implements Algorithm 9 as described in ISO 32000-2:2020 (PDF 2.0).
957    pub(crate) fn compute_hashed_owner_password_r6<K, O>(
958        &self, file_encryption_key: K, owner_password: O,
959    ) -> Result<(Vec<u8>, Vec<u8>), DecryptionError>
960    where
961        K: AsRef<[u8]>,
962        O: AsRef<[u8]>,
963    {
964        let file_encryption_key = file_encryption_key.as_ref();
965        let owner_password = owner_password.as_ref();
966
967        // Generate 16 random bytes of data using a strong random number generator. The first 8
968        // bytes are the owner validation salt. The second 8 bytes are the owner key salt. Compute
969        // the 32-byte hash using algorithm 2.B with an input string consisting of the UTF-8
970        // password concatenated with the owner validation salt and then concatenated with the
971        // 48-byte U string as generated in Algorithm 8. The 48-byte string consisting of the
972        // 32-byte hash followed by the owner validation salt followed by the owner key salt is
973        // stored as the O key.
974        let mut owner_value = [0u8; 48];
975        let mut rng = rand::rng();
976
977        rng.fill(&mut owner_value[32..]);
978
979        let owner_validation_salt = &owner_value[32..][..8];
980
981        let hashed_owner_password = self.compute_hash(owner_password, owner_validation_salt, Some(&self.user_value))?;
982        owner_value[..32].copy_from_slice(&hashed_owner_password);
983
984        // Compute the 32-byte hash using algorithm 2.B with an input string consisting of the
985        // UTF-8 password concatenated with the owner key salt.
986        let owner_key_salt = &owner_value[40..][..8];
987
988        let hash = self.compute_hash(owner_password, owner_key_salt, Some(&self.user_value))?;
989
990        // Using this hash as the key, encrypt the file encryption key using AES-256 in CBC mode
991        // with no padding and initialization vector of zero. The resulting 32-byte string is
992        // stored as the OE key.
993        let mut key = [0u8; 32];
994        key.copy_from_slice(&hash);
995
996        let iv = [0u8; 16];
997
998        let mut owner_encrypted = file_encryption_key.to_vec();
999        let mut encryptor = Aes256CbcEnc::new(&key.into(), &iv.into());
1000
1001        for block in owner_encrypted.chunks_exact_mut(16) {
1002            encryptor.encrypt_block_mut(block.into());
1003        }
1004
1005        Ok((owner_value.to_vec(), owner_encrypted))
1006    }
1007
1008    /// Compute the encryption dictionary's Perms (permissions) value (revision 6 and later).
1009    ///
1010    /// This implements Algorithm 10 as described in ISO 32000-2:2020 (PDF 2.0).
1011    pub(crate) fn compute_permissions<K>(&self, file_encryption_key: K) -> Result<Vec<u8>, DecryptionError>
1012    where
1013        K: AsRef<[u8]>,
1014    {
1015        let file_encryption_key = file_encryption_key.as_ref();
1016        let mut bytes = [0u8; 16];
1017
1018        // Record the 8 bytes of permission in the bytes 0-7 of the block, low order byte first.
1019        bytes[..8].copy_from_slice(&u64::to_le_bytes(self.permissions.bits()));
1020
1021        // Set byte 8 to ASCII character "T" or "F" according to the EncryptMetadata boolean.
1022        bytes[8] = if self.encrypt_metadata { b'T' } else { b'F' };
1023
1024        // Set bytes 9-11 to the ASCII characters "a", "d", "b".
1025        bytes[9..][..3].copy_from_slice(b"adb");
1026
1027        // Set bytes 12-15 to 4 bytes of random data, which will be ignored.
1028        let mut rng = rand::rng();
1029        rng.fill(&mut bytes[12..][..4]);
1030
1031        // Encrypt the 16-byte block using AES-256 in ECB mode with an initialization vector of
1032        // zero, using the file encryption key as the key.
1033        let mut key = [0u8; 32];
1034        key.copy_from_slice(file_encryption_key);
1035
1036        let mut encryptor = Aes256EbcEnc::new(&key.into());
1037
1038        for block in bytes.chunks_exact_mut(16) {
1039            encryptor.encrypt_block_mut(block.into());
1040        }
1041
1042        // The result (16 bytes) is stored as the Perms string, and checked for validity when the
1043        // file is opened.
1044        Ok(bytes.to_vec())
1045    }
1046
1047    /// Authenticate the user password (revision 6 and later).
1048    ///
1049    /// This implements Algorithm 11 as described in ISO 32000-2:2020 (PDF 2.0).
1050    fn authenticate_user_password_r6<U>(&self, user_password: U) -> Result<(), DecryptionError>
1051    where
1052        U: AsRef<[u8]>,
1053    {
1054        let mut user_password = user_password.as_ref();
1055
1056        let hashed_user_password = &self.user_value[0..][..32];
1057        let user_validation_salt = &self.user_value[32..][..8];
1058
1059        // Truncate the UTF-8 representation to 127 bytes if it is longer than 127 bytes.
1060        if user_password.len() > 127 {
1061            user_password = &user_password[..127];
1062        }
1063
1064        // Test the password against the user key by computing a hash using algorithm 2.B with an
1065        // input string consisting of the UTF-8 password concatenated with the 8 bytes of user
1066        // validation salt. If the 32-byte result matches the first 32-bytes of the U string, this
1067        // is the user password.
1068        let mut input = Vec::with_capacity(user_password.len() + user_validation_salt.len());
1069
1070        input.extend_from_slice(user_password);
1071        input.extend_from_slice(user_validation_salt);
1072
1073        if self.compute_hash(user_password, user_validation_salt, None)? != hashed_user_password {
1074            return Err(DecryptionError::IncorrectPassword);
1075        }
1076
1077        Ok(())
1078    }
1079
1080    /// Authenticate the owner password (revision 6 and later).
1081    ///
1082    /// This implements Algorithm 12 as described in ISO 32000-2:2020 (PDF 2.0).
1083    fn authenticate_owner_password_r6<O>(&self, owner_password: O) -> Result<(), DecryptionError>
1084    where
1085        O: AsRef<[u8]>,
1086    {
1087        let mut owner_password = owner_password.as_ref();
1088
1089        let hashed_owner_password = &self.owner_value[0..][..32];
1090        let owner_validation_salt = &self.owner_value[32..][..8];
1091
1092        // Truncate the UTF-8 representation to 127 bytes if it is longer than 127 bytes.
1093        if owner_password.len() > 127 {
1094            owner_password = &owner_password[..127];
1095        }
1096
1097        // Test the password against the owner key by computing a hash using algorithm 2.B with an
1098        // input string consisting of the UTF-8 password concatenated with the 8 bytes of owner
1099        // validation salt and the 48 byte U string. If the 32-byte result matches the first
1100        // 32-bytes of the O string, this is the owner password.
1101        let mut input = Vec::with_capacity(owner_password.len() + owner_validation_salt.len());
1102
1103        input.extend_from_slice(owner_password);
1104        input.extend_from_slice(owner_validation_salt);
1105
1106        if self.compute_hash(owner_password, owner_validation_salt, Some(&self.user_value))? != hashed_owner_password {
1107            return Err(DecryptionError::IncorrectPassword);
1108        }
1109
1110        Ok(())
1111    }
1112
1113    /// Validate the permissions (revision 6 and later).
1114    ///
1115    /// This implements Algorithm 13 as described in ISO 32000-2:2020 (PDF 2.0).
1116    fn validate_permissions<K>(&self, file_encryption_key: K) -> Result<(), DecryptionError>
1117    where
1118        K: AsRef<[u8]>,
1119    {
1120        let file_encryption_key = file_encryption_key.as_ref();
1121
1122        // Decrypt the 16 byte Perms string using AES-256 in ECB mode with an initialization vector
1123        // of zero and the file encryption key as the key.
1124        let mut bytes = [0u8; 16];
1125        bytes.copy_from_slice(&self.permission_encrypted);
1126
1127        let mut key = [0u8; 32];
1128        key.copy_from_slice(file_encryption_key);
1129
1130        let mut decryptor = Aes256EbcDec::new(&key.into());
1131
1132        for block in bytes.chunks_exact_mut(16) {
1133            decryptor.decrypt_block_mut(block.into());
1134        }
1135
1136        // Verify that bytes 9-11 of the result are the characters "a", "d", "b".
1137        if &bytes[9..][..3] != b"adb" {
1138            return Err(DecryptionError::IncorrectPassword);
1139        }
1140
1141        // Bytes 0-3 of the decrypted Perms entry, treated as a little-endian integer, are the
1142        // user permissions. They should match the value in the P key.
1143        if bytes[..3] != u64::to_le_bytes(self.permissions.bits())[..3] {
1144            return Err(DecryptionError::IncorrectPassword);
1145        }
1146
1147        // Byte 8 should match the ASCII character "T" or "F" according to the boolean value of the
1148        // EncryptMetadata key.
1149        if bytes[8] != if self.encrypt_metadata { b'T' } else { b'F' } {
1150            return Err(DecryptionError::IncorrectPassword);
1151        }
1152
1153        Ok(())
1154    }
1155
1156    /// Sanitize the password.
1157    pub fn sanitize_password(&self, password: &str) -> Result<Vec<u8>, DecryptionError> {
1158        match self.revision {
1159            2..=4 => self.sanitize_password_r4(password),
1160            5..=6 => self.sanitize_password_r6(password),
1161            _ => Err(DecryptionError::UnsupportedRevision),
1162        }
1163    }
1164
1165    /// Compute the file encryption key used to encrypt/decrypt the document.
1166    pub fn compute_file_encryption_key<P>(&self, doc: &Document, password: P) -> Result<Vec<u8>, DecryptionError>
1167    where
1168        P: AsRef<[u8]>,
1169    {
1170        match self.revision {
1171            2..=4 => self.compute_file_encryption_key_r4(doc, password),
1172            5..=6 => self.compute_file_encryption_key_r6(password),
1173            _ => Err(DecryptionError::UnsupportedRevision),
1174        }
1175    }
1176
1177    /// Authenticate the owner password.
1178    pub fn authenticate_user_password<U>(&self, doc: &Document, user_password: U) -> Result<(), DecryptionError>
1179    where
1180        U: AsRef<[u8]>,
1181    {
1182        match self.revision {
1183            2..=4 => self.authenticate_user_password_r4(doc, user_password),
1184            5..=6 => self.authenticate_user_password_r6(user_password),
1185            _ => Err(DecryptionError::UnsupportedRevision),
1186        }
1187    }
1188
1189    /// Authenticate the owner password.
1190    pub fn authenticate_owner_password<O>(&self, doc: &Document, owner_password: O) -> Result<(), DecryptionError>
1191    where
1192        O: AsRef<[u8]>,
1193    {
1194        match self.revision {
1195            2..=4 => self.authenticate_owner_password_r4(doc, owner_password),
1196            5..=6 => self.authenticate_owner_password_r6(owner_password),
1197            _ => Err(DecryptionError::UnsupportedRevision),
1198        }
1199    }
1200}
1201
1202#[cfg(test)]
1203mod tests {
1204    use crate::Permissions;
1205    use crate::creator::tests::create_document;
1206    use crate::encryption::PasswordAlgorithm;
1207    use rand::RngExt as _;
1208
1209    #[test]
1210    fn authenticate_password_r2() {
1211        let document = create_document();
1212
1213        let mut algorithm = PasswordAlgorithm {
1214            encrypt_metadata: true,
1215            length: None,
1216            version: 1,
1217            revision: 2,
1218            permissions: Permissions::all(),
1219            ..Default::default()
1220        };
1221
1222        let owner_password = "owner";
1223        let user_password = "user";
1224
1225        // Sanitize the passwords.
1226        let owner_password = algorithm.sanitize_password_r4(owner_password).unwrap();
1227        let user_password = algorithm.sanitize_password_r4(user_password).unwrap();
1228
1229        // Compute the hashed values.
1230        algorithm.owner_value = algorithm
1231            .compute_hashed_owner_password_r4(Some(&owner_password), &user_password)
1232            .unwrap();
1233
1234        algorithm.user_value = algorithm
1235            .compute_hashed_user_password_r2(&document, &user_password)
1236            .unwrap();
1237
1238        // Assert that the correct passwords authenticate.
1239        assert!(
1240            algorithm
1241                .authenticate_owner_password_r4(&document, &owner_password)
1242                .is_ok()
1243        );
1244        assert!(
1245            algorithm
1246                .authenticate_user_password_r4(&document, &user_password)
1247                .is_ok()
1248        );
1249
1250        // Assert that the swapped passwords do not authenticate.
1251        assert!(
1252            algorithm
1253                .authenticate_owner_password_r4(&document, user_password)
1254                .is_err()
1255        );
1256        assert!(
1257            algorithm
1258                .authenticate_user_password_r4(&document, owner_password)
1259                .is_err()
1260        );
1261    }
1262
1263    #[test]
1264    fn authenticate_password_r3() {
1265        let document = create_document();
1266
1267        let mut algorithm = PasswordAlgorithm {
1268            encrypt_metadata: true,
1269            length: Some(40),
1270            version: 2,
1271            revision: 3,
1272            permissions: Permissions::all(),
1273            ..Default::default()
1274        };
1275
1276        let owner_password = "owner";
1277        let user_password = "user";
1278
1279        // Sanitize the passwords.
1280        let owner_password = algorithm.sanitize_password_r4(owner_password).unwrap();
1281        let user_password = algorithm.sanitize_password_r4(user_password).unwrap();
1282
1283        // Compute the hashed values.
1284        algorithm.owner_value = algorithm
1285            .compute_hashed_owner_password_r4(Some(&owner_password), &user_password)
1286            .unwrap();
1287
1288        algorithm.user_value = algorithm
1289            .compute_hashed_user_password_r3_r4(&document, &user_password)
1290            .unwrap();
1291
1292        // Assert that the correct passwords authenticate.
1293        assert!(
1294            algorithm
1295                .authenticate_owner_password_r4(&document, &owner_password)
1296                .is_ok()
1297        );
1298        assert!(
1299            algorithm
1300                .authenticate_user_password_r4(&document, &user_password)
1301                .is_ok()
1302        );
1303
1304        // Assert that the swapped passwords do not authenticate.
1305        assert!(
1306            algorithm
1307                .authenticate_owner_password_r4(&document, user_password)
1308                .is_err()
1309        );
1310        assert!(
1311            algorithm
1312                .authenticate_user_password_r4(&document, owner_password)
1313                .is_err()
1314        );
1315    }
1316
1317    #[test]
1318    fn authenticate_password_r4() {
1319        let document = create_document();
1320
1321        let mut algorithm = PasswordAlgorithm {
1322            encrypt_metadata: true,
1323            length: Some(128),
1324            version: 4,
1325            revision: 4,
1326            permissions: Permissions::all(),
1327            ..Default::default()
1328        };
1329
1330        let owner_password = "owner";
1331        let user_password = "user";
1332
1333        // Sanitize the passwords.
1334        let owner_password = algorithm.sanitize_password_r4(owner_password).unwrap();
1335        let user_password = algorithm.sanitize_password_r4(user_password).unwrap();
1336
1337        // Compute the hashed values.
1338        algorithm.owner_value = algorithm
1339            .compute_hashed_owner_password_r4(Some(&owner_password), &user_password)
1340            .unwrap();
1341
1342        algorithm.user_value = algorithm
1343            .compute_hashed_user_password_r3_r4(&document, &user_password)
1344            .unwrap();
1345
1346        // Assert that the correct passwords authenticate.
1347        assert!(
1348            algorithm
1349                .authenticate_owner_password_r4(&document, &owner_password)
1350                .is_ok()
1351        );
1352        assert!(
1353            algorithm
1354                .authenticate_user_password_r4(&document, &user_password)
1355                .is_ok()
1356        );
1357
1358        // Assert that the swapped passwords do not authenticate.
1359        assert!(
1360            algorithm
1361                .authenticate_owner_password_r4(&document, user_password)
1362                .is_err()
1363        );
1364        assert!(
1365            algorithm
1366                .authenticate_user_password_r4(&document, owner_password)
1367                .is_err()
1368        );
1369    }
1370
1371    #[test]
1372    fn authenticate_password_r5() {
1373        let mut algorithm = PasswordAlgorithm {
1374            encrypt_metadata: true,
1375            version: 5,
1376            revision: 5,
1377            permissions: Permissions::all(),
1378            ..Default::default()
1379        };
1380
1381        let owner_password = "owner";
1382        let user_password = "user";
1383
1384        // Sanitize the passwords.
1385        let owner_password = algorithm.sanitize_password_r6(owner_password).unwrap();
1386        let user_password = algorithm.sanitize_password_r6(user_password).unwrap();
1387
1388        // Compute the hashed values.
1389        let mut file_encryption_key = [0u8; 32];
1390
1391        let mut rng = rand::rng();
1392        rng.fill(&mut file_encryption_key);
1393
1394        let (user_value, user_encrypted) = algorithm
1395            .compute_hashed_user_password_r6(file_encryption_key, &user_password)
1396            .unwrap();
1397
1398        algorithm.user_value = user_value;
1399        algorithm.user_encrypted = user_encrypted;
1400
1401        let (owner_value, owner_encrypted) = algorithm
1402            .compute_hashed_owner_password_r6(file_encryption_key, &owner_password)
1403            .unwrap();
1404
1405        algorithm.owner_value = owner_value;
1406        algorithm.owner_encrypted = owner_encrypted;
1407
1408        algorithm.permission_encrypted = algorithm.compute_permissions(file_encryption_key).unwrap();
1409
1410        // Assert that the correct passwords authenticate.
1411        assert!(algorithm.authenticate_owner_password_r6(&owner_password).is_ok());
1412        assert!(algorithm.authenticate_user_password_r6(&user_password).is_ok());
1413
1414        // Assert that the swapped passwords do not authenticate.
1415        assert!(algorithm.authenticate_owner_password_r6(&user_password).is_err());
1416        assert!(algorithm.authenticate_user_password_r6(&owner_password).is_err());
1417
1418        // Assert that the permissions validate correctly.
1419        assert!(algorithm.validate_permissions(file_encryption_key).is_ok());
1420
1421        // Assert that the file encryption key is equal for the owner password.
1422        let key = algorithm.compute_file_encryption_key_r6(&owner_password).unwrap();
1423        assert_eq!(&file_encryption_key[..], key);
1424
1425        // Assert that the file encryption key is equal for the user password.
1426        let key = algorithm.compute_file_encryption_key_r6(&user_password).unwrap();
1427        assert_eq!(&file_encryption_key[..], key);
1428    }
1429
1430    #[test]
1431    fn authenticate_password_r6() {
1432        let mut algorithm = PasswordAlgorithm {
1433            encrypt_metadata: true,
1434            version: 5,
1435            revision: 6,
1436            permissions: Permissions::all(),
1437            ..Default::default()
1438        };
1439
1440        let owner_password = "owner";
1441        let user_password = "user";
1442
1443        // Sanitize the passwords.
1444        let owner_password = algorithm.sanitize_password_r6(owner_password).unwrap();
1445        let user_password = algorithm.sanitize_password_r6(user_password).unwrap();
1446
1447        // Compute the hashed values.
1448        let mut file_encryption_key = [0u8; 32];
1449
1450        let mut rng = rand::rng();
1451        rng.fill(&mut file_encryption_key);
1452
1453        let (user_value, user_encrypted) = algorithm
1454            .compute_hashed_user_password_r6(file_encryption_key, &user_password)
1455            .unwrap();
1456
1457        algorithm.user_value = user_value;
1458        algorithm.user_encrypted = user_encrypted;
1459
1460        let (owner_value, owner_encrypted) = algorithm
1461            .compute_hashed_owner_password_r6(file_encryption_key, &owner_password)
1462            .unwrap();
1463
1464        algorithm.owner_value = owner_value;
1465        algorithm.owner_encrypted = owner_encrypted;
1466
1467        algorithm.permission_encrypted = algorithm.compute_permissions(file_encryption_key).unwrap();
1468
1469        // Assert that the correct passwords authenticate.
1470        assert!(algorithm.authenticate_owner_password_r6(&owner_password).is_ok());
1471        assert!(algorithm.authenticate_user_password_r6(&user_password).is_ok());
1472
1473        // Assert that the swapped passwords do not authenticate.
1474        assert!(algorithm.authenticate_owner_password_r6(&user_password).is_err());
1475        assert!(algorithm.authenticate_user_password_r6(&owner_password).is_err());
1476
1477        // Assert that the permissions validate correctly.
1478        assert!(algorithm.validate_permissions(file_encryption_key).is_ok());
1479
1480        // Assert that the file encryption key is equal for the owner password.
1481        let key = algorithm.compute_file_encryption_key_r6(&owner_password).unwrap();
1482        assert_eq!(&file_encryption_key[..], key);
1483
1484        // Assert that the file encryption key is equal for the user password.
1485        let key = algorithm.compute_file_encryption_key_r6(&user_password).unwrap();
1486        assert_eq!(&file_encryption_key[..], key);
1487    }
1488
1489    /// Some PDF writers (e.g. Adobe) pad /O and /U to 127 bytes with trailing
1490    /// zeros instead of the spec-required 48. Verify that `try_from` accepts
1491    /// these and truncates to the correct 48-byte length.
1492    #[test]
1493    fn r6_padded_owner_user_values_accepted() {
1494        use crate::{Document, Object, StringFormat, dictionary};
1495
1496        let mut doc = Document::with_version("2.0");
1497
1498        // Build valid 48-byte /O and /U (contents don't matter for parsing).
1499        let o_48 = vec![0xAAu8; 48];
1500        let u_48 = vec![0xBBu8; 48];
1501
1502        // Pad to 127 bytes with trailing zeros — mimics real-world Adobe PDFs.
1503        let mut o_127 = o_48.clone();
1504        o_127.resize(127, 0u8);
1505        let mut u_127 = u_48.clone();
1506        u_127.resize(127, 0u8);
1507
1508        let encrypt_dict = dictionary! {
1509            "Filter" => "Standard",
1510            "V" => Object::Integer(5),
1511            "R" => Object::Integer(6),
1512            "Length" => Object::Integer(256),
1513            "O" => Object::String(o_127, StringFormat::Literal),
1514            "OE" => Object::String(vec![0xCCu8; 32], StringFormat::Literal),
1515            "U" => Object::String(u_127, StringFormat::Literal),
1516            "UE" => Object::String(vec![0xDDu8; 32], StringFormat::Literal),
1517            "P" => Object::Integer(-3388),
1518            "Perms" => Object::String(vec![0xEEu8; 16], StringFormat::Literal)
1519        };
1520
1521        let encrypt_id = doc.add_object(encrypt_dict);
1522        doc.trailer.set("Encrypt", Object::Reference(encrypt_id));
1523
1524        let algo = PasswordAlgorithm::try_from(&doc).expect("should accept padded /O and /U longer than 48 bytes");
1525
1526        // Verify the values were truncated to the spec-required 48 bytes.
1527        assert_eq!(algo.owner_value.len(), 48);
1528        assert_eq!(algo.user_value.len(), 48);
1529        assert_eq!(&algo.owner_value, &o_48);
1530        assert_eq!(&algo.user_value, &u_48);
1531    }
1532
1533    /// Verify that /O and /U values shorter than 48 bytes are still rejected
1534    /// for R >= 5.
1535    #[test]
1536    fn r6_short_owner_user_values_rejected() {
1537        use crate::{Document, Object, StringFormat, dictionary};
1538
1539        let mut doc = Document::with_version("2.0");
1540
1541        let encrypt_dict = dictionary! {
1542            "Filter" => "Standard",
1543            "V" => Object::Integer(5),
1544            "R" => Object::Integer(6),
1545            "Length" => Object::Integer(256),
1546            "O" => Object::String(vec![0xAAu8; 47], StringFormat::Literal),
1547            "OE" => Object::String(vec![0xCCu8; 32], StringFormat::Literal),
1548            "U" => Object::String(vec![0xBBu8; 48], StringFormat::Literal),
1549            "UE" => Object::String(vec![0xDDu8; 32], StringFormat::Literal),
1550            "P" => Object::Integer(-3388),
1551            "Perms" => Object::String(vec![0xEEu8; 16], StringFormat::Literal)
1552        };
1553
1554        let encrypt_id = doc.add_object(encrypt_dict);
1555        doc.trailer.set("Encrypt", Object::Reference(encrypt_id));
1556
1557        assert!(
1558            PasswordAlgorithm::try_from(&doc).is_err(),
1559            "should reject /O shorter than 48 bytes"
1560        );
1561    }
1562}