zest4096 0.1.27

ChaCha based hash for faster, larger blocks
Documentation
use std::{error::Error, fmt::Display};

use crate::{zest_block::ZestBlock, zest_digest::zest_digest, zest_hash::zest4096};

//Can be parallelized. Keep in mind that the key,
//init_ctr_enc, init_result_dgst, and init_ctr_dgst
//should be consistent across encoding and decoding.

//The key should be unique for every single message (as a nonce in itself)
//for maximum protection.

#[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> {
    //Variables needed for decryption
    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) {
        //Generate CSPRNG data stream and extract data.
        let mut hashed_out = zest4096(key ^ counter);
        hashed_out ^= *block;
        counter.increment_block();
        text_out.push(hashed_out);
    }
    //Check if there *is* a encoded digest attached to the recieved data
    if let Some(enc_digest_enc) = cipher_blocks.last() {
        //Decrypt digest block
        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);
    }
}