use std::{error::Error, fmt::Display};
use crate::{zest_block::ZestBlock, zest_digest::zest_digest, zest_hash::zest4096};
#[derive(Debug)]
pub enum DecryptErr {
NoDigest, InvalidDigest
}
impl Display for DecryptErr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Ok(match self {
DecryptErr::NoDigest => write!(f, "No digest in decrypted text."),
DecryptErr::InvalidDigest => write!(f, "Invalid digest in decrypted text."),
}?)
}
}
impl Error for DecryptErr {}
pub fn zest_dec(
cipher_blocks: Vec<ZestBlock>,
key: ZestBlock,
init_ctr_dec: Option<ZestBlock>,
init_result_dgst: Option<ZestBlock>,
init_ctr_dgst: Option<ZestBlock>,
) -> Result<Vec<ZestBlock>, DecryptErr> {
let mut text_out = vec![];
let mut counter = init_ctr_dec.unwrap_or_else(ZestBlock::new);
for block in cipher_blocks.iter().take(cipher_blocks.len() - 1) {
let mut hashed_out = zest4096(key ^ counter);
hashed_out ^= *block;
counter.increment_block();
text_out.push(hashed_out);
}
if let Some(enc_digest_enc) = cipher_blocks.last() {
let cipher_stream = zest4096(key ^ counter);
let digest_enc = *enc_digest_enc ^ cipher_stream;
if digest_enc == zest_digest(text_out.clone(), init_result_dgst, init_ctr_dgst) {
return Ok(text_out);
} else {
return Err(DecryptErr::InvalidDigest);
}
} else {
return Err(DecryptErr::NoDigest);
}
}