/ src / decrypt.rs
decrypt.rs
 1  use super::{
 2     EncryptedInfo, credentials::Credentials, encrypt::*, error::Error,
 3     extract_encrypted_info_and_data,
 4  };
 5  use bincode::{config::standard, decode_from_slice};
 6  use chacha20poly1305::aead::{Aead, Payload, generic_array::GenericArray};
 7  use secure_types::SecureBytes;
 8  use 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
16  pub 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  
31  fn decrypt(
32     credentials: Credentials,
33     info: EncryptedInfo,
34     data: Vec<u8>,
35  ) -> Result<SecureBytes, Error> {
36     credentials.is_valid()?;
37  
38     let password_hash = info
39        .argon2
40        .hash_password(&credentials.password, info.password_salt.clone())?;
41  
42     let username_hash = info
43        .argon2
44        .hash_password(&credentials.username, info.username_salt.clone())?;
45  
46     let nonce = GenericArray::from_slice(&info.cipher_nonce);
47     let mut aad = username_hash.unlock_slice(|bytes| bytes.to_vec());
48  
49     let payload = Payload {
50        msg: data.as_ref(),
51        aad: &aad,
52     };
53  
54     let cipher = xchacha20_poly_1305(password_hash);
55     let decrypted_data_res = cipher.decrypt(nonce, payload);
56     aad.zeroize();
57  
58     let decrypted_data = match decrypted_data_res {
59        Ok(data) => data,
60        Err(e) => {
61           return Err(Error::DecryptionFailed(e.to_string()));
62        }
63     };
64  
65     let secure_data =
66        SecureBytes::from_vec(decrypted_data).map_err(|e| Error::Custom(e.to_string()))?;
67  
68     Ok(secure_data)
69  }