primitives/transcripts/
mod.rs1use rand::RngCore;
2use serde::Serialize;
3
4use crate::types::SessionId;
5
6pub mod folklore;
7pub mod merlin;
8
9pub use folklore::FolkloreTranscript;
10pub use merlin::MerlinTranscript;
11pub trait Transcript {
12 fn new(label: &'static [u8]) -> Self;
14 fn new_with_session_id(label: &'static [u8], session_id: &SessionId) -> Self;
15 fn append<T: AsRef<[u8]>>(&mut self, label: &'static [u8], message: &T);
16 fn append_many<T: AsRef<[u8]>>(&mut self, label: &'static [u8], values: &[T]);
17 fn extract<T: AsMut<[u8]>>(&mut self, label: &'static [u8], dest: &mut T);
18
19 fn append_serializable<T: Serialize>(&mut self, label: &'static [u8], value: &T) {
21 let serialized = bincode::serialize(value).unwrap();
22 self.append(label, &serialized);
23 }
24}
25
26pub trait TranscriptRng {
27 type Rng: RngCore;
28 fn derive_rng(&mut self, label: &'static [u8]) -> Self::Rng;
29}
30
31#[cfg(test)]
32mod tests {
33 use rand::RngCore;
34
35 use super::{Transcript, TranscriptRng};
36
37 pub fn test_happypath_same_transcripts_yield_same_extracts<T: Transcript + TranscriptRng>() {
40 let message = b"hello world";
41
42 let mut t1 = T::new(b"my_protocol");
43 let mut t2 = T::new(b"my_protocol");
44
45 t1.append(b"message_1", &message);
46 t2.append(b"message_1", &message);
47
48 let mut dest1 = [0u8; 32];
49 let mut dest2 = [0u8; 32];
50
51 t1.extract(b"value_1", &mut dest1);
52 t2.extract(b"value_1", &mut dest2);
53
54 assert_eq!(dest1, dest2);
55
56 let mut rng1 = t1.derive_rng(b"stream");
57 let mut rng2 = t2.derive_rng(b"stream");
58
59 let mut bytes1 = [0u8; 100];
60 let mut bytes2 = [0u8; 100];
61
62 rng1.fill_bytes(&mut bytes1);
63 rng2.fill_bytes(&mut bytes2);
64
65 assert_eq!(bytes1, bytes2);
66 }
67
68 pub fn test_unhappypath_different_transcripts_yield_different_extracts<
71 T: Transcript + TranscriptRng,
72 >() {
73 let message = b"hello world";
75
76 let mut t1 = T::new(b"protocol1");
77 let mut t2 = T::new(b"protocol2");
78
79 t1.append(b"message_1", &message);
80 t2.append(b"message_1", &message);
81
82 let mut dest1 = [0u8; 32];
83 let mut dest2 = [0u8; 32];
84
85 t1.extract(b"value_1", &mut dest1);
86 t2.extract(b"value_1", &mut dest2);
87
88 assert_ne!(dest1, dest2);
89
90 let mut rng1 = t1.derive_rng(b"stream");
91 let mut rng2 = t2.derive_rng(b"stream");
92
93 let mut bytes1 = [0u8; 100];
94 let mut bytes2 = [0u8; 100];
95
96 rng1.fill_bytes(&mut bytes1);
97 rng2.fill_bytes(&mut bytes2);
98
99 assert_ne!(bytes1, bytes2);
100
101 let mut t1 = T::new(b"protocol");
103 let mut t2 = T::new(b"protocol");
104
105 let message1 = b"hello world";
106 let message2 = b"goodbye world";
107
108 t1.append(b"message_1", &message1);
109 t1.append(b"message_2", &message2);
110 t2.append(b"message_2", &message2);
111 t2.append(b"message_1", &message1);
112
113 let mut dest1 = [0u8; 32];
114 let mut dest2 = [0u8; 32];
115
116 t1.extract(b"value_1", &mut dest1);
117 t2.extract(b"value_1", &mut dest2);
118
119 assert_ne!(dest1, dest2);
120
121 let mut rng1 = t1.derive_rng(b"stream");
122 let mut rng2 = t2.derive_rng(b"stream");
123
124 let mut bytes1 = [0u8; 100];
125 let mut bytes2 = [0u8; 100];
126
127 rng1.fill_bytes(&mut bytes1);
128 rng2.fill_bytes(&mut bytes2);
129
130 assert_ne!(bytes1, bytes2);
131 }
132
133 #[test]
134 fn test_folklore_transcript() {
135 test_happypath_same_transcripts_yield_same_extracts::<super::folklore::FolkloreTranscript>(
136 );
137 test_unhappypath_different_transcripts_yield_different_extracts::<
138 super::folklore::FolkloreTranscript,
139 >();
140 }
141
142 #[test]
143 fn test_merlin_transcript() {
144 test_happypath_same_transcripts_yield_same_extracts::<super::merlin::MerlinTranscript>();
145 test_unhappypath_different_transcripts_yield_different_extracts::<
146 super::merlin::MerlinTranscript,
147 >();
148 }
149}