lopdf/encryption/
algorithms.rs

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