file_encrypt/encryption_algos/
chacha20_poly.rs1use anyhow::{anyhow, Result};
2use argon2::PasswordHash;
3use base64::prelude::*;
4use chacha20poly1305::{
5 aead::{Aead, AeadCore},
6 ChaCha20Poly1305, Key, KeyInit, Nonce,
7};
8use rand_core::OsRng;
9use std::{ffi::OsString, fs, path::PathBuf};
10
11use crate::hash_algos::argon_hash;
12
13pub fn encrypt_file(
14 file_path: String,
15 passphrase: String,
16 output_file: String,
17) -> Result<(OsString, String)> {
18 let argon_pch: String = argon_hash::hash_passphrase(passphrase);
20 let hash = PasswordHash::new(&argon_pch).unwrap();
21 let hash = match hash.hash {
22 Some(hash) => hash.to_string(),
23 None => {
24 eprintln!("[-] Error with argon2 hash");
25 return Err(anyhow!("Unable to get hash from Argon2 PCH"));
26 }
27 };
28
29 let hash = BASE64_STANDARD_NO_PAD.decode(hash)?;
31
32 let key = Key::from_slice(&hash);
34 let nonce = ChaCha20Poly1305::generate_nonce(&mut OsRng);
35 let cipher = ChaCha20Poly1305::new(&key);
36
37 let file_data = fs::read(file_path.clone())?;
38 let mut enc_data = match cipher.encrypt(&nonce, file_data.as_ref()) {
39 Ok(enc_data) => enc_data,
40 Err(e) => {
41 let e = e.to_string();
42 return Err(anyhow!("Unable to encrypt data: {e}"));
43 }
44 };
45
46 let mut nonce_and_data = nonce.to_vec();
47 nonce_and_data.append(&mut enc_data);
48
49 let new_file = PathBuf::from(output_file);
50 fs::write(new_file.clone(), nonce_and_data)?;
51
52 Ok((new_file.into(), argon_pch))
53}
54
55pub fn decrypt_file(
56 file_path: String,
57 passphrase: String,
58 expected_pch: String,
59 output_file: String,
60) -> Result<()> {
61 let (res, hash_opt) = argon_hash::check_hash(passphrase, expected_pch);
62 if res == false {
63 eprintln!("[-] Invalid passphrase provided");
64 return Err(anyhow!("Invalid passphrase"));
65 }
66
67 let hash = hash_opt.unwrap();
68 let hash = PasswordHash::new(&hash).unwrap();
69 let hash = hash.hash.unwrap().to_string();
70
71 let hash = BASE64_STANDARD_NO_PAD.decode(hash)?;
72
73 let key = Key::from_slice(&hash);
75 let cipher = ChaCha20Poly1305::new(&key);
76
77 let mut nonce_and_data = fs::read(file_path.clone())?;
79 let data = nonce_and_data.split_off(12);
80 let nonce = nonce_and_data;
81 let nonce = Nonce::from_slice(&nonce);
82
83 let plain_data = match cipher.decrypt(nonce, data.as_ref()) {
84 Ok(data) => data,
85 Err(e) => {
86 let e = e.to_string();
87 return Err(anyhow!("Unable to decrypt file: {e}"));
88 }
89 };
90
91 let new_file = PathBuf::from(output_file);
92
93 fs::write(new_file, plain_data)?;
94
95 Ok(())
96}