sigma-protocols 0.5.1

SIGMA zero-knowledge proof protocols
Documentation
use sha3::{
    digest::{ExtendableOutput, Update, XofReader},
    Shake128,
};

#[derive(Clone)]
pub struct Transcript {
    hasher: Shake128,
    #[allow(dead_code)]
    domain_separator: Vec<u8>,
}

impl Transcript {
    pub fn new(domain_separator: &[u8]) -> Self {
        let mut hasher = Shake128::default();
        hasher.update(domain_separator);
        hasher.update(&(domain_separator.len() as u64).to_le_bytes());

        Self {
            hasher,
            domain_separator: domain_separator.to_vec(),
        }
    }

    pub fn append_message(&mut self, label: &[u8], message: &[u8]) {
        self.hasher.update(label);
        self.hasher.update(&(label.len() as u64).to_le_bytes());
        self.hasher.update(message);
        self.hasher.update(&(message.len() as u64).to_le_bytes());
    }

    pub fn challenge_bytes(&mut self, label: &[u8], dest: &mut [u8]) {
        self.hasher.update(label);
        self.hasher.update(&(label.len() as u64).to_le_bytes());

        let mut reader = self.hasher.clone().finalize_xof();
        reader.read(dest);

        self.hasher.update(dest);
    }
}

#[derive(Clone)]
pub struct DuplexSponge {
    state: Shake128,
}

impl DuplexSponge {
    pub fn new(initialization_vector: &[u8; 32]) -> Self {
        let mut state = Shake128::default();
        state.update(initialization_vector);
        Self { state }
    }

    pub fn absorb(&mut self, data: &[u8]) {
        self.state.update(data);
        self.state.update(&(data.len() as u64).to_le_bytes());
    }

    pub fn squeeze(&mut self, output_len: usize) -> Vec<u8> {
        let mut output = vec![0u8; output_len];
        let mut reader = self.state.clone().finalize_xof();
        reader.read(&mut output);

        self.state.update(&output);

        output
    }

    pub fn prover_message(&mut self, commitment: &[u8]) -> &mut Self {
        self.absorb(b"prover");
        self.absorb(commitment);
        self
    }

    pub fn verifier_challenge(&mut self, challenge_len: usize) -> Vec<u8> {
        self.absorb(b"verifier");
        self.squeeze(challenge_len)
    }
}