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, &self.user_password)?;
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 =
136 handler.compute_r5_oe_entry(&self.owner_password, &o_entry, &encryption_key)?;
137
138 Ok(EncryptionDictionary::aes_256(
139 o_entry,
140 u_entry,
141 self.permissions,
142 file_id.map(|id| id.to_vec()),
143 )
144 .with_r5_entries(ue_entry, oe_entry))
145 }
146
147 pub fn get_encryption_key(
156 &self,
157 enc_dict: &EncryptionDictionary,
158 file_id: Option<&[u8]>,
159 ) -> Result<EncryptionKey> {
160 let handler = self.handler();
161 if matches!(self.strength, EncryptionStrength::Aes256) {
162 let ue = enc_dict.ue.as_deref().ok_or_else(|| {
163 PdfError::EncryptionError("AES-256 encryption dict missing UE entry".to_string())
164 })?;
165 return handler.recover_r5_encryption_key(&self.user_password, &enc_dict.u, ue);
166 }
167 handler.compute_encryption_key(&self.user_password, &enc_dict.o, self.permissions, file_id)
168 }
169}
170
171#[allow(dead_code)]
173pub struct EncryptionContext {
174 handler: StandardSecurityHandler,
176 key: EncryptionKey,
178}
179
180#[allow(dead_code)]
181impl EncryptionContext {
182 pub fn new(handler: StandardSecurityHandler, key: EncryptionKey) -> Self {
184 Self { handler, key }
185 }
186
187 pub fn encrypt_string(&self, data: &[u8], obj_id: &ObjectId) -> Vec<u8> {
189 self.handler.encrypt_string(data, &self.key, obj_id)
190 }
191
192 pub fn decrypt_string(&self, data: &[u8], obj_id: &ObjectId) -> Vec<u8> {
194 self.handler.decrypt_string(data, &self.key, obj_id)
195 }
196
197 pub fn encrypt_stream(&self, data: &[u8], obj_id: &ObjectId) -> Vec<u8> {
199 self.handler.encrypt_stream(data, &self.key, obj_id)
200 }
201
202 pub fn decrypt_stream(&self, data: &[u8], obj_id: &ObjectId) -> Vec<u8> {
204 self.handler.decrypt_stream(data, &self.key, obj_id)
205 }
206}
207
208#[cfg(test)]
209mod tests {
210 use super::*;
211
212 #[test]
213 fn test_document_encryption_new() {
214 let enc = DocumentEncryption::new(
215 "user123",
216 "owner456",
217 Permissions::all(),
218 EncryptionStrength::Rc4_128bit,
219 );
220
221 assert_eq!(enc.user_password.0, "user123");
222 assert_eq!(enc.owner_password.0, "owner456");
223 }
224
225 #[test]
226 fn test_with_passwords() {
227 let enc = DocumentEncryption::with_passwords("user", "owner");
228 assert_eq!(enc.user_password.0, "user");
229 assert_eq!(enc.owner_password.0, "owner");
230 assert!(enc.permissions.can_print());
231 assert!(enc.permissions.can_modify_contents());
232 }
233
234 #[test]
235 fn test_encryption_dict_creation() {
236 let enc = DocumentEncryption::new(
237 "test",
238 "owner",
239 Permissions::new(),
240 EncryptionStrength::Rc4_40bit,
241 );
242
243 let enc_dict = enc.create_encryption_dict(None).unwrap();
244 assert_eq!(enc_dict.v, 1);
245 assert_eq!(enc_dict.r, 2);
246 assert_eq!(enc_dict.length, Some(5));
247 }
248
249 #[test]
250 fn test_encryption_context() {
251 let handler = StandardSecurityHandler::rc4_40bit();
252 let key = EncryptionKey::new(vec![1, 2, 3, 4, 5]);
253 let ctx = EncryptionContext::new(handler, key);
254
255 let obj_id = ObjectId::new(1, 0);
256 let plaintext = b"Hello, World!";
257
258 let encrypted = ctx.encrypt_string(plaintext, &obj_id);
259 assert_ne!(encrypted, plaintext);
260
261 let decrypted = ctx.decrypt_string(&encrypted, &obj_id);
262 assert_eq!(decrypted, plaintext);
263 }
264
265 #[test]
266 fn test_encryption_strength_variants() {
267 let enc_40 = DocumentEncryption::new(
268 "user",
269 "owner",
270 Permissions::new(),
271 EncryptionStrength::Rc4_40bit,
272 );
273
274 let enc_128 = DocumentEncryption::new(
275 "user",
276 "owner",
277 Permissions::new(),
278 EncryptionStrength::Rc4_128bit,
279 );
280
281 let _handler_40 = enc_40.handler();
283 let _handler_128 = enc_128.handler();
284
285 let dict_40 = enc_40.create_encryption_dict(None).unwrap();
287 let dict_128 = enc_128.create_encryption_dict(None).unwrap();
288
289 assert_eq!(dict_40.v, 1);
290 assert_eq!(dict_40.r, 2);
291 assert_eq!(dict_40.length, Some(5));
292
293 assert_eq!(dict_128.v, 2);
294 assert_eq!(dict_128.r, 3);
295 assert_eq!(dict_128.length, Some(16));
296 }
297
298 #[test]
299 fn test_empty_passwords() {
300 let enc =
301 DocumentEncryption::new("", "", Permissions::all(), EncryptionStrength::Rc4_128bit);
302
303 assert_eq!(enc.user_password.0, "");
304 assert_eq!(enc.owner_password.0, "");
305
306 let dict = enc.create_encryption_dict(None);
308 assert!(dict.is_ok());
309 }
310
311 #[test]
312 fn test_long_passwords() {
313 let long_user = "a".repeat(100);
314 let long_owner = "b".repeat(100);
315
316 let enc = DocumentEncryption::new(
317 &long_user,
318 &long_owner,
319 Permissions::new(),
320 EncryptionStrength::Rc4_128bit,
321 );
322
323 assert_eq!(enc.user_password.0.len(), 100);
324 assert_eq!(enc.owner_password.0.len(), 100);
325
326 let dict = enc.create_encryption_dict(None);
327 assert!(dict.is_ok());
328 }
329
330 #[test]
331 fn test_unicode_passwords() {
332 let enc = DocumentEncryption::new(
333 "contraseña",
334 "密码",
335 Permissions::all(),
336 EncryptionStrength::Rc4_40bit,
337 );
338
339 assert_eq!(enc.user_password.0, "contraseña");
340 assert_eq!(enc.owner_password.0, "密码");
341
342 let dict = enc.create_encryption_dict(None);
343 assert!(dict.is_ok());
344 }
345
346 #[test]
347 fn test_encryption_with_file_id() {
348 let enc = DocumentEncryption::new(
349 "user",
350 "owner",
351 Permissions::new(),
352 EncryptionStrength::Rc4_128bit,
353 );
354
355 let file_id = b"test_file_id_12345";
356 let dict = enc.create_encryption_dict(Some(file_id)).unwrap();
357
358 let key = enc.get_encryption_key(&dict, Some(file_id));
360 assert!(key.is_ok());
361 }
362
363 #[test]
364 fn test_different_permissions() {
365 let perms_none = Permissions::new();
366 let perms_all = Permissions::all();
367 let mut perms_custom = Permissions::new();
368 perms_custom.set_print(true);
369 perms_custom.set_modify_contents(false);
370
371 let enc1 =
372 DocumentEncryption::new("user", "owner", perms_none, EncryptionStrength::Rc4_128bit);
373
374 let enc2 =
375 DocumentEncryption::new("user", "owner", perms_all, EncryptionStrength::Rc4_128bit);
376
377 let enc3 = DocumentEncryption::new(
378 "user",
379 "owner",
380 perms_custom,
381 EncryptionStrength::Rc4_128bit,
382 );
383
384 let _dict1 = enc1.create_encryption_dict(None).unwrap();
386 let _dict2 = enc2.create_encryption_dict(None).unwrap();
387 let _dict3 = enc3.create_encryption_dict(None).unwrap();
388
389 }
393
394 #[test]
395 fn test_encryption_context_stream() {
396 let handler = StandardSecurityHandler::rc4_128bit();
397 let key = EncryptionKey::new(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
398 let ctx = EncryptionContext::new(handler, key);
399
400 let obj_id = ObjectId::new(5, 0);
401 let stream_data = b"This is a PDF stream content that needs encryption";
402
403 let encrypted = ctx.encrypt_stream(stream_data, &obj_id);
404 assert_ne!(encrypted, stream_data);
405
406 let decrypted = ctx.decrypt_stream(&encrypted, &obj_id);
407 assert_eq!(decrypted, stream_data);
408 }
409
410 #[test]
411 fn test_encryption_context_different_objects() {
412 let handler = StandardSecurityHandler::rc4_40bit();
413 let key = EncryptionKey::new(vec![1, 2, 3, 4, 5]);
414 let ctx = EncryptionContext::new(handler, key);
415
416 let obj_id1 = ObjectId::new(1, 0);
417 let obj_id2 = ObjectId::new(2, 0);
418 let plaintext = b"Test data";
419
420 let encrypted1 = ctx.encrypt_string(plaintext, &obj_id1);
421 let encrypted2 = ctx.encrypt_string(plaintext, &obj_id2);
422
423 assert_ne!(encrypted1, encrypted2);
425
426 assert_eq!(ctx.decrypt_string(&encrypted1, &obj_id1), plaintext);
428 assert_eq!(ctx.decrypt_string(&encrypted2, &obj_id2), plaintext);
429 }
430
431 #[test]
432 fn test_get_encryption_key_consistency() {
433 let enc = DocumentEncryption::new(
434 "user123",
435 "owner456",
436 Permissions::all(),
437 EncryptionStrength::Rc4_128bit,
438 );
439
440 let file_id = b"consistent_file_id";
441 let dict = enc.create_encryption_dict(Some(file_id)).unwrap();
442
443 let key1 = enc.get_encryption_key(&dict, Some(file_id));
445 let key2 = enc.get_encryption_key(&dict, Some(file_id));
446
447 assert!(key1.is_ok());
449 assert!(key2.is_ok());
450 }
451
452 #[test]
453 fn test_handler_selection() {
454 let enc_40 = DocumentEncryption::new(
455 "test",
456 "test",
457 Permissions::new(),
458 EncryptionStrength::Rc4_40bit,
459 );
460
461 let enc_128 = DocumentEncryption::new(
462 "test",
463 "test",
464 Permissions::new(),
465 EncryptionStrength::Rc4_128bit,
466 );
467
468 let _handler_40 = enc_40.handler();
470 let _handler_128 = enc_128.handler();
471
472 let dict_40 = enc_40.create_encryption_dict(None).unwrap();
474 let dict_128 = enc_128.create_encryption_dict(None).unwrap();
475
476 assert_eq!(dict_40.length, Some(5));
478 assert_eq!(dict_128.length, Some(16));
479 }
480}