use aes_siv::aead::{generic_array::GenericArray, Aead, NewAead};
use aes_siv::Aes128SivAead;
use rand::RngCore;
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)]
pub struct Encrypted {
nonce: [u8; 16],
ciphertext: Vec<u8>,
}
#[derive(Deserialize, Serialize, Debug)]
pub enum EncryptError {
PasswordSize,
EncryptionFail,
SerializeFail,
}
#[derive(Deserialize, Serialize, Debug)]
pub enum DecryptError {
PasswordSize,
DecryptFail,
DeserializeFail,
}
pub fn encrypt(password: &[u8], bytes: &[u8]) -> Result<Encrypted, EncryptError> {
let mut key: [u8; 32] = [0; 32];
if password.len() > key.len() {
return Err(EncryptError::PasswordSize);
};
for (i, k) in password.iter().enumerate() {
if i >= key.len() {
break;
} else {
key[i] = *k;
}
}
let key = GenericArray::from_slice(&key);
let mut rng = rand::thread_rng();
let mut nonce: [u8; 16] = [0; 16];
rng.fill_bytes(&mut nonce);
let noncearray = GenericArray::from_slice(&nonce);
let cipher = Aes128SivAead::new(key);
let ciphertext = cipher
.encrypt(noncearray, bytes)
.map_err(|_e| EncryptError::EncryptionFail)?;
Ok(Encrypted { nonce, ciphertext })
}
pub fn encrypt_and_serialize(password: &[u8], bytes: &[u8]) -> Result<Vec<u8>, EncryptError> {
let encrypted = encrypt(password, bytes)?;
bincode::serialize(&encrypted).map_err(|_e| EncryptError::SerializeFail)
}
pub fn decrypt(password: &[u8], encrypted: &Encrypted) -> Result<Vec<u8>, DecryptError> {
let mut key: [u8; 32] = [0; 32];
if password.len() > key.len() {
return Err(DecryptError::PasswordSize);
};
for (i, k) in password.iter().enumerate() {
if i >= key.len() {
break;
} else {
key[i] = *k;
}
}
let key = GenericArray::from_slice(&key);
let cipher = Aes128SivAead::new(key);
let noncearray = GenericArray::from_slice(&encrypted.nonce);
let bytes = cipher
.decrypt(noncearray, encrypted.ciphertext.as_ref())
.map_err(|_e| DecryptError::DecryptFail)?;
Ok(bytes)
}
pub fn deserialize_and_decrypt(
password: &[u8],
serialized: &[u8],
) -> Result<Vec<u8>, DecryptError> {
let deser: Encrypted =
bincode::deserialize(&serialized).map_err(|_e| DecryptError::DeserializeFail)?;
let plain = decrypt(&password[..], &deser).map_err(|_e| DecryptError::DecryptFail)?;
Ok(plain)
}