pants_store/
secure.rs

1use std::{error::Error, marker::PhantomData};
2
3use aes_gcm::{
4    aead::{generic_array::GenericArray, Aead, OsRng},
5    AeadCore, Aes256Gcm, Key, KeyInit,
6};
7use argon2::{password_hash::SaltString, Argon2};
8use serde::{Deserialize, Serialize};
9
10use crate::errors::{DecryptionError, EncryptionError};
11
12#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
13pub struct Encrypted<Data> {
14    nonce: Vec<u8>,
15    data: Vec<u8>,
16    #[serde(skip)]
17    data_type: PhantomData<Data>,
18}
19// needed to work around lifetimes :/
20pub struct Decrypted<Data> {
21    data: Vec<u8>,
22    data_type: PhantomData<Data>,
23}
24
25impl<'de, Data: Deserialize<'de>> Decrypted<Data> {
26    pub fn deserialize(&'de self) -> Data {
27        bincode::deserialize(&self.data).unwrap()
28    }
29}
30
31impl<'de, Data: Serialize + Deserialize<'de>> Encrypted<Data> {
32    pub fn decrypt(&self, key: Key<Aes256Gcm>) -> Result<Decrypted<Data>, Box<dyn Error>> {
33        let cipher = Aes256Gcm::new(&key);
34        let decrypt = cipher
35            .decrypt(
36                GenericArray::from_slice(self.nonce.as_slice()),
37                self.data.as_ref(),
38            )
39            .map_err(|_| DecryptionError::Decryption)?;
40        Ok(Decrypted {
41            data: decrypt,
42            data_type: PhantomData,
43        })
44    }
45
46    pub fn encrypt(data: &Data, key: Key<Aes256Gcm>) -> Result<Encrypted<Data>, Box<dyn Error>> {
47        let cipher = Aes256Gcm::new(&key);
48        let nonce = Aes256Gcm::generate_nonce(&mut OsRng);
49        let encoded = bincode::serialize(data)?;
50        let encrypted = cipher
51            .encrypt(&nonce, encoded.as_ref())
52            .map_err(|_| EncryptionError::Encryption)?;
53        Ok(Encrypted {
54            data: encrypted,
55            nonce: nonce.to_vec(),
56            data_type: PhantomData,
57        })
58    }
59}
60
61pub trait SecureData {
62    type Item;
63    fn salt(&self) -> &str;
64    fn data(&self) -> &Encrypted<Self::Item>;
65    // not much point in this function
66    fn encrypt<'de>(
67        data: &Self::Item,
68        key: Key<Aes256Gcm>,
69    ) -> Result<Encrypted<Self::Item>, Box<dyn Error>>
70    where
71        Self::Item: Serialize + Deserialize<'de>,
72    {
73        Encrypted::encrypt(data, key)
74    }
75    fn decrypt<'de>(&self, key: Key<Aes256Gcm>) -> Result<Decrypted<Self::Item>, Box<dyn Error>>
76    where
77        Self::Item: Serialize + Deserialize<'de> + 'de,
78    {
79        Encrypted::decrypt(self.data(), key)
80    }
81    // not much point in this fuction
82    //
83    // fn deserialize<'de>(decrypted: &'de Decrypted<Self::Item>) -> Self::Item
84    // where
85    //     Self::Item: Deserialize<'de>,
86    // {
87    //     Decrypted::deserialize(decrypted)
88    // }
89    fn key(&self, password: String) -> Key<Aes256Gcm> {
90        Self::get_key(self.salt(), password)
91    }
92    fn get_key(salt: &str, password: String) -> Key<Aes256Gcm> {
93        let salt_string = SaltString::from_b64(salt).unwrap();
94        let mut salt_arr = [0u8; 64];
95        let salt_bytes = salt_string.decode_b64(&mut salt_arr).unwrap();
96
97        let mut output_key = [0u8; 32];
98        let argon2 = Argon2::default();
99        argon2
100            .hash_password_into(password.as_bytes(), salt_bytes, &mut output_key)
101            .unwrap();
102
103        output_key.into()
104    }
105}