primitives/transcripts/
merlin.rs1use hybrid_array::Array;
2pub use merlin::Transcript as MerlinTranscript;
3use rand::SeedableRng;
4use rand_chacha::ChaCha12Rng as ChachaRng;
5use typenum::Unsigned;
6
7use super::Transcript;
8use crate::{constants::CollisionResistanceBytes, hashing::flatten_slices, types::SessionId};
9
10impl Transcript for MerlinTranscript {
11 type Rng = merlin::TranscriptRng;
12
13 fn new(label: &'static [u8]) -> Self {
14 merlin::Transcript::new(label)
15 }
16
17 fn new_with_session_id(label: &'static [u8], session_id: &SessionId) -> Self {
18 let mut t = merlin::Transcript::new(label);
19 t.append_message(b"session_id", session_id.as_ref());
20 t
21 }
22
23 fn append<T: AsRef<[u8]>>(&mut self, label: &'static [u8], message: &T) {
24 self.append_message(label, message.as_ref());
25 }
26
27 fn append_many<T: AsRef<[u8]>>(&mut self, label: &'static [u8], values: &[T]) {
28 let concatenated = flatten_slices(values);
29 self.append_message(label, &concatenated);
30 }
31
32 fn extract<T: AsMut<[u8]>>(&mut self, label: &'static [u8], dest: &mut T) {
33 self.challenge_bytes(label, dest.as_mut());
34 }
35
36 fn derive_rng(&mut self, label: &'static [u8]) -> Self::Rng {
37 let mut seed: Array<u8, CollisionResistanceBytes> =
38 Array([0u8; CollisionResistanceBytes::USIZE]);
39 self.extract(label, &mut seed);
40 self.build_rng()
41 .finalize(&mut ChachaRng::from_seed(seed.into()))
42 }
43}