use crate::error::{Error, Result};
use crate::operation::{Operation, WithAssociatedData, WithNonce, WithData};
use std::marker::PhantomData;
pub trait AeadOperation {
type Key: AsRef<[u8]>;
type Nonce: AsRef<[u8]>;
const TAG_SIZE: usize;
fn algorithm_name() -> &'static str;
}
pub struct AeadEncryptOperation<'a, T: AeadOperation> {
key: &'a T::Key,
nonce: Option<&'a T::Nonce>,
aad: Option<&'a [u8]>,
plaintext: Option<&'a [u8]>,
_phantom: PhantomData<T>,
}
impl<'a, T: AeadOperation> AeadEncryptOperation<'a, T> {
pub fn new(key: &'a T::Key) -> Self {
Self {
key,
nonce: None,
aad: None,
plaintext: None,
_phantom: PhantomData,
}
}
pub fn encrypt(self) -> Result<Vec<u8>> {
let nonce = self.nonce.ok_or_else(||
Error::InvalidParameter("Nonce is required for AEAD encryption")
)?;
let plaintext = self.plaintext.ok_or_else(||
Error::InvalidParameter("Plaintext is required for AEAD encryption")
)?;
Err(Error::NotImplemented("AEAD encryption implementation"))
}
}
impl<'a, T: AeadOperation> Operation<Vec<u8>> for AeadEncryptOperation<'a, T> {
fn execute(self) -> Result<Vec<u8>> {
self.encrypt()
}
fn reset(&mut self) {
self.nonce = None;
self.aad = None;
self.plaintext = None;
}
}
impl<'a, T: AeadOperation> WithNonce<'a, T::Nonce, Self> for AeadEncryptOperation<'a, T> {
fn with_nonce(mut self, nonce: &'a T::Nonce) -> Self {
self.nonce = Some(nonce);
self
}
}
impl<'a, T: AeadOperation> WithAssociatedData<'a, Self> for AeadEncryptOperation<'a, T> {
fn with_associated_data(mut self, aad: &'a [u8]) -> Self {
self.aad = Some(aad);
self
}
}
impl<'a, T: AeadOperation> WithData<'a, Self> for AeadEncryptOperation<'a, T> {
fn with_data(mut self, data: &'a [u8]) -> Self {
self.plaintext = Some(data);
self
}
}
pub struct AeadDecryptOperation<'a, T: AeadOperation> {
key: &'a T::Key,
nonce: Option<&'a T::Nonce>,
aad: Option<&'a [u8]>,
ciphertext: Option<&'a [u8]>,
_phantom: PhantomData<T>,
}
impl<'a, T: AeadOperation> AeadDecryptOperation<'a, T> {
pub fn new(key: &'a T::Key) -> Self {
Self {
key,
nonce: None,
aad: None,
ciphertext: None,
_phantom: PhantomData,
}
}
pub fn decrypt(self) -> Result<Vec<u8>> {
let nonce = self.nonce.ok_or_else(||
Error::InvalidParameter("Nonce is required for AEAD decryption")
)?;
let ciphertext = self.ciphertext.ok_or_else(||
Error::InvalidParameter("Ciphertext is required for AEAD decryption")
)?;
if ciphertext.len() < T::TAG_SIZE {
return Err(Error::InvalidLength {
context: "AEAD ciphertext",
needed: T::TAG_SIZE,
got: ciphertext.len(),
});
}
Err(Error::NotImplemented("AEAD decryption implementation"))
}
}
impl<'a, T: AeadOperation> Operation<Vec<u8>> for AeadDecryptOperation<'a, T> {
fn execute(self) -> Result<Vec<u8>> {
self.decrypt()
}
fn reset(&mut self) {
self.nonce = None;
self.aad = None;
self.ciphertext = None;
}
}
impl<'a, T: AeadOperation> WithNonce<'a, T::Nonce, Self> for AeadDecryptOperation<'a, T> {
fn with_nonce(mut self, nonce: &'a T::Nonce) -> Self {
self.nonce = Some(nonce);
self
}
}
impl<'a, T: AeadOperation> WithAssociatedData<'a, Self> for AeadDecryptOperation<'a, T> {
fn with_associated_data(mut self, aad: &'a [u8]) -> Self {
self.aad = Some(aad);
self
}
}
impl<'a, T: AeadOperation> WithData<'a, Self> for AeadDecryptOperation<'a, T> {
fn with_data(mut self, data: &'a [u8]) -> Self {
self.ciphertext = Some(data);
self
}
}