pub mod algorithm;
pub use secured_cipher_key::{random_bytes, Key, KeyDerivationStrategy};
pub use algorithm::{
AEADAlgorithm, AlgorithmKeyIVInit, AlgorithmKeyInit, AlgorithmProcess, AlgorithmProcessInPlace,
ChaCha20, EncryptionAlgorithm, Poly1305, SignedEnvelope,
};
use std::error::Error;
pub struct Cipher {
encryption: Box<dyn EncryptionAlgorithm>,
aead: Box<dyn AEADAlgorithm>,
}
pub enum CipherMode {
ChaCha20Poly1305,
Custom(Box<dyn EncryptionAlgorithm>, Box<dyn AEADAlgorithm>),
}
impl Cipher {
pub fn new(mode: CipherMode) -> Self {
let (encryption, aead): (Box<dyn EncryptionAlgorithm>, Box<dyn AEADAlgorithm>) = match mode {
CipherMode::ChaCha20Poly1305 => (Box::new(ChaCha20::new()), Box::new(Poly1305::new())),
CipherMode::Custom(encryption, aead) => (encryption, aead),
};
Self { encryption, aead }
}
pub fn init(&mut self, key: &[u8], iv: &[u8]) -> &mut Self {
self.encryption.init(key, iv);
self.aead.init(&self.encryption.process(&[0; 64]));
self
}
pub fn encrypt(&mut self, data: &[u8]) -> Vec<u8> {
self.encryption.process(data)
}
pub fn sign(&mut self, header: &[u8], data: &[u8]) -> SignedEnvelope {
let mac = self
.aead
.process(&[header.to_vec(), data.to_vec()].concat());
SignedEnvelope {
header: header.to_vec(),
data: data.into(),
mac,
}
}
pub fn decrypt(&mut self, data: &[u8]) -> Vec<u8> {
self.encryption.process(data)
}
pub fn decrypt_and_verify(&mut self, envelope: &SignedEnvelope) -> Result<Vec<u8>, CipherError> {
if envelope.mac
!= self
.aead
.process(&[envelope.header.clone(), envelope.data.clone()].concat())
{
return Err(CipherError::AuthenticationFailed);
}
Ok(self.encryption.process(&envelope.data))
}
}
impl Default for Cipher {
fn default() -> Self {
Self::new(CipherMode::ChaCha20Poly1305)
}
}
#[derive(Debug)]
pub enum CipherError {
AuthenticationFailed,
}
impl Error for CipherError {}
impl std::fmt::Display for CipherError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
CipherError::AuthenticationFailed => write!(f, "Authentication failed"),
}
}
}