1use super::{PBKDF2_ITERS, SALT_BYTES};
4use aes::{
5 cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit},
6 Aes256,
7};
8use anyhow::{anyhow, Result};
9use pbkdf2::pbkdf2_hmac_array;
10use rand_core::{OsRng, RngCore};
11use sha2::Sha512;
12
13fn pad_zeroes<const N: usize>(arr: &[u8]) -> [u8; N] {
14 let mut ret = [0; N];
15 ret[..arr.len()].copy_from_slice(&arr);
16 ret
17}
18
19pub fn generate_salt() -> [u8; SALT_BYTES] {
20 let mut salt = [0u8; SALT_BYTES];
21 OsRng.fill_bytes(&mut salt);
22 salt
23}
24
25pub fn generate_key(pwd: &str, salt: &[u8]) -> [u8; 32] {
26 let hash = pbkdf2_hmac_array::<Sha512, 20>(pwd.as_bytes(), salt, PBKDF2_ITERS);
27 pad_zeroes(&hash)
28}
29
30pub fn encrypt_data(key: [u8; 32], data: &[u8]) -> Result<Vec<u8>> {
31 let mut output = Vec::with_capacity(data.len());
32 let mut block = GenericArray::from([0u8; 16]);
33 let cipher =
34 Aes256::new_from_slice(&key).map_err(|e| anyhow!("Failed to create AES cipher: {}", e))?;
35
36 let mut handle_chunk = |chunk: &[u8]| {
37 block.copy_from_slice(chunk);
38 cipher.encrypt_block(&mut block);
39 output.extend_from_slice(&block);
40 };
41
42 let chunks = data.chunks_exact(16);
43 let remainder = chunks.remainder();
44 for block_data in chunks {
45 handle_chunk(block_data);
46 }
47 if !remainder.is_empty() {
48 let block_data = pad_zeroes::<16>(remainder);
49 handle_chunk(&block_data);
50 }
51
52 Ok(output)
53}
54
55pub fn decrypt_data(key: [u8; 32], data: &[u8]) -> Result<Vec<u8>> {
56 if data.len() % 16 != 0 {
57 return Err(anyhow!("Data length is not a multiple of 16"));
58 }
59 let mut output = Vec::with_capacity(data.len());
60 let mut block = GenericArray::from([0u8; 16]);
61 let cipher =
62 Aes256::new_from_slice(&key).map_err(|e| anyhow!("Failed to create AES cipher: {}", e))?;
63
64 let mut handle_chunk = |chunk: &[u8]| {
65 block.copy_from_slice(chunk);
66 cipher.decrypt_block(&mut block);
67 output.extend_from_slice(&block);
68 };
69
70 let chunks = data.chunks_exact(16);
71 for block_data in chunks {
72 handle_chunk(block_data);
73 }
74
75 Ok(output)
76}
77
78pub fn encrypt_data_formatted(pwd: &str, salt: &[u8], data: &[u8]) -> Result<Vec<u8>> {
79 let mut input = Vec::with_capacity(SALT_BYTES + data.len());
80 let mut output = Vec::with_capacity(SALT_BYTES + data.len());
81 input.extend_from_slice(&(data.len() as u64).to_le_bytes());
82 input.extend_from_slice(data);
83 output.extend_from_slice(salt);
84 let key = generate_key(pwd, salt);
85 let encrypted_data = encrypt_data(key, &input)?;
86 output.extend_from_slice(&encrypted_data);
87 Ok(output)
88}
89
90pub fn decrypt_data_formatted(pwd: &str, data: &[u8]) -> Result<Vec<u8>> {
91 if data.len() < SALT_BYTES {
92 return Err(anyhow!("Data is too short"));
93 }
94 let salt = &data[..SALT_BYTES];
95 let key = generate_key(pwd, salt);
96 let decrypted_data = decrypt_data(key, &data[SALT_BYTES..])?;
97 let len_bytes = &decrypted_data[..8];
98 let len = u64::from_le_bytes(len_bytes.try_into()?) as usize;
99 Ok(decrypted_data[8..8 + len].to_vec())
100}