use crate::{
*,
cryptography::{*, hmac_sign::{Sign, SignType, Operation}},
error::{*},
core::{
KeyControlVariant,
},
};
use std::result::Result;
use rand::{RngCore, rngs::OsRng};
use hex;
use aes::cipher::{KeyIvInit, StreamCipher, generic_array::GenericArray};
pub fn generate_iv() -> [u8; 16] {
let mut iv = [0u8; 16];
OsRng.fill_bytes(&mut iv);
iv
}
type Aes256Ctr64LE = ctr::Ctr64LE<aes::Aes256>;
impl CipherAesCtr {
pub fn new(infos: CryptographicInformation, iv: Option<String>) -> Self {
let iv: Vec<u8> = match iv {
Some(iv) => hex::decode(iv).expect("An error occoured while decoding hex!"),
None => generate_iv().to_vec(),
};
CipherAesCtr { infos, sharedsecret: Vec::new(), iv }
}
pub fn get_data(&self) -> Result<Vec<u8>, CryptError> {
let data = &self.infos.content()?;
let data = data.to_vec();
Ok(data)
}
pub fn set_shared_secret(&mut self, sharedsecret: Vec<u8>) -> &Self {
self.sharedsecret = sharedsecret;
self
}
pub fn sharedsecret(&self) -> Result<&[u8], CryptError> {
Ok(&self.sharedsecret)
}
pub fn set_iv(&mut self, iv: Vec<u8>) -> &Vec<u8> {
self.iv = iv;
&self.iv
}
pub fn iv(&self) -> &Vec<u8> {
&self.iv
}
fn encryption(&self) -> Result<(Vec<u8>, Vec<u8>), CryptError> {
let plaintext = self.infos.content()?;
let passphrase = self.infos.passphrase()?.to_vec();
let key = GenericArray::from_slice(&self.sharedsecret);
let iv = GenericArray::from_slice(&self.iv);
let mut cipher = Aes256Ctr64LE::new(key, iv);
let mut hmac = Sign::new(plaintext.to_vec(), passphrase, Operation::Sign, SignType::Sha512);
let data = hmac.hmac();
let mut buf = data;
cipher.apply_keystream(&mut buf);
let iv = self.iv();
Ok((buf.to_owned(), iv.to_owned()))
}
fn decryption(&self) -> Result<(Vec<u8>, Vec<u8>), CryptError> {
let ciphertext = self.infos.content()?;
let passphrase = self.infos.passphrase()?.to_vec();
let key = GenericArray::from_slice(&self.sharedsecret);
let iv = GenericArray::from_slice(&self.iv);
let mut cipher = Aes256Ctr64LE::new(key, iv);
let mut buf = ciphertext.to_owned();
cipher.apply_keystream(&mut buf);
let mut hmac = Sign::new(buf.to_owned(), passphrase, Operation::Verify, SignType::Sha512);
let data = hmac.hmac();
let iv = self.iv();
Ok((data, iv.to_owned()))
}
}
impl CryptographicFunctions for CipherAesCtr {
fn encrypt(&mut self, public_key: Vec<u8>) -> Result<(Vec<u8>, Vec<u8>), CryptError> {
let key = KeyControlVariant::new(self.infos.metadata.key_type()?);
let (sharedsecret, ciphertext) = key.encap(&public_key)?;
let _ = self.set_shared_secret(sharedsecret);
let (encrypted_data, iv) = self.encryption()?;
println!("Please write down this iv: {}", hex::encode(iv));
Ok((encrypted_data, ciphertext))
}
fn decrypt(&mut self, secret_key: Vec<u8>, ciphertext: Vec<u8>) -> Result<Vec<u8>, CryptError>{
let key = KeyControlVariant::new(self.infos.metadata.key_type()?);
let sharedsecret = key.decap(&secret_key, &ciphertext)?;
let _ = self.set_shared_secret(sharedsecret);
let (decrypted_data, _iv) = self.decryption()?;
Ok(decrypted_data)
}
}