shadow_crypt_shell/encryption/
workflow.rs1use rayon::prelude::*;
2use shadow_crypt_core::{
3 algorithm::Algorithm,
4 memory::SecureKey,
5 progress::ProgressCounter,
6 report::{EncryptionReport, KeyDerivationReport},
7 v1::{
8 crypt::encrypt_bytes,
9 file::{EncryptedFile, PlaintextFile},
10 header::FileHeader,
11 key::KeyDerivationParams,
12 key_ops::derive_key,
13 },
14};
15
16use crate::{
17 encryption::{
18 file::{EncryptionInput, EncryptionInputFile, EncryptionOutputFile},
19 file_ops::{load_plaintext_file, store_encrypted_file},
20 nonce::generate_nonce,
21 salt::generate_salt,
22 },
23 errors::WorkflowResult,
24 ui::{display_encryption_report, display_key_derivation_report, display_progress},
25};
26
27pub fn run_workflow(input: EncryptionInput) -> WorkflowResult<()> {
28 let salt: [u8; 16] = generate_salt()?;
29
30 let params = KeyDerivationParams::from(input.security_profile);
31 let (key, report): (SecureKey, KeyDerivationReport) =
32 derive_key(input.password.as_str().as_bytes(), salt.as_ref(), ¶ms)?;
33
34 display_key_derivation_report(&report);
35
36 let counter = ProgressCounter::new(input.files.len() as u64);
37
38 input
40 .files
41 .par_iter()
42 .map(|input_file| {
43 counter.increment();
44 display_progress(&counter);
45 process_file_encryption(
46 input_file.to_owned(),
47 &key,
48 &salt,
49 ¶ms,
50 &input.output_dir,
51 )
52 })
53 .for_each(display_encryption_report);
54
55 Ok(())
56}
57
58fn process_file_encryption(
59 file: EncryptionInputFile,
60 key: &SecureKey,
61 salt: &[u8; 16],
62 kdf_params: &KeyDerivationParams,
63 output_dir: &std::path::Path,
64) -> WorkflowResult<EncryptionReport> {
65 let start_time = std::time::Instant::now();
66
67 let input_file: EncryptionInputFile = file;
68
69 let filename_nonce: [u8; 24] = generate_nonce()?;
70 let content_nonce: [u8; 24] = generate_nonce()?;
71 let plaintext_file: PlaintextFile = load_plaintext_file(&input_file)?;
72
73 let (filename_ciphertext, _): (Vec<u8>, Algorithm) = encrypt_bytes(
74 input_file.filename.as_bytes(),
75 key.as_bytes(),
76 &filename_nonce,
77 )?;
78
79 let (content_ciphertext, algorithm): (Vec<u8>, Algorithm) = encrypt_bytes(
80 plaintext_file.content().as_slice(),
81 key.as_bytes(),
82 &content_nonce,
83 )?;
84
85 let header = FileHeader::new(
86 *salt,
87 kdf_params.clone(),
88 content_nonce,
89 filename_nonce,
90 filename_ciphertext,
91 );
92
93 let encrypted_file = EncryptedFile::new(header, content_ciphertext);
94
95 let output_file: EncryptionOutputFile = store_encrypted_file(&encrypted_file, output_dir)?;
96
97 let duration = start_time.elapsed();
98
99 Ok(EncryptionReport::new(
100 input_file.filename,
101 output_file.filename,
102 duration,
103 algorithm,
104 ))
105}