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}