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