1use crate::encryption::{
4 EncryptionDictionary, EncryptionKey, OwnerPassword, Permissions, StandardSecurityHandler,
5 UserPassword,
6};
7use crate::error::{PdfError, Result};
8use crate::objects::ObjectId;
9
10#[derive(Debug, Clone)]
12pub struct DocumentEncryption {
13 pub user_password: UserPassword,
15 pub owner_password: OwnerPassword,
17 pub permissions: Permissions,
19 pub strength: EncryptionStrength,
21}
22
23#[derive(Debug, Clone, Copy)]
25pub enum EncryptionStrength {
26 Rc4_40bit,
28 Rc4_128bit,
30 Aes128,
32 Aes256,
34}
35
36impl DocumentEncryption {
37 pub fn new(
39 user_password: impl Into<String>,
40 owner_password: impl Into<String>,
41 permissions: Permissions,
42 strength: EncryptionStrength,
43 ) -> Self {
44 Self {
45 user_password: UserPassword(user_password.into()),
46 owner_password: OwnerPassword(owner_password.into()),
47 permissions,
48 strength,
49 }
50 }
51
52 pub fn with_passwords(
54 user_password: impl Into<String>,
55 owner_password: impl Into<String>,
56 ) -> Self {
57 Self::new(
58 user_password,
59 owner_password,
60 Permissions::all(),
61 EncryptionStrength::Rc4_128bit,
62 )
63 }
64
65 pub fn handler(&self) -> StandardSecurityHandler {
67 match self.strength {
68 EncryptionStrength::Rc4_40bit => StandardSecurityHandler::rc4_40bit(),
69 EncryptionStrength::Rc4_128bit => StandardSecurityHandler::rc4_128bit(),
70 EncryptionStrength::Aes128 => StandardSecurityHandler::aes_128_r4(),
71 EncryptionStrength::Aes256 => StandardSecurityHandler::aes_256_r5(),
72 }
73 }
74
75 pub fn create_encryption_dict(&self, file_id: Option<&[u8]>) -> Result<EncryptionDictionary> {
77 let handler = self.handler();
78
79 if matches!(self.strength, EncryptionStrength::Aes256) {
81 return self.create_aes256_encryption_dict(&handler, file_id);
82 }
83
84 let owner_hash = handler.compute_owner_hash(&self.owner_password, &self.user_password);
86 let user_hash = handler.compute_user_hash(
87 &self.user_password,
88 &owner_hash,
89 self.permissions,
90 file_id,
91 )?;
92
93 let enc_dict = match self.strength {
94 EncryptionStrength::Rc4_40bit => EncryptionDictionary::rc4_40bit(
95 owner_hash,
96 user_hash,
97 self.permissions,
98 file_id.map(|id| id.to_vec()),
99 ),
100 EncryptionStrength::Rc4_128bit => EncryptionDictionary::rc4_128bit(
101 owner_hash,
102 user_hash,
103 self.permissions,
104 file_id.map(|id| id.to_vec()),
105 ),
106 EncryptionStrength::Aes128 => EncryptionDictionary::aes_128(
107 owner_hash,
108 user_hash,
109 self.permissions,
110 file_id.map(|id| id.to_vec()),
111 ),
112 EncryptionStrength::Aes256 => unreachable!("handled above"),
113 };
114
115 Ok(enc_dict)
116 }
117
118 fn create_aes256_encryption_dict(
120 &self,
121 handler: &StandardSecurityHandler,
122 file_id: Option<&[u8]>,
123 ) -> Result<EncryptionDictionary> {
124 let u_entry = handler.compute_r5_user_hash(&self.user_password)?;
125 let o_entry = handler.compute_r5_owner_hash(&self.owner_password, &u_entry)?;
126
127 let mut encryption_key = vec![0u8; 32];
129 use rand::Rng;
130 rand::rng().fill_bytes(&mut encryption_key);
131 let enc_key_obj = EncryptionKey::new(encryption_key.clone());
132
133 let ue_entry = handler.compute_r5_ue_entry(&self.user_password, &u_entry, &enc_key_obj)?;
135 let oe_entry = handler.compute_r5_oe_entry(
136 &self.owner_password,
137 &o_entry,
138 &u_entry,
139 &encryption_key,
140 )?;
141
142 Ok(EncryptionDictionary::aes_256(
143 o_entry,
144 u_entry,
145 self.permissions,
146 file_id.map(|id| id.to_vec()),
147 )
148 .with_r5_entries(ue_entry, oe_entry))
149 }
150
151 pub fn get_encryption_key(
160 &self,
161 enc_dict: &EncryptionDictionary,
162 file_id: Option<&[u8]>,
163 ) -> Result<EncryptionKey> {
164 let handler = self.handler();
165 if matches!(self.strength, EncryptionStrength::Aes256) {
166 let ue = enc_dict.ue.as_deref().ok_or_else(|| {
167 PdfError::EncryptionError("AES-256 encryption dict missing UE entry".to_string())
168 })?;
169 return handler.recover_r5_encryption_key(&self.user_password, &enc_dict.u, ue);
170 }
171 handler.compute_encryption_key(&self.user_password, &enc_dict.o, self.permissions, file_id)
172 }
173}
174
175#[allow(dead_code)]
177pub struct EncryptionContext {
178 handler: StandardSecurityHandler,
180 key: EncryptionKey,
182}
183
184#[allow(dead_code)]
185impl EncryptionContext {
186 pub fn new(handler: StandardSecurityHandler, key: EncryptionKey) -> Self {
188 Self { handler, key }
189 }
190
191 pub fn encrypt_string(&self, data: &[u8], obj_id: &ObjectId) -> Vec<u8> {
193 self.handler.encrypt_string(data, &self.key, obj_id)
194 }
195
196 pub fn decrypt_string(&self, data: &[u8], obj_id: &ObjectId) -> Vec<u8> {
198 self.handler.decrypt_string(data, &self.key, obj_id)
199 }
200
201 pub fn encrypt_stream(&self, data: &[u8], obj_id: &ObjectId) -> Vec<u8> {
203 self.handler.encrypt_stream(data, &self.key, obj_id)
204 }
205
206 pub fn decrypt_stream(&self, data: &[u8], obj_id: &ObjectId) -> Vec<u8> {
208 self.handler.decrypt_stream(data, &self.key, obj_id)
209 }
210}
211
212#[cfg(test)]
213mod tests {
214 use super::*;
215
216 #[test]
217 fn test_document_encryption_new() {
218 let enc = DocumentEncryption::new(
219 "user123",
220 "owner456",
221 Permissions::all(),
222 EncryptionStrength::Rc4_128bit,
223 );
224
225 assert_eq!(enc.user_password.0, "user123");
226 assert_eq!(enc.owner_password.0, "owner456");
227 }
228
229 #[test]
230 fn test_with_passwords() {
231 let enc = DocumentEncryption::with_passwords("user", "owner");
232 assert_eq!(enc.user_password.0, "user");
233 assert_eq!(enc.owner_password.0, "owner");
234 assert!(enc.permissions.can_print());
235 assert!(enc.permissions.can_modify_contents());
236 }
237
238 #[test]
239 fn test_encryption_dict_creation() {
240 let enc = DocumentEncryption::new(
241 "test",
242 "owner",
243 Permissions::new(),
244 EncryptionStrength::Rc4_40bit,
245 );
246
247 let enc_dict = enc.create_encryption_dict(None).unwrap();
248 assert_eq!(enc_dict.v, 1);
249 assert_eq!(enc_dict.r, 2);
250 assert_eq!(enc_dict.length, Some(5));
251 }
252
253 #[test]
254 fn test_encryption_context() {
255 let handler = StandardSecurityHandler::rc4_40bit();
256 let key = EncryptionKey::new(vec![1, 2, 3, 4, 5]);
257 let ctx = EncryptionContext::new(handler, key);
258
259 let obj_id = ObjectId::new(1, 0);
260 let plaintext = b"Hello, World!";
261
262 let encrypted = ctx.encrypt_string(plaintext, &obj_id);
263 assert_ne!(encrypted, plaintext);
264
265 let decrypted = ctx.decrypt_string(&encrypted, &obj_id);
266 assert_eq!(decrypted, plaintext);
267 }
268
269 #[test]
270 fn test_encryption_strength_variants() {
271 let enc_40 = DocumentEncryption::new(
272 "user",
273 "owner",
274 Permissions::new(),
275 EncryptionStrength::Rc4_40bit,
276 );
277
278 let enc_128 = DocumentEncryption::new(
279 "user",
280 "owner",
281 Permissions::new(),
282 EncryptionStrength::Rc4_128bit,
283 );
284
285 let _handler_40 = enc_40.handler();
287 let _handler_128 = enc_128.handler();
288
289 let dict_40 = enc_40.create_encryption_dict(None).unwrap();
291 let dict_128 = enc_128.create_encryption_dict(None).unwrap();
292
293 assert_eq!(dict_40.v, 1);
294 assert_eq!(dict_40.r, 2);
295 assert_eq!(dict_40.length, Some(5));
296
297 assert_eq!(dict_128.v, 2);
298 assert_eq!(dict_128.r, 3);
299 assert_eq!(dict_128.length, Some(16));
300 }
301
302 #[test]
303 fn test_empty_passwords() {
304 let enc =
305 DocumentEncryption::new("", "", Permissions::all(), EncryptionStrength::Rc4_128bit);
306
307 assert_eq!(enc.user_password.0, "");
308 assert_eq!(enc.owner_password.0, "");
309
310 let dict = enc.create_encryption_dict(None);
312 assert!(dict.is_ok());
313 }
314
315 #[test]
316 fn test_long_passwords() {
317 let long_user = "a".repeat(100);
318 let long_owner = "b".repeat(100);
319
320 let enc = DocumentEncryption::new(
321 &long_user,
322 &long_owner,
323 Permissions::new(),
324 EncryptionStrength::Rc4_128bit,
325 );
326
327 assert_eq!(enc.user_password.0.len(), 100);
328 assert_eq!(enc.owner_password.0.len(), 100);
329
330 let dict = enc.create_encryption_dict(None);
331 assert!(dict.is_ok());
332 }
333
334 #[test]
335 fn test_unicode_passwords() {
336 let enc = DocumentEncryption::new(
337 "contraseña",
338 "密码",
339 Permissions::all(),
340 EncryptionStrength::Rc4_40bit,
341 );
342
343 assert_eq!(enc.user_password.0, "contraseña");
344 assert_eq!(enc.owner_password.0, "密码");
345
346 let dict = enc.create_encryption_dict(None);
347 assert!(dict.is_ok());
348 }
349
350 #[test]
351 fn test_encryption_with_file_id() {
352 let enc = DocumentEncryption::new(
353 "user",
354 "owner",
355 Permissions::new(),
356 EncryptionStrength::Rc4_128bit,
357 );
358
359 let file_id = b"test_file_id_12345";
360 let dict = enc.create_encryption_dict(Some(file_id)).unwrap();
361
362 let key = enc.get_encryption_key(&dict, Some(file_id));
364 assert!(key.is_ok());
365 }
366
367 #[test]
368 fn test_different_permissions() {
369 let perms_none = Permissions::new();
370 let perms_all = Permissions::all();
371 let mut perms_custom = Permissions::new();
372 perms_custom.set_print(true);
373 perms_custom.set_modify_contents(false);
374
375 let enc1 =
376 DocumentEncryption::new("user", "owner", perms_none, EncryptionStrength::Rc4_128bit);
377
378 let enc2 =
379 DocumentEncryption::new("user", "owner", perms_all, EncryptionStrength::Rc4_128bit);
380
381 let enc3 = DocumentEncryption::new(
382 "user",
383 "owner",
384 perms_custom,
385 EncryptionStrength::Rc4_128bit,
386 );
387
388 let _dict1 = enc1.create_encryption_dict(None).unwrap();
390 let _dict2 = enc2.create_encryption_dict(None).unwrap();
391 let _dict3 = enc3.create_encryption_dict(None).unwrap();
392
393 }
397
398 #[test]
399 fn test_encryption_context_stream() {
400 let handler = StandardSecurityHandler::rc4_128bit();
401 let key = EncryptionKey::new(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
402 let ctx = EncryptionContext::new(handler, key);
403
404 let obj_id = ObjectId::new(5, 0);
405 let stream_data = b"This is a PDF stream content that needs encryption";
406
407 let encrypted = ctx.encrypt_stream(stream_data, &obj_id);
408 assert_ne!(encrypted, stream_data);
409
410 let decrypted = ctx.decrypt_stream(&encrypted, &obj_id);
411 assert_eq!(decrypted, stream_data);
412 }
413
414 #[test]
415 fn test_encryption_context_different_objects() {
416 let handler = StandardSecurityHandler::rc4_40bit();
417 let key = EncryptionKey::new(vec![1, 2, 3, 4, 5]);
418 let ctx = EncryptionContext::new(handler, key);
419
420 let obj_id1 = ObjectId::new(1, 0);
421 let obj_id2 = ObjectId::new(2, 0);
422 let plaintext = b"Test data";
423
424 let encrypted1 = ctx.encrypt_string(plaintext, &obj_id1);
425 let encrypted2 = ctx.encrypt_string(plaintext, &obj_id2);
426
427 assert_ne!(encrypted1, encrypted2);
429
430 assert_eq!(ctx.decrypt_string(&encrypted1, &obj_id1), plaintext);
432 assert_eq!(ctx.decrypt_string(&encrypted2, &obj_id2), plaintext);
433 }
434
435 #[test]
436 fn test_get_encryption_key_consistency() {
437 let enc = DocumentEncryption::new(
438 "user123",
439 "owner456",
440 Permissions::all(),
441 EncryptionStrength::Rc4_128bit,
442 );
443
444 let file_id = b"consistent_file_id";
445 let dict = enc.create_encryption_dict(Some(file_id)).unwrap();
446
447 let key1 = enc.get_encryption_key(&dict, Some(file_id));
449 let key2 = enc.get_encryption_key(&dict, Some(file_id));
450
451 assert!(key1.is_ok());
453 assert!(key2.is_ok());
454 }
455
456 #[test]
457 fn test_handler_selection() {
458 let enc_40 = DocumentEncryption::new(
459 "test",
460 "test",
461 Permissions::new(),
462 EncryptionStrength::Rc4_40bit,
463 );
464
465 let enc_128 = DocumentEncryption::new(
466 "test",
467 "test",
468 Permissions::new(),
469 EncryptionStrength::Rc4_128bit,
470 );
471
472 let _handler_40 = enc_40.handler();
474 let _handler_128 = enc_128.handler();
475
476 let dict_40 = enc_40.create_encryption_dict(None).unwrap();
478 let dict_128 = enc_128.create_encryption_dict(None).unwrap();
479
480 assert_eq!(dict_40.length, Some(5));
482 assert_eq!(dict_128.length, Some(16));
483 }
484}