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