1use super::{
2 EncryptedInfo, credentials::Credentials, encrypt::*, error::Error,
3 extract_encrypted_info_and_data,
4};
5use chacha20poly1305::aead::{Aead, Payload, generic_array::GenericArray};
6use secure_types::SecureBytes;
7use zeroize::Zeroize;
8
9pub fn decrypt_data(data: Vec<u8>, credentials: Credentials) -> Result<SecureBytes, Error> {
16 let (_, encrypted_data) = extract_encrypted_info_and_data(&data)?;
17
18 let info = EncryptedInfo::from_encrypted_data(&data)?;
19
20 let decrypted_data = decrypt(credentials, info, encrypted_data)?;
21 let secure_data =
22 SecureBytes::from_vec(decrypted_data).map_err(|e| Error::Custom(e.to_string()))?;
23
24 Ok(secure_data)
25}
26
27pub fn decrypt_data_unsecured(data: Vec<u8>, credentials: Credentials) -> Result<Vec<u8>, Error> {
38 let (_, encrypted_data) = extract_encrypted_info_and_data(&data)?;
39
40 let info = EncryptedInfo::from_encrypted_data(&data)?;
41
42 let decrypted_data = decrypt(credentials, info, encrypted_data)?;
43 Ok(decrypted_data)
44}
45
46fn decrypt(credentials: Credentials, info: EncryptedInfo, data: Vec<u8>) -> Result<Vec<u8>, Error> {
47 credentials.is_valid()?;
48
49 let argon2 = &info.argon2;
50 let username = &credentials.username;
51 let password = &credentials.password;
52
53 let mut aad = username
54 .unlock_str(|username_str| argon2.hash_password(&username_str, info.username_salt.clone()))
55 .map_err(|e| Error::Custom(e.to_string()))?;
56
57 let password_hash = password
58 .unlock_str(|password_str| argon2.hash_password(&password_str, info.password_salt.clone()))
59 .map_err(|e| Error::Custom(e.to_string()))?;
60
61 let nonce = GenericArray::from_slice(&info.cipher_nonce);
62
63 let payload = Payload {
64 msg: data.as_ref(),
65 aad: &aad,
66 };
67
68 let cipher = xchacha20_poly_1305(password_hash);
69 let decrypted_data_res = cipher.decrypt(nonce, payload);
70 aad.zeroize();
71
72 let decrypted_data = match decrypted_data_res {
73 Ok(data) => data,
74 Err(e) => {
75 return Err(Error::DecryptionFailed(e.to_string()));
76 }
77 };
78
79 Ok(decrypted_data)
80}