sigma_protocols/
transcript.rs

1use sha3::{
2    digest::{ExtendableOutput, Update, XofReader},
3    Shake128,
4};
5
6#[derive(Clone)]
7pub struct Transcript {
8    hasher: Shake128,
9    #[allow(dead_code)]
10    domain_separator: Vec<u8>,
11}
12
13impl Transcript {
14    pub fn new(domain_separator: &[u8]) -> Self {
15        let mut hasher = Shake128::default();
16        hasher.update(domain_separator);
17        hasher.update(&(domain_separator.len() as u64).to_le_bytes());
18
19        Self {
20            hasher,
21            domain_separator: domain_separator.to_vec(),
22        }
23    }
24
25    pub fn append_message(&mut self, label: &[u8], message: &[u8]) {
26        self.hasher.update(label);
27        self.hasher.update(&(label.len() as u64).to_le_bytes());
28        self.hasher.update(message);
29        self.hasher.update(&(message.len() as u64).to_le_bytes());
30    }
31
32    pub fn challenge_bytes(&mut self, label: &[u8], dest: &mut [u8]) {
33        self.hasher.update(label);
34        self.hasher.update(&(label.len() as u64).to_le_bytes());
35
36        let mut reader = self.hasher.clone().finalize_xof();
37        reader.read(dest);
38
39        self.hasher.update(dest);
40    }
41}
42
43#[derive(Clone)]
44pub struct DuplexSponge {
45    state: Shake128,
46}
47
48impl DuplexSponge {
49    pub fn new(initialization_vector: &[u8; 32]) -> Self {
50        let mut state = Shake128::default();
51        state.update(initialization_vector);
52        Self { state }
53    }
54
55    pub fn absorb(&mut self, data: &[u8]) {
56        self.state.update(data);
57        self.state.update(&(data.len() as u64).to_le_bytes());
58    }
59
60    pub fn squeeze(&mut self, output_len: usize) -> Vec<u8> {
61        let mut output = vec![0u8; output_len];
62        let mut reader = self.state.clone().finalize_xof();
63        reader.read(&mut output);
64
65        self.state.update(&output);
66
67        output
68    }
69
70    pub fn prover_message(&mut self, commitment: &[u8]) -> &mut Self {
71        self.absorb(b"prover");
72        self.absorb(commitment);
73        self
74    }
75
76    pub fn verifier_challenge(&mut self, challenge_len: usize) -> Vec<u8> {
77        self.absorb(b"verifier");
78        self.squeeze(challenge_len)
79    }
80}