primitives/transcripts/
merlin.rs

1pub use merlin::Transcript as MerlinTranscript;
2use rand::SeedableRng;
3use rand_chacha::ChaCha12Rng as ChachaRng;
4
5use super::Transcript;
6use crate::{
7    hashing::flatten_slices,
8    random::Seed,
9    types::{identifiers::ProtocolInfo, SessionId},
10};
11
12impl Transcript for MerlinTranscript {
13    type Rng = merlin::TranscriptRng;
14
15    fn new(protocol_info: &'static ProtocolInfo, session_id: &SessionId) -> Self {
16        let mut t = merlin::Transcript::new(protocol_info.name().as_bytes());
17        t.append_message(b"session_id", session_id.as_ref());
18        t
19    }
20
21    fn append_with<T: AsRef<[u8]>>(&mut self, label: &'static [u8], message: &T) {
22        self.append_message(label, message.as_ref());
23    }
24
25    fn append_many_with<T: AsRef<[u8]>>(&mut self, label: &'static [u8], values: &[T]) {
26        let concatenated = flatten_slices(values);
27        self.append_message(label, &concatenated);
28    }
29
30    fn extract(&mut self, label: &'static [u8]) -> Seed {
31        let mut seed = Seed::default();
32        self.challenge_bytes(label, seed.as_mut());
33        seed
34    }
35
36    fn derive_rng(&mut self, label: &'static [u8]) -> Self::Rng {
37        let seed = self.extract(label);
38        self.build_rng().finalize(&mut ChachaRng::from_seed(seed))
39    }
40}