ncrypt_me/
decrypt.rs

1use super::{
2   EncryptedInfo, credentials::Credentials, encrypt::*, error::Error,
3   extract_encrypted_info_and_data,
4};
5use bincode::{config::standard, decode_from_slice};
6use chacha20poly1305::aead::{Aead, Payload, generic_array::GenericArray};
7use secure_types::SecureBytes;
8use zeroize::Zeroize;
9
10/// Decrypts the data using the provided credentials
11///
12/// ### Arguments
13///
14/// - `data` - The data to decrypt
15/// - `credentials` - The credentials to use for decryption
16pub fn decrypt_data(data: Vec<u8>, credentials: Credentials) -> Result<SecureBytes, Error> {
17   // Verify Header
18   if &data[0..8] != HEADER {
19      return Err(Error::InvalidFileFormat);
20   }
21
22   let (encrypted_info, encrypted_data) = extract_encrypted_info_and_data(&data)?;
23
24   let info: (EncryptedInfo, usize) = decode_from_slice(&encrypted_info, standard())
25      .map_err(|e| Error::DecodingFailed(e.to_string()))?;
26
27   let decrypted_data = decrypt(credentials, info.0, encrypted_data)?;
28   Ok(decrypted_data)
29}
30
31fn decrypt(
32   credentials: Credentials,
33   info: EncryptedInfo,
34   data: Vec<u8>,
35) -> Result<SecureBytes, Error> {
36   credentials.is_valid()?;
37
38   let argon2 = &info.argon2;
39   let username = &credentials.username;
40   let password = &credentials.password;
41
42   let mut aad = username
43      .unlock_str(|username_str| argon2.hash_password(&username_str, info.username_salt.clone()))
44      .map_err(|e| Error::Custom(e.to_string()))?;
45
46   let password_hash = password
47      .unlock_str(|password_str| argon2.hash_password(&password_str, info.password_salt.clone()))
48      .map_err(|e| Error::Custom(e.to_string()))?;
49
50   let nonce = GenericArray::from_slice(&info.cipher_nonce);
51
52   let payload = Payload {
53      msg: data.as_ref(),
54      aad: &aad,
55   };
56
57   let cipher = xchacha20_poly_1305(password_hash);
58   let decrypted_data_res = cipher.decrypt(nonce, payload);
59   aad.zeroize();
60
61   let decrypted_data = match decrypted_data_res {
62      Ok(data) => data,
63      Err(e) => {
64         return Err(Error::DecryptionFailed(e.to_string()));
65      }
66   };
67
68   let secure_data =
69      SecureBytes::from_vec(decrypted_data).map_err(|e| Error::Custom(e.to_string()))?;
70
71   Ok(secure_data)
72}