use {
crate::{
BlockCipher,
BlockDecrypt,
BlockEncrypt,
BlockMode,
Cipher,
CipherDecrypt,
CipherEncrypt,
Padding,
},
docext::docext,
std::{convert::Infallible, fmt, mem::size_of},
};
#[docext]
pub struct Cbc<Cip, Pad, Block> {
cip: Cip,
pad: Pad,
iv: Block,
}
impl<Cip, Pad, Block> Cbc<Cip, Pad, Block> {
pub fn new(cip: Cip, pad: Pad, iv: Block) -> Self {
Self { cip, pad, iv }
}
}
impl<Cip: BlockCipher, Pad: Padding> Cipher for Cbc<Cip, Pad, Cip::Block>
where
Cip::Block: for<'a> TryFrom<&'a mut [u8], Error: fmt::Debug>
+ AsRef<[u8]>
+ AsMut<[u8]>
+ IntoIterator<Item = u8>
+ Clone,
Cip::Key: Clone,
{
type Key = Cip::Key;
}
impl<Cip: BlockCipher, Pad: Padding> BlockMode for Cbc<Cip, Pad, Cip::Block>
where
Cip::Block: for<'a> TryFrom<&'a mut [u8], Error: fmt::Debug>
+ AsRef<[u8]>
+ AsMut<[u8]>
+ IntoIterator<Item = u8>
+ Clone,
Cip::Key: Clone,
{
}
impl<Enc: BlockEncrypt, Pad: Padding> CipherEncrypt for Cbc<Enc, Pad, Enc::EncryptionBlock>
where
Enc::EncryptionBlock: for<'a> TryFrom<&'a mut [u8], Error: fmt::Debug>
+ AsRef<[u8]>
+ AsMut<[u8]>
+ IntoIterator<Item = u8>
+ Clone,
Enc::EncryptionKey: Clone,
{
type EncryptionErr = Infallible;
type EncryptionKey = Enc::EncryptionKey;
fn encrypt(
&self,
data: Vec<u8>,
key: Self::EncryptionKey,
) -> Result<Vec<u8>, Self::EncryptionErr> {
let block_size = size_of::<Enc::EncryptionBlock>();
let mut prev = self.iv.clone();
let mut data = self.pad.pad(data, block_size);
for chunk in data.chunks_mut(block_size) {
let mut block: Enc::EncryptionBlock = chunk.try_into().unwrap();
block
.as_mut()
.iter_mut()
.zip(prev.into_iter())
.for_each(|(a, b)| *a ^= b);
let ciphertext = self.cip.encrypt(block, key.clone());
chunk.copy_from_slice(ciphertext.as_ref());
prev = ciphertext;
}
Ok(data)
}
}
impl<Dec: BlockDecrypt, Pad: Padding> CipherDecrypt for Cbc<Dec, Pad, Dec::DecryptionBlock>
where
Dec::DecryptionBlock: for<'a> TryFrom<&'a mut [u8], Error: fmt::Debug>
+ AsRef<[u8]>
+ AsMut<[u8]>
+ IntoIterator<Item = u8>
+ Clone,
Dec::DecryptionKey: Clone,
{
type DecryptionErr = Pad::Err;
type DecryptionKey = Dec::DecryptionKey;
fn decrypt(
&self,
mut data: Vec<u8>,
key: Self::DecryptionKey,
) -> Result<Vec<u8>, Self::DecryptionErr> {
let block_size = size_of::<Dec::DecryptionBlock>();
let mut prev = self.iv.clone();
for chunk in data.chunks_mut(block_size) {
let block: Dec::DecryptionBlock = chunk.try_into().unwrap();
let mut plaintext = self.cip.decrypt(block.clone(), key.clone());
plaintext
.as_mut()
.iter_mut()
.zip(prev.into_iter())
.for_each(|(a, b): (&mut u8, _)| *a ^= b);
chunk.copy_from_slice(plaintext.as_ref());
prev = block;
}
self.pad.unpad(data, block_size)
}
}