Skip to main content

pdfluent_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::Rng 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,
22    0x2E, 0x2E, 0x00, 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 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        if revision >= 5 && owner_value.len() != 48 {
158            return Err(DecryptionError::InvalidHashLength)?;
159        }
160
161        let owner_encrypted = encrypted
162            .get(b"OE")
163            .and_then(Object::as_str)
164            .map(|s| s.to_vec())
165            .ok()
166            .unwrap_or_default();
167
168        // The owner encrypted blob is required if R is 5 or greater and the blob shall be 32 bytes
169        // long.
170        if revision >= 5 && owner_encrypted.len() != 32 {
171            return Err(DecryptionError::InvalidCipherTextLength)?;
172        }
173
174        // Get the user value and user encrypted blobs.
175        let user_value = encrypted
176            .get(b"U")
177            .map_err(|_| DecryptionError::MissingUserPassword)?
178            .as_str()
179            .map_err(|_| DecryptionError::InvalidType)?
180            .to_vec();
181
182        // The user value is 32 bytes long if the value of R is 4 or less.
183        if revision <= 4 && user_value.len() != 32 {
184            return Err(DecryptionError::InvalidHashLength)?;
185        }
186
187        // The user value is 48 bytes long if the value of R is 5 or greater.
188        if revision >= 5 && user_value.len() != 48 {
189            return Err(DecryptionError::InvalidHashLength)?;
190        }
191
192        let user_encrypted = encrypted
193            .get(b"UE")
194            .and_then(Object::as_str)
195            .map(|s| s.to_vec())
196            .ok()
197            .unwrap_or_default();
198
199        // The user encrypted blob is required if R is 5 or greater and the blob shall be 32 bytes
200        // long.
201        if revision >= 5 && user_encrypted.len() != 32 {
202            return Err(DecryptionError::InvalidCipherTextLength)?;
203        }
204
205        // Get the permission value and permission encrypted blobs.
206        let permission_value = encrypted
207            .get(b"P")
208            .map_err(|_| DecryptionError::MissingPermissions)?
209            .as_i64()
210            .map_err(|_| DecryptionError::InvalidType)? as u64;
211
212        let permissions = Permissions::from_bits_retain(permission_value);
213
214        let permission_encrypted = encrypted
215            .get(b"Perms")
216            .and_then(Object::as_str)
217            .map(|s| s.to_vec())
218            .ok()
219            .unwrap_or_default();
220
221        // The permission encrypted blob is required if R is 65 or greater and the blob shall be
222        // 16 bytes long.
223        if revision >= 5 && permission_encrypted.len() != 16 {
224            return Err(DecryptionError::InvalidCipherTextLength)?;
225        }
226
227        Ok(Self {
228            encrypt_metadata,
229            length,
230            version,
231            revision,
232            owner_value,
233            owner_encrypted,
234            user_value,
235            user_encrypted,
236            permissions,
237            permission_encrypted,
238        })
239    }
240}
241
242impl PasswordAlgorithm {
243    /// Sanitize the password (revision 4 and earlier).
244    ///
245    /// This implements the first step of Algorithm 2 as described in ISO 32000-2:2020 (PDF 2.0).
246    ///
247    /// This algorithm is deprecated in PDF 2.0.
248    pub(crate) fn sanitize_password_r4(&self, password: &str) -> Result<Vec<u8>, DecryptionError> {
249        // The password string is generated from host system codepage characters (or system scripts) by
250        // first converting the string to PDFDocEncoding. If the input is Unicode, first convert to a
251        // codepage encoding, and then to PDFDocEncoding for backward compatibility.
252        let password = encodings::string_to_bytes(&encodings::PDF_DOC_ENCODING, password);
253
254        Ok(password)
255    }
256
257    /// Compute a file encryption key in order to encrypt/decrypt a document (revision 4 and
258    /// earlier).
259    ///
260    /// This implements Algorithm 2 as described in ISO 32000-2:2020 (PDF 2.0).
261    ///
262    /// This algorithm is deprecated in PDF 2.0.
263    pub(crate) fn compute_file_encryption_key_r4<P>(
264        &self,
265        doc: &Document,
266        password: P,
267    ) -> Result<Vec<u8>, DecryptionError>
268    where
269        P: AsRef<[u8]>,
270    {
271        let password = password.as_ref();
272
273        // Pad or truncate the resulting password string to exactly 32 bytes. If the password string is
274        // more than 32 bytes long, use only its first 32 bytes; if it is less than 32 bytes long, pad
275        // it by appending the required number of additional bytes from the beginning of the following
276        // padding string (see `PAD_BYTES`).
277        //
278        // That is, if the password is n bytes long, append the first 32 - n bytes of the padding
279        // string to the end of the password string. If the password string is empty (zero-length),
280        // meaning there is no user password, substitute the entire padding string in its place.
281        //
282        // i.e., we will simply calculate `len = min(password length, 32)` and use the first len bytes
283        // of password and the first len bytes of `PAD_BYTES`.
284        let len = password.len().min(32);
285
286        // Initialize the MD5 hash function and pass the result as input to this function.
287        let mut hasher = Md5::new();
288
289        hasher.update(&password[..len]);
290        hasher.update(&PAD_BYTES[..32 - len]);
291
292        // Pass the value of the encryption dictionary's O entry (owner password hash) to the MD5 hash
293        // function.
294        hasher.update(&self.owner_value);
295
296        // Convert the integer value of the P entry (permissions) to a 32-bit unsigned binary number
297        // and pass these bytes to the MD5 hash function, low-order byte first.
298        //
299        // We don't actually care about the permissions, but we need the correct value to derive the
300        // correct key.
301        hasher.update((self.permissions.bits() as u32).to_le_bytes());
302
303        // Pass the first element of the file's file identifier array (the value of the ID entry in the
304        // document's trailer dictionary to the MD5 hash function.
305        let file_id_0 = doc
306            .trailer
307            .get(b"ID")
308            .map_err(|_| DecryptionError::MissingFileID)?
309            .as_array()
310            .map_err(|_| DecryptionError::InvalidType)?
311            .first()
312            .ok_or(DecryptionError::InvalidType)?
313            .as_str()
314            .map_err(|_| DecryptionError::InvalidType)?;
315        hasher.update(file_id_0);
316
317        // (Security handlers of revision 4 or greater) If document metadata is not being encrypted,
318        // pass 4 bytes with the value 0xFFFFFFFF to the MD5 hash function.
319        if self.revision >= 4 && !self.encrypt_metadata {
320            hasher.update(b"\xff\xff\xff\xff");
321        }
322
323        // Finish the hash.
324        let mut hash = hasher.finalize();
325
326        // (Security handlers of revision 3 or greater) Do the following 50 times: take the output from
327        // the previous MD5 hash and pass the first n bytes of the output as input into a new MD5 hash,
328        // where n is the number of bytes of the file encryption key as defined by the value of the
329        // encryption dictionary's Length entry.
330        let n = if self.revision >= 3 {
331            self.length.unwrap_or(40) / 8
332        } else {
333            5
334        };
335
336        // The maximum supported key length is 16 bytes (128 bits) due to the use of MD5.
337        if n > 16 {
338            return Err(DecryptionError::InvalidKeyLength);
339        }
340
341        if self.revision >= 3 {
342            for _ in 0..50 {
343                hash = Md5::digest(&hash[..n]);
344            }
345        }
346
347        // Set the file encryption key to the first n bytes of the output from the final MD5 hash,
348        // where n shall always be 5 for security handlers of revision 2 but, for security handlers of
349        // revision 3 or greater, shall depend on the value of the encrpytion dictionary's Length
350        // entry.
351        Ok(hash[..n].to_vec())
352    }
353
354    /// Sanitize the password (revision 6 and later).
355    ///
356    /// This implements the first step of Algorithm 2.A as described in ISO 32000-2:2020 (PDF 2.0).
357    pub(crate) fn sanitize_password_r6(&self, password: &str) -> Result<Vec<u8>, DecryptionError> {
358        // The UTF-8 password string shall be generated from Unicode input by processing the input
359        // with the SASLprep (Internet RFC 4013) profile of stringprep (Internet RFC 3454) using
360        // the Normalize and BiDi options, and then coverting to a UTF-8 representation.
361        Ok(stringprep::saslprep(password)?.as_bytes().to_vec())
362    }
363
364    /// Compute a file encryption key in order to encrypt/decrypt a document (revision 6 and
365    /// later).
366    ///
367    /// This implements Algorithm 2.A as described in ISO 32000-2:2020 (PDF 2.0).
368    fn compute_file_encryption_key_r6<P>(&self, password: P) -> 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))?
392            == hashed_owner_password
393        {
394            // Compute an intermediate owner key by computing a hash using algorithm 2.B with an
395            // input string consisting of the UTF-8 owner password concatenated with the 8 bytes of
396            // owner key salt, concatenated with the 48-byte U string.
397            let hash = self.compute_hash(password, owner_key_salt, Some(&self.user_value))?;
398
399            let mut key = [0u8; 32];
400            key.copy_from_slice(&hash);
401
402            // The 32-byte result is the key used to decrypt the 32-byte OE string using AES-256 in
403            // CBC mode with no padding and an initialization vector of zero. The 32-byte result is
404            // the file encryption key.
405            let iv = [0u8; 16];
406
407            let mut owner_encrypted = self.owner_encrypted.clone();
408            let mut decryptor = Aes256CbcDec::new(&key.into(), &iv.into());
409
410            for block in owner_encrypted.chunks_exact_mut(16) {
411                decryptor.decrypt_block_mut(block.into());
412            }
413
414            return Ok(owner_encrypted);
415        }
416
417        // Note: this step is not in the specification, but is a precaution.
418        //
419        // Test the password against the user key by computing a hash using algorithm 2.B with an
420        // input string consisting of the UTF-8 password concatenated with the 8 bytes of user
421        // validation salt. If the 32-byte result matches the first 32-bytes of the U string, this
422        // is the user password.
423
424        if self.compute_hash(password, user_validation_salt, None)? == hashed_user_password {
425            // Compute an intermediate user key by computing a hash using algorithm 2.B with an
426            // input string consisting of the UTF-8 owner password concatenated with the 8 bytes of
427            // user key salt.
428            let hash = self.compute_hash(password, user_key_salt, None)?;
429
430            let mut key = [0u8; 32];
431            key.copy_from_slice(&hash);
432
433            // The 32-byte result is the key used to decrypt the 32-byte UE string using AES-256 in
434            // CBC mode with no padding and an initialization vector of zero. The 32-byte result is
435            // the file encryption key.
436            let iv = [0u8; 16];
437            let mut user_encrypted = self.user_encrypted.clone();
438            let mut decryptor = Aes256CbcDec::new(&key.into(), &iv.into());
439
440            for block in user_encrypted.chunks_exact_mut(16) {
441                decryptor.decrypt_block_mut(block.into());
442            }
443
444            // Decrypt the 16-byte Perms string using AES-256 in EBC mode with an initialization
445            // vector of zero and the file encryption key as the key. Verify that bytes 9-11 of the
446            // result are the characters "a", "d", "b". Bytes 0-3 of the decrypted Perms entry,
447            // treated as a little-endian integer, are the user permissions. They shall match the
448            // value in the P key.
449            //
450            // i.e., use algorithm 13 to validate the permissions.
451            self.validate_permissions(&user_encrypted)?;
452
453            return Ok(user_encrypted);
454        }
455
456        Err(DecryptionError::IncorrectPassword)
457    }
458
459    /// Compute a hash (revision 6 and later).
460    ///
461    /// This implements Algorithm 2.B as described in ISO 32000-2:2020 (PDF 2.0).
462    fn compute_hash<P, S>(
463        &self,
464        password: P,
465        salt: S,
466        user_key: Option<&[u8]>,
467    ) -> Result<Vec<u8>, DecryptionError>
468    where
469        P: AsRef<[u8]>,
470        S: AsRef<[u8]>,
471    {
472        let password = password.as_ref();
473        let salt = salt.as_ref();
474
475        // Take the SHA-256 hash of the original input to the algorithm and name the resulting 32
476        // bytes, K.
477        let mut hasher = Sha256::new();
478
479        hasher.update(password);
480        hasher.update(salt);
481
482        if let Some(user_key) = user_key {
483            hasher.update(user_key);
484        }
485
486        let mut k = hasher.finalize().to_vec();
487
488        // Revision 5 uses a simplified hash algorithm that simply calculates the SHA-256 hash of
489        // the original input to the algorithm.
490        if self.revision == 5 {
491            return Ok(k);
492        }
493
494        let mut k1 = Vec::with_capacity(
495            64 * (password.len() + 64 + user_key.map(|user_key| user_key.len()).unwrap_or(0)),
496        );
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
504            //   concatenation of the input 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,
576        owner_password: Option<O>,
577        user_password: U,
578    ) -> Result<Vec<u8>, DecryptionError>
579    where
580        O: AsRef<[u8]>,
581        U: AsRef<[u8]>,
582    {
583        let user_password = user_password.as_ref();
584
585        // Pad or truncate the owner string. If there is no owner password, use the user password
586        // instead.
587        let password = owner_password
588            .as_ref()
589            .map(|password| password.as_ref())
590            .unwrap_or(user_password);
591
592        // Pad or truncate the resulting password string to exactly 32 bytes. If the password string is
593        // more than 32 bytes long, use only its first 32 bytes; if it is less than 32 bytes long, pad
594        // it by appending the required number of additional bytes from the beginning of the following
595        // padding string (see `PAD_BYTES`).
596        //
597        // That is, if the password is n bytes long, append the first 32 - n bytes of the padding
598        // string to the end of the password string. If the password string is empty (zero-length),
599        // meaning there is no user password, substitute the entire padding string in its place.
600        //
601        // i.e., we will simply calculate `len = min(password length, 32)` and use the first len bytes
602        // of password and the first len bytes of `PAD_BYTES`.
603        let len = password.len().min(32);
604
605        // Initialize the MD5 hash function and pass the result as input to this function.
606        let mut hasher = Md5::new();
607
608        hasher.update(&password[..len]);
609        hasher.update(&PAD_BYTES[..32 - len]);
610
611        let mut hash = hasher.finalize();
612
613        // (Security handlers of revision 3 or greater) Do the following 50 times: take the output from
614        // the previous MD5 hash and pass it as input into a new MD5 hash.
615        if self.revision >= 3 {
616            for _ in 0..50 {
617                hash = Md5::digest(hash);
618            }
619        }
620
621        // Create an RC4 file encryption key using the first n bytes of the output from the final MD5
622        // hash, where n shall always be 5 for security handlers of revision 2 but, for security
623        // handlers of revision 3 or greater, shall depend on the value of the encryption dictionary's
624        // Length entry.
625        let n = if self.revision >= 3 {
626            self.length.unwrap_or(40) / 8
627        } else {
628            5
629        };
630
631        // The maximum supported key length is 16 bytes (128 bits) due to the use of MD5.
632        if n > 16 {
633            return Err(DecryptionError::InvalidKeyLength);
634        }
635
636        // Pad or truncate the user password string to exactly 32 bytes. If the user password string is
637        // more than 32 bytes long, use only its first 32 bytes; if it is less than 32 bytes long, pad
638        // it by appending the required number of additional bytes from the beginning of the following
639        // padding string (see `PAD_BYTES`).
640        //
641        // That is, if the password is n bytes long, append the first 32 - n bytes of the padding
642        // string to the end of the password string. If the password string is empty (zero-length),
643        // meaning there is no user password, substitute the entire padding string in its place.
644        //
645        // i.e., we will simply calculate `len = min(password length, 32)` and use the first len bytes
646        // of password and the first len bytes of `PAD_BYTES`.
647        let len = user_password.len().min(32);
648
649        // Encrypt the result of the previous step using an RC4 encryption function with the RC4 file
650        // encryption key obtained in the step before the previous step.
651        let mut bytes = [0u8; 32];
652
653        bytes[..len].copy_from_slice(&user_password[..len]);
654        bytes[len..].copy_from_slice(&PAD_BYTES[..32 - len]);
655
656        let mut result = Rc4::new(&hash[..n]).encrypt(bytes);
657
658        // (Security handlers of revision 3 or greater) Do the following 19 times: Take the output from
659        // the previous invocation of the RC4 function and pass it as input to a new invocation of the
660        // function; use a file encryption key generated by taking each byte of the RC4 file encryption
661        // key and performing an XOR (exclusive or) operation between that byte and the single-byte
662        // value of the iteration counter (from 1 to 19).
663        if self.revision >= 3 {
664            let mut key = vec![0u8; n];
665
666            for i in 1..=19 {
667                for (in_byte, out_byte) in hash[..n].iter().zip(key.iter_mut()) {
668                    *out_byte = in_byte ^ i;
669                }
670
671                result = Rc4::new(&key).encrypt(&result);
672            }
673        }
674
675        // Store the output from the final invocation of the RC4 function as the value of the O entry
676        // in the encryption dictionary.
677        Ok(result)
678    }
679
680    /// Compute the encryption dictionary's U-entry value (revision 2).
681    ///
682    /// This implements Algorithm 4 as described in ISO 32000-2:2020 (PDF 2.0).
683    ///
684    /// This algorithm is deprecated in PDF 2.0.
685    pub(crate) fn compute_hashed_user_password_r2<U>(
686        &self,
687        doc: &Document,
688        user_password: U,
689    ) -> Result<Vec<u8>, DecryptionError>
690    where
691        U: AsRef<[u8]>,
692    {
693        // Create a file encryption key based on the user password string.
694        let file_encryption_key = self.compute_file_encryption_key_r4(doc, user_password)?;
695
696        // Encrypt the 32-byte padding string using an RC4 encryption function with the file encryption
697        // key from the preceding step.
698        let result = Rc4::new(&file_encryption_key).encrypt(PAD_BYTES);
699
700        // Store the result of the previous step as the value of the U entry in the encryption dictionary.
701        Ok(result)
702    }
703
704    /// Compute the encryption dictionary's U-entry value (revision 3 or 4).
705    ///
706    /// This implements Algorithm 5 as described in ISO 32000-2:2020 (PDF 2.0).
707    ///
708    /// This algorithm is deprecated in PDF 2.0.
709    pub(crate) fn compute_hashed_user_password_r3_r4<U>(
710        &self,
711        doc: &Document,
712        user_password: U,
713    ) -> Result<Vec<u8>, DecryptionError>
714    where
715        U: AsRef<[u8]>,
716    {
717        // Create a file encryption key based on the user password string.
718        let file_encryption_key = self.compute_file_encryption_key_r4(doc, user_password)?;
719
720        // Initialize the MD5 hash function and pass the 32-byte padding string.
721        let mut hasher = Md5::new();
722
723        hasher.update(PAD_BYTES);
724
725        // Pass the first element of the file's file identifier array (the value of the ID entry in the
726        // document's trailer dictionary) to the hash function and finish the hash.
727        let file_id_0 = doc
728            .trailer
729            .get(b"ID")
730            .map_err(|_| DecryptionError::MissingFileID)?
731            .as_array()
732            .map_err(|_| DecryptionError::InvalidType)?
733            .first()
734            .ok_or(DecryptionError::InvalidType)?
735            .as_str()
736            .map_err(|_| DecryptionError::InvalidType)?;
737        hasher.update(file_id_0);
738
739        let hash = hasher.finalize();
740
741        // Encrypt the 16-byte result of the hash, using an RC4 encryption function with the file
742        // encryption key.
743        let mut result = Rc4::new(&file_encryption_key).encrypt(hash);
744
745        // Do the following 19 times: Take the output from the previous invocation of the RC4 function
746        // and pass it as input to a new invocation of the function; use a file encryption key
747        // generated by taking each byte of the RC4 file encryption key and performing an XOR
748        // (exclusive or) operation between that byte and the single-byte value of the iteration
749        // counter (from 1 to 19).
750        let mut key = vec![0u8; file_encryption_key.len()];
751
752        for i in 1..=19 {
753            for (in_byte, out_byte) in file_encryption_key.iter().zip(key.iter_mut()) {
754                *out_byte = in_byte ^ i;
755            }
756
757            result = Rc4::new(&key).encrypt(&result);
758        }
759
760        // Append 16 bytes of arbitrary padding to the output from the final invocation of the RC4
761        // function and store the 32-byte result as the value of the U entry in the encryption
762        // dictionary.
763        result.resize(32, 0);
764
765        let mut rng = rand::rng();
766        rng.fill(&mut result[16..]);
767
768        Ok(result)
769    }
770
771    /// Authenticate the user password (revision 4 and earlier).
772    ///
773    /// This implements Algorithm 6 as described in ISO 32000-2:2020 (PDF 2.0).
774    ///
775    /// This algorithm is deprecated in PDF 2.0.
776    fn authenticate_user_password_r4<U>(
777        &self,
778        doc: &Document,
779        user_password: U,
780    ) -> Result<(), DecryptionError>
781    where
782        U: AsRef<[u8]>,
783    {
784        // Perform all but the last step of Algorithm 4 (security handlers of revision 2) or Algorithm
785        // 5 (security handlers of revision 3 or 4) using the supplied password string to compute the
786        // encryption dictionary's U-entry value.
787        let hashed_user_password = match self.revision {
788            2 => self.compute_hashed_user_password_r2(doc, &user_password)?,
789            3 | 4 => self.compute_hashed_user_password_r3_r4(doc, &user_password)?,
790            _ => return Err(DecryptionError::InvalidRevision),
791        };
792
793        // If the result of the previous step is equal to the value of the encryption dictionary's U
794        // entry (comparing on the first 16 bytes in the case of security handlers of revision 3 or
795        // greater), the password supplied is the correct user password.
796        let len = match self.revision {
797            3 | 4 => 16,
798            _ => hashed_user_password.len(),
799        };
800
801        if self.user_value.len() < len {
802            return Err(DecryptionError::InvalidHashLength);
803        }
804
805        if hashed_user_password[..len] != self.user_value[..len] {
806            return Err(DecryptionError::IncorrectPassword);
807        }
808
809        Ok(())
810    }
811
812    /// Authenticate the owner password (revision 4 and earlier).
813    ///
814    /// This implements Algorithm 7 as described in ISO 32000-2:2020 (PDF 2.0).
815    ///
816    /// This algorithm is deprecated in PDF 2.0.
817    fn authenticate_owner_password_r4<O>(
818        &self,
819        doc: &Document,
820        owner_password: O,
821    ) -> Result<(), DecryptionError>
822    where
823        O: AsRef<[u8]>,
824    {
825        // Pad or truncate the owner string. If there is no owner password, use the user password
826        // instead.
827        let password = owner_password.as_ref();
828
829        // Pad or truncate the resulting password string to exactly 32 bytes. If the password string is
830        // more than 32 bytes long, use only its first 32 bytes; if it is less than 32 bytes long, pad
831        // it by appending the required number of additional bytes from the beginning of the following
832        // padding string (see `PAD_BYTES`).
833        //
834        // That is, if the password is n bytes long, append the first 32 - n bytes of the padding
835        // string to the end of the password string. If the password string is empty (zero-length),
836        // meaning there is no user password, substitute the entire padding string in its place.
837        //
838        // i.e., we will simply calculate `len = min(password length, 32)` and use the first len bytes
839        // of password and the first len bytes of `PAD_BYTES`.
840        let len = password.len().min(32);
841
842        // Initialize the MD5 hash function and pass the result as input to this function.
843        let mut hasher = Md5::new();
844
845        hasher.update(&password[..len]);
846        hasher.update(&PAD_BYTES[..32 - len]);
847
848        let mut hash = hasher.finalize();
849
850        // (Security handlers of revision 3 or greater) Do the following 50 times: take the output from
851        // the previous MD5 hash and pass it as input into a new MD5 hash.
852        if self.revision >= 3 {
853            for _ in 0..50 {
854                hash = Md5::digest(hash);
855            }
856        }
857
858        // Create an RC4 file encryption key using the first n bytes of the output from the final MD5
859        // hash, where n shall always be 5 for security handlers of revision 2 but, for security
860        // handlers of revision 3 or greater, shall depend on the value of the encryption dictionary's
861        // Length entry.
862        let n = if self.revision >= 3 {
863            self.length.unwrap_or(40) / 8
864        } else {
865            5
866        };
867
868        // The maximum supported key length is 16 bytes (128 bits) due to the use of MD5.
869        if n > 16 {
870            return Err(DecryptionError::InvalidKeyLength);
871        }
872
873        // Decrypt the value of the encryption dictionary's O entry, using an RC4 encryption function
874        // with the file encryption key to retrieve the user password.
875        let mut result = self.owner_value.to_vec();
876
877        // (Security handlers of revision 3 or greater) Do the following 19 times: Take the output from
878        // the previous invocation of the RC4 function and pass it as input to a new invocation of the
879        // function; use a file encryption key generated by taking each byte of the RC4 file encryption
880        // key and performing an XOR (exclusive or) operation between that byte and the single-byte
881        // value of the iteration counter (from 19 to 1).
882        if self.revision >= 3 {
883            let mut key = vec![0u8; n];
884
885            for i in (1..=19).rev() {
886                for (in_byte, out_byte) in hash[..n].iter().zip(key.iter_mut()) {
887                    *out_byte = in_byte ^ i;
888                }
889
890                result = Rc4::new(&key).decrypt(&result);
891            }
892        }
893
894        // (Security handler of revision 2 and the final step for revision 3 or greater) Decrypt the
895        // value of the encryption dictionary's O entry, using an RC4 encryption function with the file
896        // encryption key.
897        result = Rc4::new(&hash[..n]).decrypt(&result);
898
899        // The result of the previous step purports to be the user password. Authenticate this user
900        // password using Algorithm 5. If it is correct, the password supplied is the correct owner
901        // password.
902        self.authenticate_user_password_r4(doc, &result)
903    }
904
905    /// Compute the encryption dictionary's U-entry value (revision 6).
906    ///
907    /// This implements Algorithm 8 as described in ISO 32000-2:2020 (PDF 2.0).
908    pub(crate) fn compute_hashed_user_password_r6<K, U>(
909        &self,
910        file_encryption_key: K,
911        user_password: U,
912    ) -> Result<(Vec<u8>, Vec<u8>), DecryptionError>
913    where
914        K: AsRef<[u8]>,
915        U: AsRef<[u8]>,
916    {
917        let file_encryption_key = file_encryption_key.as_ref();
918        let user_password = user_password.as_ref();
919
920        // Generate 16 random bytes of data using a strong random number generator. The first 8
921        // bytes are the user validation salt. The second 8 bytes are the user key salt. Compute
922        // the 32-byte hash using algorithm 2.B with an input string consisting of the UTF-8
923        // password concatenated with the user validation salt. The 48-byte string consisting of
924        // the 32-byte hash followed by the user validation salt followed by the user key salt is
925        // stored as the U key.
926        let mut user_value = [0u8; 48];
927        let mut rng = rand::rng();
928
929        rng.fill(&mut user_value[32..]);
930
931        let user_validation_salt = &user_value[32..][..8];
932
933        let mut input = Vec::with_capacity(user_password.len() + user_validation_salt.len());
934
935        input.extend_from_slice(user_password);
936        input.extend_from_slice(user_validation_salt);
937
938        let hashed_user_password = self.compute_hash(user_password, user_validation_salt, None)?;
939        user_value[..32].copy_from_slice(&hashed_user_password);
940
941        // Compute the 32-byte hash using algorithm 2.B with an input string consisting of the
942        // UTF-8 password concatenated with the user key salt.
943        let user_key_salt = &user_value[40..][..8];
944
945        input.clear();
946
947        input.extend_from_slice(user_password);
948        input.extend_from_slice(user_key_salt);
949
950        let hash = self.compute_hash(user_password, user_key_salt, None)?;
951
952        // Using this hash as the key, encrypt the file encryption key using AES-256 in CBC mode
953        // with no padding and initialization vector of zero. The resulting 32-byte string is
954        // stored as the UE key.
955        let mut key = [0u8; 32];
956        key.copy_from_slice(&hash);
957
958        let iv = [0u8; 16];
959
960        let mut user_encrypted = file_encryption_key.to_vec();
961        let mut encryptor = Aes256CbcEnc::new(&key.into(), &iv.into());
962
963        for block in user_encrypted.chunks_exact_mut(16) {
964            encryptor.encrypt_block_mut(block.into());
965        }
966
967        Ok((user_value.to_vec(), user_encrypted))
968    }
969
970    /// Compute the encryption dictionary's O-entry value (revision 6).
971    ///
972    /// This implements Algorithm 9 as described in ISO 32000-2:2020 (PDF 2.0).
973    pub(crate) fn compute_hashed_owner_password_r6<K, O>(
974        &self,
975        file_encryption_key: K,
976        owner_password: O,
977    ) -> Result<(Vec<u8>, Vec<u8>), DecryptionError>
978    where
979        K: AsRef<[u8]>,
980        O: AsRef<[u8]>,
981    {
982        let file_encryption_key = file_encryption_key.as_ref();
983        let owner_password = owner_password.as_ref();
984
985        // Generate 16 random bytes of data using a strong random number generator. The first 8
986        // bytes are the owner validation salt. The second 8 bytes are the owner key salt. Compute
987        // the 32-byte hash using algorithm 2.B with an input string consisting of the UTF-8
988        // password concatenated with the owner validation salt and then concatenated with the
989        // 48-byte U string as generated in Algorithm 8. The 48-byte string consisting of the
990        // 32-byte hash followed by the owner validation salt followed by the owner key salt is
991        // stored as the O key.
992        let mut owner_value = [0u8; 48];
993        let mut rng = rand::rng();
994
995        rng.fill(&mut owner_value[32..]);
996
997        let owner_validation_salt = &owner_value[32..][..8];
998
999        let hashed_owner_password = self.compute_hash(
1000            owner_password,
1001            owner_validation_salt,
1002            Some(&self.user_value),
1003        )?;
1004        owner_value[..32].copy_from_slice(&hashed_owner_password);
1005
1006        // Compute the 32-byte hash using algorithm 2.B with an input string consisting of the
1007        // UTF-8 password concatenated with the owner key salt.
1008        let owner_key_salt = &owner_value[40..][..8];
1009
1010        let hash = self.compute_hash(owner_password, owner_key_salt, Some(&self.user_value))?;
1011
1012        // Using this hash as the key, encrypt the file encryption key using AES-256 in CBC mode
1013        // with no padding and initialization vector of zero. The resulting 32-byte string is
1014        // stored as the OE key.
1015        let mut key = [0u8; 32];
1016        key.copy_from_slice(&hash);
1017
1018        let iv = [0u8; 16];
1019
1020        let mut owner_encrypted = file_encryption_key.to_vec();
1021        let mut encryptor = Aes256CbcEnc::new(&key.into(), &iv.into());
1022
1023        for block in owner_encrypted.chunks_exact_mut(16) {
1024            encryptor.encrypt_block_mut(block.into());
1025        }
1026
1027        Ok((owner_value.to_vec(), owner_encrypted))
1028    }
1029
1030    /// Compute the encryption dictionary's Perms (permissions) value (revision 6 and later).
1031    ///
1032    /// This implements Algorithm 10 as described in ISO 32000-2:2020 (PDF 2.0).
1033    pub(crate) fn compute_permissions<K>(
1034        &self,
1035        file_encryption_key: K,
1036    ) -> Result<Vec<u8>, DecryptionError>
1037    where
1038        K: AsRef<[u8]>,
1039    {
1040        let file_encryption_key = file_encryption_key.as_ref();
1041        let mut bytes = [0u8; 16];
1042
1043        // Record the 8 bytes of permission in the bytes 0-7 of the block, low order byte first.
1044        bytes[..8].copy_from_slice(&u64::to_le_bytes(self.permissions.bits()));
1045
1046        // Set byte 8 to ASCII character "T" or "F" according to the EncryptMetadata boolean.
1047        bytes[8] = if self.encrypt_metadata { b'T' } else { b'F' };
1048
1049        // Set bytes 9-11 to the ASCII characters "a", "d", "b".
1050        bytes[9..][..3].copy_from_slice(b"adb");
1051
1052        // Set bytes 12-15 to 4 bytes of random data, which will be ignored.
1053        let mut rng = rand::rng();
1054        rng.fill(&mut bytes[12..][..4]);
1055
1056        // Encrypt the 16-byte block using AES-256 in ECB mode with an initialization vector of
1057        // zero, using the file encryption key as the key.
1058        let mut key = [0u8; 32];
1059        key.copy_from_slice(file_encryption_key);
1060
1061        let mut encryptor = Aes256EbcEnc::new(&key.into());
1062
1063        for block in bytes.chunks_exact_mut(16) {
1064            encryptor.encrypt_block_mut(block.into());
1065        }
1066
1067        // The result (16 bytes) is stored as the Perms string, and checked for validity when the
1068        // file is opened.
1069        Ok(bytes.to_vec())
1070    }
1071
1072    /// Authenticate the user password (revision 6 and later).
1073    ///
1074    /// This implements Algorithm 11 as described in ISO 32000-2:2020 (PDF 2.0).
1075    fn authenticate_user_password_r6<U>(&self, user_password: U) -> Result<(), DecryptionError>
1076    where
1077        U: AsRef<[u8]>,
1078    {
1079        let mut user_password = user_password.as_ref();
1080
1081        let hashed_user_password = &self.user_value[0..][..32];
1082        let user_validation_salt = &self.user_value[32..][..8];
1083
1084        // Truncate the UTF-8 representation to 127 bytes if it is longer than 127 bytes.
1085        if user_password.len() > 127 {
1086            user_password = &user_password[..127];
1087        }
1088
1089        // Test the password against the user key by computing a hash using algorithm 2.B with an
1090        // input string consisting of the UTF-8 password concatenated with the 8 bytes of user
1091        // validation salt. If the 32-byte result matches the first 32-bytes of the U string, this
1092        // is the user password.
1093        let mut input = Vec::with_capacity(user_password.len() + user_validation_salt.len());
1094
1095        input.extend_from_slice(user_password);
1096        input.extend_from_slice(user_validation_salt);
1097
1098        if self.compute_hash(user_password, user_validation_salt, None)? != hashed_user_password {
1099            return Err(DecryptionError::IncorrectPassword);
1100        }
1101
1102        Ok(())
1103    }
1104
1105    /// Authenticate the owner password (revision 6 and later).
1106    ///
1107    /// This implements Algorithm 12 as described in ISO 32000-2:2020 (PDF 2.0).
1108    fn authenticate_owner_password_r6<O>(&self, owner_password: O) -> Result<(), DecryptionError>
1109    where
1110        O: AsRef<[u8]>,
1111    {
1112        let mut owner_password = owner_password.as_ref();
1113
1114        let hashed_owner_password = &self.owner_value[0..][..32];
1115        let owner_validation_salt = &self.owner_value[32..][..8];
1116
1117        // Truncate the UTF-8 representation to 127 bytes if it is longer than 127 bytes.
1118        if owner_password.len() > 127 {
1119            owner_password = &owner_password[..127];
1120        }
1121
1122        // Test the password against the owner key by computing a hash using algorithm 2.B with an
1123        // input string consisting of the UTF-8 password concatenated with the 8 bytes of owner
1124        // validation salt and the 48 byte U string. If the 32-byte result matches the first
1125        // 32-bytes of the O string, this is the owner password.
1126        let mut input = Vec::with_capacity(owner_password.len() + owner_validation_salt.len());
1127
1128        input.extend_from_slice(owner_password);
1129        input.extend_from_slice(owner_validation_salt);
1130
1131        if self.compute_hash(
1132            owner_password,
1133            owner_validation_salt,
1134            Some(&self.user_value),
1135        )? != hashed_owner_password
1136        {
1137            return Err(DecryptionError::IncorrectPassword);
1138        }
1139
1140        Ok(())
1141    }
1142
1143    /// Validate the permissions (revision 6 and later).
1144    ///
1145    /// This implements Algorithm 13 as described in ISO 32000-2:2020 (PDF 2.0).
1146    fn validate_permissions<K>(&self, file_encryption_key: K) -> Result<(), DecryptionError>
1147    where
1148        K: AsRef<[u8]>,
1149    {
1150        let file_encryption_key = file_encryption_key.as_ref();
1151
1152        // Decrypt the 16 byte Perms string using AES-256 in ECB mode with an initialization vector
1153        // of zero and the file encryption key as the key.
1154        let mut bytes = [0u8; 16];
1155        bytes.copy_from_slice(&self.permission_encrypted);
1156
1157        let mut key = [0u8; 32];
1158        key.copy_from_slice(file_encryption_key);
1159
1160        let mut decryptor = Aes256EbcDec::new(&key.into());
1161
1162        for block in bytes.chunks_exact_mut(16) {
1163            decryptor.decrypt_block_mut(block.into());
1164        }
1165
1166        // Verify that bytes 9-11 of the result are the characters "a", "d", "b".
1167        if &bytes[9..][..3] != b"adb" {
1168            return Err(DecryptionError::IncorrectPassword);
1169        }
1170
1171        // Bytes 0-3 of the decrypted Perms entry, treated as a little-endian integer, are the
1172        // user permissions. They should match the value in the P key.
1173        if bytes[..3] != u64::to_le_bytes(self.permissions.bits())[..3] {
1174            return Err(DecryptionError::IncorrectPassword);
1175        }
1176
1177        // Byte 8 should match the ASCII character "T" or "F" according to the boolean value of the
1178        // EncryptMetadata key.
1179        if bytes[8] != if self.encrypt_metadata { b'T' } else { b'F' } {
1180            return Err(DecryptionError::IncorrectPassword);
1181        }
1182
1183        Ok(())
1184    }
1185
1186    /// Sanitize the password.
1187    pub fn sanitize_password(&self, password: &str) -> Result<Vec<u8>, DecryptionError> {
1188        match self.revision {
1189            2..=4 => self.sanitize_password_r4(password),
1190            5..=6 => self.sanitize_password_r6(password),
1191            _ => Err(DecryptionError::UnsupportedRevision),
1192        }
1193    }
1194
1195    /// Compute the file encryption key used to encrypt/decrypt the document.
1196    pub fn compute_file_encryption_key<P>(
1197        &self,
1198        doc: &Document,
1199        password: P,
1200    ) -> Result<Vec<u8>, DecryptionError>
1201    where
1202        P: AsRef<[u8]>,
1203    {
1204        match self.revision {
1205            2..=4 => self.compute_file_encryption_key_r4(doc, password),
1206            5..=6 => self.compute_file_encryption_key_r6(password),
1207            _ => Err(DecryptionError::UnsupportedRevision),
1208        }
1209    }
1210
1211    /// Authenticate the owner password.
1212    pub fn authenticate_user_password<U>(
1213        &self,
1214        doc: &Document,
1215        user_password: U,
1216    ) -> Result<(), DecryptionError>
1217    where
1218        U: AsRef<[u8]>,
1219    {
1220        match self.revision {
1221            2..=4 => self.authenticate_user_password_r4(doc, user_password),
1222            5..=6 => self.authenticate_user_password_r6(user_password),
1223            _ => Err(DecryptionError::UnsupportedRevision),
1224        }
1225    }
1226
1227    /// Authenticate the owner password.
1228    pub fn authenticate_owner_password<O>(
1229        &self,
1230        doc: &Document,
1231        owner_password: O,
1232    ) -> Result<(), DecryptionError>
1233    where
1234        O: AsRef<[u8]>,
1235    {
1236        match self.revision {
1237            2..=4 => self.authenticate_owner_password_r4(doc, owner_password),
1238            5..=6 => self.authenticate_owner_password_r6(owner_password),
1239            _ => Err(DecryptionError::UnsupportedRevision),
1240        }
1241    }
1242}
1243
1244#[cfg(test)]
1245mod tests {
1246    use crate::Permissions;
1247    use crate::creator::tests::create_document;
1248    use crate::encryption::PasswordAlgorithm;
1249    use rand::Rng as _;
1250
1251    #[test]
1252    fn authenticate_password_r2() {
1253        let document = create_document();
1254
1255        let mut algorithm = PasswordAlgorithm {
1256            encrypt_metadata: true,
1257            length: None,
1258            version: 1,
1259            revision: 2,
1260            permissions: Permissions::all(),
1261            ..Default::default()
1262        };
1263
1264        let owner_password = "owner";
1265        let user_password = "user";
1266
1267        // Sanitize the passwords.
1268        let owner_password = algorithm.sanitize_password_r4(owner_password).unwrap();
1269        let user_password = algorithm.sanitize_password_r4(user_password).unwrap();
1270
1271        // Compute the hashed values.
1272        algorithm.owner_value = algorithm
1273            .compute_hashed_owner_password_r4(Some(&owner_password), &user_password)
1274            .unwrap();
1275
1276        algorithm.user_value = algorithm
1277            .compute_hashed_user_password_r2(&document, &user_password)
1278            .unwrap();
1279
1280        // Assert that the correct passwords authenticate.
1281        assert!(
1282            algorithm
1283                .authenticate_owner_password_r4(&document, &owner_password)
1284                .is_ok()
1285        );
1286        assert!(
1287            algorithm
1288                .authenticate_user_password_r4(&document, &user_password)
1289                .is_ok()
1290        );
1291
1292        // Assert that the swapped passwords do not authenticate.
1293        assert!(
1294            algorithm
1295                .authenticate_owner_password_r4(&document, user_password)
1296                .is_err()
1297        );
1298        assert!(
1299            algorithm
1300                .authenticate_user_password_r4(&document, owner_password)
1301                .is_err()
1302        );
1303    }
1304
1305    #[test]
1306    fn authenticate_password_r3() {
1307        let document = create_document();
1308
1309        let mut algorithm = PasswordAlgorithm {
1310            encrypt_metadata: true,
1311            length: Some(40),
1312            version: 2,
1313            revision: 3,
1314            permissions: Permissions::all(),
1315            ..Default::default()
1316        };
1317
1318        let owner_password = "owner";
1319        let user_password = "user";
1320
1321        // Sanitize the passwords.
1322        let owner_password = algorithm.sanitize_password_r4(owner_password).unwrap();
1323        let user_password = algorithm.sanitize_password_r4(user_password).unwrap();
1324
1325        // Compute the hashed values.
1326        algorithm.owner_value = algorithm
1327            .compute_hashed_owner_password_r4(Some(&owner_password), &user_password)
1328            .unwrap();
1329
1330        algorithm.user_value = algorithm
1331            .compute_hashed_user_password_r3_r4(&document, &user_password)
1332            .unwrap();
1333
1334        // Assert that the correct passwords authenticate.
1335        assert!(
1336            algorithm
1337                .authenticate_owner_password_r4(&document, &owner_password)
1338                .is_ok()
1339        );
1340        assert!(
1341            algorithm
1342                .authenticate_user_password_r4(&document, &user_password)
1343                .is_ok()
1344        );
1345
1346        // Assert that the swapped passwords do not authenticate.
1347        assert!(
1348            algorithm
1349                .authenticate_owner_password_r4(&document, user_password)
1350                .is_err()
1351        );
1352        assert!(
1353            algorithm
1354                .authenticate_user_password_r4(&document, owner_password)
1355                .is_err()
1356        );
1357    }
1358
1359    #[test]
1360    fn authenticate_password_r4() {
1361        let document = create_document();
1362
1363        let mut algorithm = PasswordAlgorithm {
1364            encrypt_metadata: true,
1365            length: Some(128),
1366            version: 4,
1367            revision: 4,
1368            permissions: Permissions::all(),
1369            ..Default::default()
1370        };
1371
1372        let owner_password = "owner";
1373        let user_password = "user";
1374
1375        // Sanitize the passwords.
1376        let owner_password = algorithm.sanitize_password_r4(owner_password).unwrap();
1377        let user_password = algorithm.sanitize_password_r4(user_password).unwrap();
1378
1379        // Compute the hashed values.
1380        algorithm.owner_value = algorithm
1381            .compute_hashed_owner_password_r4(Some(&owner_password), &user_password)
1382            .unwrap();
1383
1384        algorithm.user_value = algorithm
1385            .compute_hashed_user_password_r3_r4(&document, &user_password)
1386            .unwrap();
1387
1388        // Assert that the correct passwords authenticate.
1389        assert!(
1390            algorithm
1391                .authenticate_owner_password_r4(&document, &owner_password)
1392                .is_ok()
1393        );
1394        assert!(
1395            algorithm
1396                .authenticate_user_password_r4(&document, &user_password)
1397                .is_ok()
1398        );
1399
1400        // Assert that the swapped passwords do not authenticate.
1401        assert!(
1402            algorithm
1403                .authenticate_owner_password_r4(&document, user_password)
1404                .is_err()
1405        );
1406        assert!(
1407            algorithm
1408                .authenticate_user_password_r4(&document, owner_password)
1409                .is_err()
1410        );
1411    }
1412
1413    #[test]
1414    fn authenticate_password_r5() {
1415        let mut algorithm = PasswordAlgorithm {
1416            encrypt_metadata: true,
1417            version: 5,
1418            revision: 5,
1419            permissions: Permissions::all(),
1420            ..Default::default()
1421        };
1422
1423        let owner_password = "owner";
1424        let user_password = "user";
1425
1426        // Sanitize the passwords.
1427        let owner_password = algorithm.sanitize_password_r6(owner_password).unwrap();
1428        let user_password = algorithm.sanitize_password_r6(user_password).unwrap();
1429
1430        // Compute the hashed values.
1431        let mut file_encryption_key = [0u8; 32];
1432
1433        let mut rng = rand::rng();
1434        rng.fill(&mut file_encryption_key);
1435
1436        let (user_value, user_encrypted) = algorithm
1437            .compute_hashed_user_password_r6(file_encryption_key, &user_password)
1438            .unwrap();
1439
1440        algorithm.user_value = user_value;
1441        algorithm.user_encrypted = user_encrypted;
1442
1443        let (owner_value, owner_encrypted) = algorithm
1444            .compute_hashed_owner_password_r6(file_encryption_key, &owner_password)
1445            .unwrap();
1446
1447        algorithm.owner_value = owner_value;
1448        algorithm.owner_encrypted = owner_encrypted;
1449
1450        algorithm.permission_encrypted =
1451            algorithm.compute_permissions(file_encryption_key).unwrap();
1452
1453        // Assert that the correct passwords authenticate.
1454        assert!(
1455            algorithm
1456                .authenticate_owner_password_r6(&owner_password)
1457                .is_ok()
1458        );
1459        assert!(
1460            algorithm
1461                .authenticate_user_password_r6(&user_password)
1462                .is_ok()
1463        );
1464
1465        // Assert that the swapped passwords do not authenticate.
1466        assert!(
1467            algorithm
1468                .authenticate_owner_password_r6(&user_password)
1469                .is_err()
1470        );
1471        assert!(
1472            algorithm
1473                .authenticate_user_password_r6(&owner_password)
1474                .is_err()
1475        );
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
1482            .compute_file_encryption_key_r6(&owner_password)
1483            .unwrap();
1484        assert_eq!(&file_encryption_key[..], key);
1485
1486        // Assert that the file encryption key is equal for the user password.
1487        let key = algorithm
1488            .compute_file_encryption_key_r6(&user_password)
1489            .unwrap();
1490        assert_eq!(&file_encryption_key[..], key);
1491    }
1492
1493    #[test]
1494    fn authenticate_password_r6() {
1495        let mut algorithm = PasswordAlgorithm {
1496            encrypt_metadata: true,
1497            version: 5,
1498            revision: 6,
1499            permissions: Permissions::all(),
1500            ..Default::default()
1501        };
1502
1503        let owner_password = "owner";
1504        let user_password = "user";
1505
1506        // Sanitize the passwords.
1507        let owner_password = algorithm.sanitize_password_r6(owner_password).unwrap();
1508        let user_password = algorithm.sanitize_password_r6(user_password).unwrap();
1509
1510        // Compute the hashed values.
1511        let mut file_encryption_key = [0u8; 32];
1512
1513        let mut rng = rand::rng();
1514        rng.fill(&mut file_encryption_key);
1515
1516        let (user_value, user_encrypted) = algorithm
1517            .compute_hashed_user_password_r6(file_encryption_key, &user_password)
1518            .unwrap();
1519
1520        algorithm.user_value = user_value;
1521        algorithm.user_encrypted = user_encrypted;
1522
1523        let (owner_value, owner_encrypted) = algorithm
1524            .compute_hashed_owner_password_r6(file_encryption_key, &owner_password)
1525            .unwrap();
1526
1527        algorithm.owner_value = owner_value;
1528        algorithm.owner_encrypted = owner_encrypted;
1529
1530        algorithm.permission_encrypted =
1531            algorithm.compute_permissions(file_encryption_key).unwrap();
1532
1533        // Assert that the correct passwords authenticate.
1534        assert!(
1535            algorithm
1536                .authenticate_owner_password_r6(&owner_password)
1537                .is_ok()
1538        );
1539        assert!(
1540            algorithm
1541                .authenticate_user_password_r6(&user_password)
1542                .is_ok()
1543        );
1544
1545        // Assert that the swapped passwords do not authenticate.
1546        assert!(
1547            algorithm
1548                .authenticate_owner_password_r6(&user_password)
1549                .is_err()
1550        );
1551        assert!(
1552            algorithm
1553                .authenticate_user_password_r6(&owner_password)
1554                .is_err()
1555        );
1556
1557        // Assert that the permissions validate correctly.
1558        assert!(algorithm.validate_permissions(file_encryption_key).is_ok());
1559
1560        // Assert that the file encryption key is equal for the owner password.
1561        let key = algorithm
1562            .compute_file_encryption_key_r6(&owner_password)
1563            .unwrap();
1564        assert_eq!(&file_encryption_key[..], key);
1565
1566        // Assert that the file encryption key is equal for the user password.
1567        let key = algorithm
1568            .compute_file_encryption_key_r6(&user_password)
1569            .unwrap();
1570        assert_eq!(&file_encryption_key[..], key);
1571    }
1572}